opencryptoki+dfsg/0000755000175000017500000000000012656010174013277 5ustar xnoxxnoxopencryptoki+dfsg/TODO0000644000175000017500000000000012630407153013754 0ustar xnoxxnoxopencryptoki+dfsg/FAQ0000644000175000017500000001007412630407153013632 0ustar xnoxxnox openCryptoki FAQ - Kent Yoder ----------------------------------------------------------------------------- 1. Q. All openCryptoki applications are returning CKR_TOKEN_NOT_PRESENT, even though the token is there, and its STDLL is in the right place. What's the problem? A1. The user who's executing the application is probably not a member of the pkcs11 group. A2. Check that the device driver for your hardware token is loaded. (`lsmod` in Linux). A3. If you're doing development, this error will also be returned of your token's STDLL has unresolved symbols in it. Enable debugging and check the debug log to find out what symbols are undefined. 2. Q. When C_Initialize() gets called by my app, openCryptoki returns CKR_HOST_MEMORY, even though I've got lots of free memory. What's the problem? A1. CKR_HOST_MEMORY is returned also if openCryptoki cannot attach to shared memory. This can happen if: a1. The user who's executing the application is not a member of the pkcs11 group. a2. pkcsslotd is not running. 3. Q. pkcsconf is returning: Error getting token info: 0x2 This is CKR_HOST_MEMORY, see question 2. Error getting token info: 0x3 The slot ID you're providing is invalid. 4. Q. How can I get the complete debug logs from openCryptoki? A. In opencryptoki version 3.3, tracing was introduced. There is no longer a need to compile opencryptoki with debug enabled via "configure --enable-debug" to debug problems. Trace messages are enabled via the environment variable, OPENCRYPTOKI_TRACE_LEVEL=. Set this environment variable to one of several trace levels available: 1 - log error messages 2 - log warning messages 3 - log informational messages 4 - log development debug messages; these messages may help debug while developing pkcs#11 applications. 5 - debug messages that are useful to opencryptoki developers; this level must be enabled via --enable-debug option in the configure script. Note: Trace messages increase as the trace level increases. In other words, trace level 4 includes all the messages from trace levels 1, 2 and 3. An additional level 5 is included for those implementing new features into opencryptoki source code. This level 5 allows for more debug output. Level 5 is enabled when compiling opencryptoki source code using "configure --enable-debug" and exporting OPENCRYPTOKI_TRACE_LEVEL=5. All trace output is logged into trace. file in the /var/log/opencryptoki directory. A trace file is created per process. Prior to opencryptoki version 3.3, opencryptoki had to be compiled with debugging enabled, i.e configure --enable-debug. Debug messages were then logged to the file specified with the OPENCRYPTOKI_DEBUG_FILE environment variable. If the environment variable was not set, then opencryptoki debug messages were not logged. Debugging does not have to be enabled for syslog messages to be logged. Syslog messages are logged according to the system's syslog configuration. For versions of openCryptoki starting with openCryptoki-2.0 and before openCryptoki-2.4, define the environment variable PKCS11_API_LOG_DEBUG=1 (in versions of openCryptoki before 2.0, define AIX_PKCS11_API_LOG_DEBUG=1). Also, apparently by default syslogd does not have an entry in /etc/syslogd.conf for debug messages, so even if you have debug messages enabled in your openCryptoki compile, you'll not get them in the system log until you edit /etc/syslogd.conf and restart syslogd. Add an entry in /etc/syslogd.conf such as: # vi /etc/syslogd.conf --- [...] *.debug /var/log/debuglog --- # killall -HUP syslogd Now, when openCryptoki is configured with the --enable-debug option (or if you install the -debug rpms), /var/log/debuglog will receive its debugging messages. ----------------------------------------------------------------------------- openCryptoki FAQ opencryptoki+dfsg/COPYING0000644000175000017500000003553112630407153014340 0ustar xnoxxnox Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. opencryptoki+dfsg/rpm/0000755000175000017500000000000012630407153014074 5ustar xnoxxnoxopencryptoki+dfsg/rpm/opencryptoki.spec0000644000175000017500000001737212630407153017510 0ustar xnoxxnoxName: opencryptoki Summary: Implementation of the PKCS#11 (Cryptoki) specification v2.11 Version: 2.3.3 Release: 1%{?dist} License: CPL Group: System Environment/Base URL: http://sourceforge.net/projects/opencryptoki Source: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) Requires(pre): shadow-utils coreutils sed Requires(post): chkconfig Requires(preun): chkconfig # This is for /sbin/service Requires(preun): initscripts Requires(postun): initscripts BuildRequires: openssl-devel trousers-devel BuildRequires: autoconf automake libtool %ifarch s390 s390x BuildRequires: libica-devel >= 2.0 %endif Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description Opencryptoki implements the PKCS#11 specification v2.11 for a set of cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the Trusted Platform Module (TPM) chip. Opencryptoki also brings a software token implementation that can be used without any cryptographic hardware. This package contains the Slot Daemon (pkcsslotd) and general utilities. %package libs Group: System Environment/Libraries Summary: The run-time libraries for the opencryptoki package %description libs Opencryptoki implements the PKCS#11 specification v2.11 for a set of cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the Trusted Platform Module (TPM) chip. Opencryptoki also brings a software token implementation that can be used without any cryptographic hardware. This package contains the PKCS#11 library implementation, and requires at least one token implementation (packaged separately) to be fully functional. %package swtok Group: System Environment/Libraries Summary: The software token implementation for the opencryptoki package Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description swtok Opencryptoki implements the PKCS#11 specification v2.11 for a set of cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the Trusted Platform Module (TPM) chip. Opencryptoki also brings a software token implementation that can be used without any cryptographic hardware. This package brings the software token implementation to use opencryptoki without any specific cryptographic hardware. %package tpmtok Group: System Environment/Libraries Summary: Trusted Platform Module (TPM) device support for opencryptoki Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description tpmtok Opencryptoki implements the PKCS#11 specification v2.11 for a set of cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the Trusted Platform Module (TPM) chip. Opencryptoki also brings a software token implementation that can be used without any cryptographic hardware. This package brings the necessary libraries and files to support Trusted Platform Module (TPM) devices in the opencryptoki stack. %package devel Group: Development/Libraries Summary: Development files for openCryptoki Requires: %{name}-libs = %{version}-%{release} %description devel This package contains the development header files for building opencryptoki and PKCS#11 based applications %ifarch s390 s390x %package icatok Group: System Environment/Libraries Summary: ICA cryptographic devices (clear-key) support for opencryptoki Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description icatok Opencryptoki implements the PKCS#11 specification v2.11 for a set of cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the Trusted Platform Module (TPM) chip. Opencryptoki also brings a software token implementation that can be used without any cryptographic hardware. This package brings the necessary libraries and files to support ICA devices in the opencryptoki stack. ICA is an interface to IBM cryptographic hardware such as IBM 4764 or 4765 that uses the "accelerator" or "clear-key" path. %package ccatok Group: System Environment/Libraries Summary: CCA cryptographic devices (secure-key) support for opencryptoki Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description ccatok Opencryptoki implements the PKCS#11 specification v2.11 for a set of cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the Trusted Platform Module (TPM) chip. Opencryptoki also brings a software token implementation that can be used without any cryptographic hardware. This package brings the necessary libraries and files to support CCA devices in the opencryptoki stack. CCA is an interface to IBM cryptographic hardware such as IBM 4764 or 4765 that uses the "co-processor" or "secure-key" path. %endif %prep %setup -q %build ./bootstrap.sh %ifarch s390 s390x %configure --enable-icatok --enable-ccatok %else %configure --disable-icatok --disable-ccatok %endif make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT rm -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/*.la rm -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/stdll/*.la %clean rm -rf $RPM_BUILD_ROOT %preun if [ "$1" = "0" ]; then /sbin/service pkcsslotd stop /dev/null 2>&1 /sbin/chkconfig --del pkcsslotd fi %postun if [ "$1" -ge "1" ] ; then /sbin/service pkcsslotd condrestart >/dev/null 2>&1 fi exit 0 %postun libs -p /sbin/ldconfig %postun swtok -p /sbin/ldconfig %postun tpmtok -p /sbin/ldconfig %ifarch s390 s390x %postun icatok -p /sbin/ldconfig %postun ccatok -p /sbin/ldconfig %endif %post /sbin/chkconfig --add pkcsslotd exit 0 %post libs -p /sbin/ldconfig %post swtok -p /sbin/ldconfig %post tpmtok -p /sbin/ldconfig %ifarch s390 s390x %post icatok -p /sbin/ldconfig %post ccatok -p /sbin/ldconfig %endif %pre # Create pkcs11 group getent group pkcs11 >/dev/null || groupadd -r pkcs11 # Add root to the pkcs11 group gpasswd -a root pkcs11 %files %defattr(-,root,root,-) %doc FAQ README LICENSE doc/README.token_data %doc doc/openCryptoki-HOWTO.pdf %{_mandir}/man*/* %{_initddir}/pkcsslotd %{_sbindir}/* %{_libdir}/opencryptoki/methods %{_libdir}/pkcs11/methods %dir %attr(770,root,pkcs11) %{_localstatedir}/lib/opencryptoki %files libs %defattr(-,root,root,-) %{_sysconfdir}/ld.so.conf.d/* # Unversioned .so symlinks usually belong to -devel packages, but opencryptoki # needs them in the main package, because: # pkcs11_startup looks for opencryptoki/stdll/*.so, and # documentation suggests that programs should dlopen "PKCS11_API.so". %dir %attr(755, root, root) %{_libdir}/opencryptoki %{_libdir}/opencryptoki/libopencryptoki.* %{_libdir}/opencryptoki/PKCS11_API.so %dir %attr(755, root, root) %{_libdir}/opencryptoki/stdll %dir %attr(755, root, root) %{_libdir}/pkcs11 %{_libdir}/pkcs11/libopencryptoki.so %{_libdir}/pkcs11/PKCS11_API.so %{_libdir}/pkcs11/stdll %files swtok %defattr(-,root,root,-) %{_libdir}/opencryptoki/stdll/libpkcs11_sw.* %{_libdir}/opencryptoki/stdll/PKCS11_SW.so %files tpmtok %defattr(-,root,root,-) %{_libdir}/opencryptoki/stdll/libpkcs11_tpm.* %{_libdir}/opencryptoki/stdll/PKCS11_TPM.so %doc doc/README.tpm_stdll %files devel %defattr(-,root,root,-) %{_includedir}/* %ifarch s390 s390x %files icatok %defattr(-,root,root,-) %{_libdir}/opencryptoki/stdll/libpkcs11_ica.* %{_libdir}/opencryptoki/stdll/PKCS11_ICA.so %files ccatok %defattr(-,root,root,-) %{_libdir}/opencryptoki/stdll/libpkcs11_cca.* %{_libdir}/opencryptoki/stdll/PKCS11_CCA.so %doc doc/README-IBM_CCA_users %doc doc/README.cca_stdll %endif %changelog * Thu Jul 29 2010 Klaus H Kiwi 2.3.2-1 - Put STDLLs in separate packages - General spec file cleanup * Thu Aug 7 2006 Daniel H Jones - spec file cleanup * Tue Aug 1 2006 Daniel H Jones - sw token not created for s390 * Tue Jul 25 2006 Daniel H Jones - fixed post section and /var/lib/opencryptoki perms * Thu May 25 2006 Daniel H Jones 2.2.4-1 - initial file created opencryptoki+dfsg/usr/0000755000175000017500000000000012630407154014110 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/0000755000175000017500000000000012630407154014656 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/Makefile.am0000644000175000017500000000067112630407154016716 0ustar xnoxxnoxSUBDIRS = pkcs11 install-data-hook: $(MKDIR_P) $(DESTDIR)/etc/ld.so.conf.d echo "$(libdir)/opencryptoki" >\ $(DESTDIR)/etc/ld.so.conf.d/opencryptoki-$(target_cpu).conf echo "$(libdir)/opencryptoki/stdll" >>\ $(DESTDIR)/etc/ld.so.conf.d/opencryptoki-$(target_cpu).conf echo "**** Remember you must run ldconfig before using the above settings ****" uninstall-hook: rm -f $(DESTDIR)/etc/ld.so.conf.d/opencryptoki-$(target_cpu).conf opencryptoki+dfsg/usr/lib/pkcs11/0000755000175000017500000000000012630407154015760 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/cca_stdll/0000755000175000017500000000000012630407154017710 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/cca_stdll/cca_specific.c0000644000175000017500000025326112630407154022460 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * openCryptoki CCA token * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2006 * * Author: Kent E. Yoder * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "cca_stdll.h" #include "pkcs11types.h" #include "p11util.h" #include "defs.h" #include "host_defs.h" #include "tok_specific.h" #include "tok_struct.h" #include "h_extern.h" #include "csulincl.h" #include "ec_defs.h" #include "trace.h" CK_CHAR manuf[] = "IBM Corp."; CK_CHAR model[] = "IBM CCA Token"; CK_CHAR descr[] = "IBM PKCS#11 CCA Token"; CK_CHAR label[] = "IBM PKCS#11 for CCA"; #define CCASHAREDLIB "libcsulcca.so" /* mechanisms provided by this token */ MECH_LIST_ELEMENT mech_list[] = { {CKM_DES_KEY_GEN, {8, 8, CKF_HW|CKF_GENERATE}}, {CKM_DES3_KEY_GEN, {24, 24, CKF_HW|CKF_GENERATE}}, {CKM_RSA_PKCS_KEY_PAIR_GEN, {512, 4096, CKF_HW|CKF_GENERATE_KEY_PAIR}}, {CKM_RSA_PKCS, {512, 4096, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_SIGN| CKF_VERIFY}}, {CKM_MD5_RSA_PKCS, {512,4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA1_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA256_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_DES_CBC, {8, 8, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES_CBC_PAD, {8, 8, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_DES3_CBC, {24, 24, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_DES3_CBC_PAD, {24, 24, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_AES_KEY_GEN, {16, 32, CKF_HW|CKF_GENERATE}}, {CKM_AES_ECB, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_AES_CBC, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_AES_CBC_PAD, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_SHA512, {0, 0, CKF_HW|CKF_DIGEST}}, {CKM_SHA512_HMAC, {80, 2048, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA512_HMAC_GENERAL, {80, 2048, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA384, {0, 0, CKF_HW|CKF_DIGEST}}, {CKM_SHA384_HMAC, {80, 2048, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA384_HMAC_GENERAL, {80, 2048, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA256, {0, 0, CKF_HW|CKF_DIGEST}}, {CKM_SHA256_HMAC, {80, 2048, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA256_HMAC_GENERAL, {80, 2048, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA_1, {0, 0, CKF_DIGEST}}, {CKM_SHA_1_HMAC, {80, 2048, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA_1_HMAC_GENERAL, {80, 2048, CKF_SIGN|CKF_VERIFY}}, {CKM_MD5, {0, 0, CKF_DIGEST}}, {CKM_MD5_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_MD5_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_EC_KEY_PAIR_GEN, {160, 521, CKF_HW|CKF_GENERATE_KEY_PAIR| CKF_EC_NAMEDCURVE|CKF_EC_F_P}}, {CKM_ECDSA, {160, 521, CKF_HW|CKF_SIGN|CKF_VERIFY|CKF_EC_NAMEDCURVE| CKF_EC_F_P}}, {CKM_ECDSA_SHA1, {160, 521, CKF_HW|CKF_SIGN|CKF_VERIFY| CKF_EC_NAMEDCURVE|CKF_EC_F_P}}, {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW|CKF_GENERATE}} }; CK_ULONG mech_list_len = (sizeof(mech_list) / sizeof(MECH_LIST_ELEMENT)); CK_RV token_specific_rng(CK_BYTE *output, CK_ULONG bytes) { long return_code, reason_code; unsigned char form[CCA_KEYWORD_SIZE], random_number[CCA_RNG_SIZE]; CK_ULONG bytes_so_far = 0, bytes_left; CK_RV rv; memcpy(form, "RANDOM ", (size_t)CCA_KEYWORD_SIZE); while (bytes_so_far < bytes) { CSNBRNG(&return_code, &reason_code, NULL, NULL, form, random_number); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBRNG failed. return:%ld, reason:%ld\n", return_code, reason_code); rv = CKR_FUNCTION_FAILED; return rv; } if (bytes_so_far + CCA_RNG_SIZE > bytes) { bytes_left = bytes - bytes_so_far; memcpy(&output[bytes_so_far], random_number, (size_t)bytes_left); bytes_so_far += bytes_left; } else { memcpy(&output[bytes_so_far], random_number, (size_t)CCA_RNG_SIZE); bytes_so_far += CCA_RNG_SIZE; } } return CKR_OK; } CK_RV token_specific_init(CK_SLOT_ID SlotNumber, char *conf_name) { unsigned char rule_array[256] = { 0, }; long return_code, reason_code, rule_array_count, verb_data_length; void *lib_csulcca; lib_csulcca = dlopen(CCASHAREDLIB, RTLD_GLOBAL | RTLD_NOW); if (lib_csulcca == NULL) { OCK_SYSLOG(LOG_ERR, "%s: Error loading library: '%s' [%s]\n", __func__, CCASHAREDLIB, dlerror()); TRACE_ERROR("%s: Error loading shared library '%s' [%s]\n", __func__, CCASHAREDLIB, dlerror()); return CKR_FUNCTION_FAILED; } memcpy(rule_array, "STATCCAE", 8); rule_array_count = 1; verb_data_length = 0; CSUACFQ(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &verb_data_length, NULL); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSUACFQ failed. return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } /* This value should be 2 if the master key is set in the card */ if (memcmp(&rule_array[CCA_STATCCAE_SYM_CMK_OFFSET], "2 ", 8)) { OCK_SYSLOG(LOG_WARNING, "Warning: CCA symmetric master key is not yet loaded"); } if (memcmp(&rule_array[CCA_STATCCAE_ASYM_CMK_OFFSET], "2 ", 8)) { OCK_SYSLOG(LOG_WARNING, "Warning: CCA asymmetric master key is not yet loaded"); } return CKR_OK; } CK_RV token_specific_final() { return CKR_OK; } CK_RV cca_key_gen(enum cca_key_type type, CK_BYTE *key, unsigned char *key_form, unsigned char *key_type_1, CK_ULONG key_size) { long return_code, reason_code; unsigned char key_length[CCA_KEYWORD_SIZE]; unsigned char key_type_2[CCA_KEYWORD_SIZE] = { 0, }; unsigned char kek_key_identifier_1[CCA_KEY_ID_SIZE] = { 0, }; unsigned char kek_key_identifier_2[CCA_KEY_ID_SIZE] = { 0, }; unsigned char generated_key_identifier_2[CCA_KEY_ID_SIZE] = { 0, }; if (type == CCA_DES_KEY) { switch (key_size) { case 8: memcpy(key_length, "KEYLN8 ", (size_t)CCA_KEYWORD_SIZE); break; case 24: memcpy(key_length, "KEYLN24 ", (size_t)CCA_KEYWORD_SIZE); break; default: TRACE_ERROR("Invalid key length: %lu\n", key_size); return CKR_KEY_SIZE_RANGE; } } else if (type == CCA_AES_KEY) { switch (key_size) { case 16: memcpy(key_length, "KEYLN16 ", CCA_KEYWORD_SIZE); break; case 24: memcpy(key_length, "KEYLN24 ", (size_t)CCA_KEYWORD_SIZE); break; case 32: memcpy(key_length, " ", (size_t)CCA_KEYWORD_SIZE); break; default: TRACE_ERROR("Invalid key length: %lu\n", key_size); return CKR_KEY_SIZE_RANGE; } } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } CSNBKGN(&return_code, &reason_code, NULL, NULL, key_form, key_length, key_type_1, key_type_2, kek_key_identifier_1, kek_key_identifier_2, key, generated_key_identifier_2); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBKGN(KEYGEN) failed. return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } // memcpy(key, generated_key_identifier_1, (size_t)CCA_KEY_ID_SIZE); return CKR_OK; } CK_RV token_specific_des_key_gen(CK_BYTE *des_key, CK_ULONG len, CK_ULONG keysize) { unsigned char key_form[CCA_KEYWORD_SIZE]; unsigned char key_type_1[CCA_KEYWORD_SIZE]; /* make sure key is the right size for the token */ if (len != CCA_KEY_ID_SIZE) return CKR_FUNCTION_FAILED; memcpy(key_form, "OP ", (size_t)CCA_KEYWORD_SIZE); memcpy(key_type_1, "DATA ", (size_t)CCA_KEYWORD_SIZE); return cca_key_gen(CCA_DES_KEY, des_key, key_form, key_type_1, keysize); } CK_RV token_specific_des_ecb(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { TRACE_INFO("Unsupported function reached.\n"); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV token_specific_des_cbc(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { long return_code, reason_code, rule_array_count, length; long pad_character = 0; //char iv[8] = { 0xfe, 0x43, 0x12, 0xed, 0xaa, 0xbb, 0xdd, 0x90 }; unsigned char chaining_vector[CCA_OCV_SIZE]; unsigned char rule_array[CCA_RULE_ARRAY_SIZE]; CK_BYTE *local_out = out_data; CK_ATTRIBUTE *attr = NULL; if (template_attribute_find(key->template, CKA_IBM_OPAQUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the key.\n"); return CKR_FUNCTION_FAILED; } /* We need to have 8 bytes more than the in data length in case CCA * adds some padding, although this extra 8 bytes may not be needed. * If *out_data_len is not 8 bytes larger than in_data_len, then * we'll malloc the needed space and get the data back from CCA in this * malloc'd buffer. If it turns out that the extra 8 bytes wasn't * needed, we just silently copy the data to the user's buffer and * free our malloc'd space, returning as normal. If the space was * needed, we return an error and no memory corruption happens. */ if (*out_data_len < (in_data_len + 8)) { local_out = malloc(in_data_len + 8); if (!local_out) { TRACE_ERROR("Malloc of %lu bytes failed.\n", in_data_len + 8); return CKR_HOST_MEMORY; } } length = in_data_len; rule_array_count = 1; memcpy(rule_array, "CBC ", (size_t)CCA_KEYWORD_SIZE); if (encrypt) { CSNBENC(&return_code, &reason_code, NULL, NULL, attr->pValue, //id, &length, in_data, //in, init_v, //iv, &rule_array_count, rule_array, &pad_character, chaining_vector, local_out);//out_data); //out); } else { CSNBDEC(&return_code, &reason_code, NULL, NULL, attr->pValue, //id, &length, in_data, //in, init_v, //iv, &rule_array_count, rule_array, chaining_vector, local_out);//out_data); //out); } if (return_code != CCA_SUCCESS) { if (encrypt) TRACE_ERROR("CSNBENC (DES ENCRYPT) failed. return:%ld," " reason:%ld\n", return_code, reason_code); else TRACE_ERROR("CSNBDEC (DES DECRYPT) failed. return:%ld," " reason:%ld\n", return_code, reason_code); if (out_data != local_out) free(local_out); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { if (encrypt) TRACE_WARNING("CSNBENC (DES ENCRYPT) succeeded, but" " returned reason:%ld\n", reason_code); else TRACE_WARNING("CSNBDEC (DES DECRYPT) succeeded, but" " returned reason:%ld\n", reason_code); } /* If we malloc'd a new buffer due to overflow concerns and the data * coming out turned out to be bigger than expected, return an error. * * Else, memcpy the data back to the user's buffer */ if ((local_out != out_data) && ((CK_ULONG)length > *out_data_len)) { TRACE_DEVEL("CKR_BUFFER_TOO_SMALL: %ld bytes to write into %ld " "bytes space\n", length, *out_data_len); TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); free(local_out); return CKR_BUFFER_TOO_SMALL; } else if (local_out != out_data) { memcpy(out_data, local_out, (size_t)length); free(local_out); } *out_data_len = length; return CKR_OK; } CK_RV token_specific_tdes_ecb(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { TRACE_WARNING("Unsupported function reached.\n"); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV token_specific_tdes_cbc(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { /* Since keys are opaque objects in this token and there's only * one encipher command to CCA, we can just pass through */ return token_specific_des_cbc(in_data, in_data_len, out_data, out_data_len, key, init_v, encrypt); } uint16_t cca_inttok_privkey_get_len(CK_BYTE *tok) { return *(uint16_t *)&tok[CCA_RSA_INTTOK_PRIVKEY_LENGTH_OFFSET]; } /* Given a CCA internal token private key object, get the modulus */ CK_RV cca_inttok_privkey_get_n(CK_BYTE *tok, CK_ULONG *n_len, CK_BYTE *n) { uint16_t privkey_length, n_length; uint32_t privkey_n_offset; privkey_length = *(uint16_t *)&tok[CCA_RSA_INTTOK_PRIVKEY_LENGTH_OFFSET]; n_length = *(uint16_t *)&tok[CCA_RSA_INTTOK_PRIVKEY_N_LENGTH_OFFSET]; if (n_length > (*n_len)) { TRACE_ERROR("Not enough room to return n.(Got %lu, need %hu)\n", *n_len, n_length); return CKR_FUNCTION_FAILED; } privkey_n_offset = privkey_length - n_length; memcpy(n, &tok[privkey_n_offset], (size_t)n_length); *n_len = n_length; return CKR_OK; } /* Given a CCA internal token pubkey object, get the public exponent */ CK_RV cca_inttok_pubkey_get_e(CK_BYTE *tok, CK_ULONG *e_len, CK_BYTE *e) { uint16_t e_length; e_length = *(uint16_t *)&tok[CCA_RSA_INTTOK_PUBKEY_E_LENGTH_OFFSET]; if (e_length > (*e_len)) { TRACE_ERROR("Not enough room to return e.(Got %lu, need %hu)\n", *e_len, e_length); return CKR_FUNCTION_FAILED; } memcpy(e, &tok[CCA_RSA_INTTOK_PUBKEY_E_OFFSET], (size_t)e_length); *e_len = (CK_ULONG)e_length; return CKR_OK; } CK_RV token_create_keypair_object(TEMPLATE *tmpl, CK_ULONG tok_len, CK_BYTE *tok) { uint16_t privkey_len, pubkey_offset; CK_BYTE n[CCATOK_MAX_N_LEN], e[CCATOK_MAX_E_LEN]; CK_ULONG n_len = CCATOK_MAX_N_LEN, e_len = CCATOK_MAX_E_LEN; CK_ATTRIBUTE *modulus, *pub_exp, *opaque_key; CK_RV rv; privkey_len = cca_inttok_privkey_get_len(&tok[CCA_RSA_INTTOK_PRIVKEY_OFFSET]); pubkey_offset = privkey_len + CCA_RSA_INTTOK_HDR_LENGTH; /* That's right, n is stored in the private key area. Get it there */ if ((rv = cca_inttok_privkey_get_n(&tok[CCA_RSA_INTTOK_PRIVKEY_OFFSET], &n_len, n))) { TRACE_DEVEL("cca_inttok_privkey_get_n() failed. rv=0x%lx\n", rv); return rv; } /* Get e */ if ((rv = cca_inttok_pubkey_get_e(&tok[pubkey_offset], &e_len, e))) { TRACE_DEVEL("cca_inttok_pubkey_get_e() failed. rv=0x%lx\n", rv); return rv; } /* Add n's value to the template */ if ((rv = build_attribute(CKA_MODULUS, n, n_len, &modulus))) { TRACE_DEVEL("build_attribute for n failed. rv=0x%lx\n", rv); return rv; } template_update_attribute(tmpl, modulus); /* Add e's value to the template */ if ((rv = build_attribute(CKA_PUBLIC_EXPONENT, e, e_len, &pub_exp))) { TRACE_DEVEL("build_attribute for e failed. rv=0x%lx\n", rv); return rv; } template_update_attribute(tmpl, pub_exp); /* Add the opaque key object to the template */ if ((rv = build_attribute(CKA_IBM_OPAQUE, tok, tok_len, &opaque_key))) { TRACE_DEVEL("build_attribute for opaque key failed. rv=0x%lx\n", rv); return rv; } template_update_attribute(tmpl, opaque_key); return CKR_OK; } #if 0 CK_RV token_create_priv_key(TEMPLATE *priv_tmpl, CK_ULONG tok_len, CK_BYTE *tok) { CK_BYTE n[CCATOK_MAX_N_LEN]; CK_ULONG n_len = CCATOK_MAX_N_LEN; CK_RV rv; CK_ATTRIBUTE *opaque_key, *modulus; /* That's right, n is stored in the private key area. Get it there */ if ((rv = cca_inttok_privkey_get_n(&tok[CCA_RSA_INTTOK_PRIVKEY_OFFSET], &n_len, n))) { TRACE_DEVEL("cca_inttok_privkey_get_n() failed. rv=0x%lx", rv); return rv; } /* Add n's value to the template. We need to do this for the private * key as well as the public key because openCryptoki checks data * sizes against the size of the CKA_MODULUS attribute of whatever * key object it gets */ if ((rv = build_attribute(CKA_MODULUS, n, n_len, &modulus))) { TRACE_DEVEL("build_attribute for n failed. rv=0x%lx", rv); return rv; } template_update_attribute(priv_tmpl, modulus); /* Add the opaque key object to the template */ if ((rv = build_attribute(CKA_IBM_OPAQUE, tok, tok_len, &opaque_key))) { TRACE_DEVEL("build_attribute for opaque key failed. rv=0x%lx", rv); return rv; } template_update_attribute(priv_tmpl, opaque_key); return CKR_OK; } #endif CK_RV token_specific_rsa_generate_keypair(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { long return_code, reason_code, rule_array_count; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; long key_value_structure_length; long private_key_name_length, key_token_length; unsigned char key_value_structure[CCA_KEY_VALUE_STRUCT_SIZE] = { 0, }; unsigned char private_key_name[CCA_PRIVATE_KEY_NAME_SIZE] = { 0, }; unsigned char key_token[CCA_KEY_TOKEN_SIZE] = { 0, }; long regeneration_data_length, generated_key_token_length; unsigned char regeneration_data[CCA_REGENERATION_DATA_SIZE] = { 0, }; unsigned char transport_key_identifier[CCA_KEY_ID_SIZE] = { 0, }; unsigned char generated_key_token[CCA_KEY_TOKEN_SIZE] = { 0, }; uint16_t size_of_e; uint16_t mod_bits; CK_ATTRIBUTE *pub_exp = NULL, *attr = NULL; CK_RV rv; CK_BYTE_PTR ptr; CK_ULONG tmpsize, tmpexp; if (!template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr)) { TRACE_ERROR("Could not find CKA_MODULUS_BITS for the key.\n"); return CKR_TEMPLATE_INCOMPLETE; } mod_bits = *(CK_ULONG *)attr->pValue; /* If e is specified in the template, use it */ rv = template_attribute_find(publ_tmpl, CKA_PUBLIC_EXPONENT, &pub_exp); if (rv == TRUE) { /* Per CCA manual, we really only support 3 values here: * * * 0 (generate random public exponent) * * * 3 or * * * 65537 * * Trim the P11 value so we can check what's comming our way */ tmpsize = pub_exp->ulValueLen; ptr = p11_bigint_trim(pub_exp->pValue, &tmpsize); /* If we trimmed the number correctly, only 3 bytes are * * sufficient to hold 65537 (0x010001) */ if (tmpsize > 3) return CKR_TEMPLATE_INCONSISTENT; /* make pValue into CK_ULONG so we can compare */ tmpexp = 0; memcpy((void *)&tmpexp + sizeof(CK_ULONG) - tmpsize, // right align ptr, tmpsize); /* Check for one of the three allowed values */ if ( (tmpexp != 0) && (tmpexp != 3) && (tmpexp != 65537) ) return CKR_TEMPLATE_INCONSISTENT; size_of_e = (uint16_t)tmpsize; memcpy(&key_value_structure[CCA_PKB_E_SIZE_OFFSET], &size_of_e, (size_t)CCA_PKB_E_SIZE); memcpy(&key_value_structure[CCA_PKB_E_OFFSET], ptr, (size_t)tmpsize); } key_value_structure_length = CCA_KEY_VALUE_STRUCT_SIZE; memcpy(key_value_structure, &mod_bits, sizeof(uint16_t)); /* One last check. CCA can't auto-generate a random public * * exponent if the modulus length is more than 2048 bits * * We should be ok checking the public exponent length in the * * key_value_structure, since either the caller never * * specified it or we trimmed it's size. The size should be * * zero if the value is zero in both cases. * * public exponent has CCA_PKB_E_SIZE_OFFSET offset with * * 2-bytes size */ if (mod_bits > 2048 && key_value_structure[CCA_PKB_E_SIZE_OFFSET] == 0x00 && key_value_structure[CCA_PKB_E_SIZE_OFFSET + 1] == 0x00) { return CKR_TEMPLATE_INCONSISTENT; } rule_array_count = 2; memcpy(rule_array, "RSA-CRT KEY-MGMT", (size_t)(CCA_KEYWORD_SIZE * 2)); private_key_name_length = 0; key_token_length = CCA_KEY_TOKEN_SIZE; CSNDPKB(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &key_value_structure_length, key_value_structure, &private_key_name_length, private_key_name, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, &key_token_length, key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKB (RSA KEY TOKEN BUILD) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } rule_array_count = 1; memset(rule_array, 0, sizeof(rule_array)); memcpy(rule_array, "MASTER ", (size_t)CCA_KEYWORD_SIZE); generated_key_token_length = CCA_KEY_TOKEN_SIZE; regeneration_data_length = 0; CSNDPKG(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, ®eneration_data_length, regeneration_data, &key_token_length, key_token, transport_key_identifier, &generated_key_token_length, generated_key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKG (RSA KEY GENERATE) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } TRACE_DEVEL("RSA secure key token generated. size: %ld\n", generated_key_token_length); rv = token_create_keypair_object(publ_tmpl, generated_key_token_length, generated_key_token); if (rv != CKR_OK) { TRACE_DEVEL("token_create_keypair_object failed. rv:%lu\n", rv); return rv; } rv = token_create_keypair_object(priv_tmpl, generated_key_token_length, generated_key_token); if (rv != CKR_OK) TRACE_DEVEL("token_create_keypair_object failed. rv:%lu\n", rv); return rv; } CK_RV token_specific_rsa_encrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { long return_code, reason_code, rule_array_count, data_structure_length; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; CK_ATTRIBUTE *attr; /* Find the secure key token */ if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } /* The max value allowable by CCA for out_data_len is 512, so cap the incoming value if its * too large. CCA will throw error 8, 72 otherwise. */ if (*out_data_len > 512) *out_data_len = 512; rule_array_count = 1; memcpy(rule_array, "PKCS-1.2", CCA_KEYWORD_SIZE); data_structure_length = 0; CSNDPKE(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, (long *)&in_data_len, in_data, &data_structure_length, // must be 0 NULL, // ignored (long *)&(attr->ulValueLen), attr->pValue, (long *)out_data_len, out_data); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKE (RSA ENCRYPT) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { TRACE_WARNING("CSNDPKE (RSA ENCRYPT) succeeded, but" " returned reason:%ld\n", reason_code); } return CKR_OK; } CK_RV token_specific_rsa_decrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { long return_code, reason_code, rule_array_count, data_structure_length; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; CK_ATTRIBUTE *attr; /* Find the secure key token */ if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } /* The max value allowable by CCA for out_data_len is 512, so cap the incoming value if its * too large. CCA will throw error 8, 72 otherwise. */ if (*out_data_len > 512) *out_data_len = 512; rule_array_count = 1; memcpy(rule_array, "PKCS-1.2", CCA_KEYWORD_SIZE); data_structure_length = 0; CSNDPKD(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, (long *)&in_data_len, in_data, &data_structure_length, // must be 0 NULL, // ignored (long *)&(attr->ulValueLen), attr->pValue, (long *)out_data_len, out_data); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKD (RSA DECRYPT) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { TRACE_WARNING("CSNDPKD (RSA DECRYPT) succeeded, but" " returned reason:%ld\n", reason_code); } return CKR_OK; } CK_RV token_specific_rsa_sign(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj ) { long return_code, reason_code, rule_array_count; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; long signature_bit_length; CK_ATTRIBUTE *attr; /* Find the secure key token */ if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } rule_array_count = 1; memcpy(rule_array, "PKCS-1.1", CCA_KEYWORD_SIZE); CSNDDSG(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, (long *)&(attr->ulValueLen), attr->pValue, (long *)&in_data_len, in_data, (long *)out_data_len, &signature_bit_length, out_data); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDDSG (RSA SIGN) failed. return :%ld, " "reason: %ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { TRACE_WARNING("CSNDDSG (RSA SIGN) succeeded, but " "returned reason: %ld\n", reason_code); } return CKR_OK; } CK_RV token_specific_rsa_verify(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len, OBJECT * key_obj ) { long return_code, reason_code, rule_array_count; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; CK_ATTRIBUTE *attr; /* Find the secure key token */ if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } rule_array_count = 1; memcpy(rule_array, "PKCS-1.1", CCA_KEYWORD_SIZE); CSNDDSV(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, (long *)&(attr->ulValueLen), attr->pValue, (long *)&in_data_len, in_data, (long *)&out_data_len, out_data); if (return_code == 4 && reason_code == 429) { return CKR_SIGNATURE_INVALID; } else if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDDSV (RSA VERIFY) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { TRACE_WARNING("CSNDDSV (RSA VERIFY) succeeded, but" " returned reason:%ld\n", reason_code); } return CKR_OK; } #ifndef NOAES CK_RV token_specific_aes_key_gen(CK_BYTE *aes_key, CK_ULONG len, CK_ULONG key_size) { long return_code, reason_code; unsigned char key_token[CCA_KEY_ID_SIZE] = { 0, }; unsigned char key_form[CCA_KEYWORD_SIZE]; unsigned char key_type[CCA_KEYWORD_SIZE]; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0x20, }; long exit_data_len = 0, rule_array_count; unsigned char exit_data[4] = { 0, }; unsigned char reserved_1[4] = { 0, }; unsigned char point_to_array_of_zeros = 0; unsigned char mkvp[16] = { 0, }; /* make sure key is the right size for the token */ if (len != CCA_KEY_ID_SIZE) return CKR_FUNCTION_FAILED; memcpy(rule_array, "INTERNALAES NO-KEY ", (size_t) (CCA_KEYWORD_SIZE*3)); memcpy(key_type, "DATA ", (size_t)CCA_KEYWORD_SIZE); switch (key_size) { case 16: memcpy(rule_array + 3*CCA_KEYWORD_SIZE, "KEYLN16 ", CCA_KEYWORD_SIZE); break; case 24: memcpy(rule_array + 3*CCA_KEYWORD_SIZE, "KEYLN24 ", (size_t)CCA_KEYWORD_SIZE); break; case 32: memcpy(rule_array + 3*CCA_KEYWORD_SIZE, "KEYLN32 ", (size_t)CCA_KEYWORD_SIZE); break; default: TRACE_ERROR("Invalid key length: %lu\n", key_size); return CKR_KEY_SIZE_RANGE; } #ifdef DEBUG { uint32_t j; TRACE_DEBUG("Rule Array:"); for ( j = 0; j < 32; j++) printf("%c", rule_array[j]); printf("\n"); for ( j = 0; j < 8; j++) printf("%c", key_type[j]); } #endif rule_array_count = 4; CSNBKTB(&return_code, &reason_code, &exit_data_len, exit_data, key_token, key_type, &rule_array_count, rule_array, NULL, reserved_1, NULL, &point_to_array_of_zeros, NULL, NULL, NULL, NULL, mkvp); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBTKB (TOKEN BUILD) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } memcpy(key_form, "OP ", (size_t)CCA_KEYWORD_SIZE); memcpy(key_type, "AESTOKEN", (size_t) CCA_KEYWORD_SIZE); memcpy(aes_key, key_token, (size_t)CCA_KEY_ID_SIZE); return cca_key_gen(CCA_AES_KEY, aes_key, key_form, key_type, key_size); } CK_RV token_specific_aes_ecb(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { long return_code, reason_code, rule_array_count; long block_size = 16; unsigned char rule_array[CCA_RULE_ARRAY_SIZE]; long opt_data_len = 0, key_params_len =0, exit_data_len = 0, IV_len = 0, chain_vector_len = 0; char exit_data[0]; CK_BYTE *local_out = out_data; CK_ATTRIBUTE *attr = NULL; CK_ULONG key_len; if (template_attribute_find(key->template, CKA_IBM_OPAQUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the key.\n"); return CKR_FUNCTION_FAILED; } key_len = 64; rule_array_count = 4; memcpy(rule_array, "AES ECB KEYIDENTINITIAL ", rule_array_count*(size_t)CCA_KEYWORD_SIZE); if (encrypt) { CSNBSAE(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &key_len, attr->pValue, &key_params_len, NULL, &block_size, &IV_len, NULL, &chain_vector_len, NULL, &in_data_len, in_data, out_data_len, local_out, &opt_data_len, NULL); } else { CSNBSAD(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &key_len, attr->pValue, &key_params_len, NULL, &block_size, &IV_len, NULL, &chain_vector_len, NULL, &in_data_len, in_data, out_data_len, local_out, &opt_data_len, NULL); } if (return_code != CCA_SUCCESS) { if (encrypt) TRACE_ERROR("CSNBSAE (AES ENCRYPT) failed. return:%ld," " reason:%ld\n", return_code, reason_code); else TRACE_ERROR("CSNBSAD (AES DECRYPT) failed. return:%ld," " reason:%ld\n", return_code, reason_code); (*out_data_len) = 0; return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { if (encrypt) TRACE_WARNING("CSNBSAE (AES ENCRYPT) succeeded, but" " returned reason:%ld\n", reason_code); else TRACE_WARNING("CSNBSAD (AES DECRYPT) succeeded, but" " returned reason:%ld\n", reason_code); } return CKR_OK; } CK_RV token_specific_aes_cbc(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { long return_code, reason_code, rule_array_count, length; long block_size = 16; unsigned char chaining_vector[32]; unsigned char rule_array[CCA_RULE_ARRAY_SIZE]; long opt_data_len = 0, key_params_len =0, exit_data_len = 0, IV_len = 16, chain_vector_len = 32; CK_BYTE *local_out = out_data; char exit_data[0]; CK_ATTRIBUTE *attr = NULL; CK_ULONG key_len; // get the key value if (template_attribute_find(key->template, CKA_IBM_OPAQUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the key.\n"); return CKR_FUNCTION_FAILED; } if (in_data_len%16 == 0) { rule_array_count = 3; memcpy(rule_array, "AES KEYIDENTINITIAL ", rule_array_count*(size_t)CCA_KEYWORD_SIZE); } else { if ((encrypt) && (*out_data_len < (in_data_len + 16))) { local_out = malloc(in_data_len + 16); if (!local_out) { TRACE_ERROR("Malloc of %lu bytes failed.\n", in_data_len + 16); return CKR_HOST_MEMORY; } } rule_array_count = 3; memcpy(rule_array, "AES PKCS-PADKEYIDENT", rule_array_count*(size_t)CCA_KEYWORD_SIZE); } length = in_data_len; key_len = 64; if (encrypt) { CSNBSAE(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &key_len, attr->pValue, &key_params_len, exit_data, &block_size, &IV_len, init_v, &chain_vector_len, chaining_vector, &length, in_data, out_data_len, out_data, &opt_data_len, NULL); } else { CSNBSAD(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &key_len, attr->pValue, &key_params_len, NULL, &block_size, &IV_len, init_v, &chain_vector_len, chaining_vector, &length, in_data, out_data_len, out_data, &opt_data_len, NULL); } if (return_code != CCA_SUCCESS) { if (encrypt) TRACE_ERROR("CSNBSAE (AES ENCRYPT) failed. return:%ld," " reason:%ld\n", return_code, reason_code); else TRACE_ERROR("CSNBSAD (AES DECRYPT) failed. return:%ld," " reason:%ld\n", return_code, reason_code); (*out_data_len) = 0; return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { if (encrypt) TRACE_WARNING("CSNBSAE (AES ENCRYPT) succeeded, but" " returned reason:%ld\n", reason_code); else TRACE_WARNING("CSNBSAD (AES DECRYPT) succeeded, but" " returned reason:%ld\n", reason_code); } /* If we malloc'd a new buffer due to overflow concerns and the data * coming out turned out to be bigger than expected, return an error. * * Else, memcpy the data back to the user's buffer */ if ((local_out != out_data) && ((CK_ULONG)length > *out_data_len)) { TRACE_ERROR("buffer too small: %ld bytes to write into %ld " "bytes space\n", length, *out_data_len); free(local_out); return CKR_BUFFER_TOO_SMALL; } else if (local_out != out_data) { memcpy(out_data, local_out, (size_t)length); free(local_out); } *out_data_len = length; return CKR_OK; } #endif #ifndef NODH /* Begin code contributed by Corrent corp. */ CK_RV token_specific_dh_pkcs_derive(CK_BYTE *z, CK_ULONG *z_len, CK_BYTE *y, CK_ULONG y_len, CK_BYTE *x, CK_ULONG x_len, CK_BYTE *p, CK_ULONG p_len) { TRACE_DEVEL("Unsupported function reached.\n"); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV token_specific_dh_pkcs_key_pair_gen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl ) { TRACE_DEVEL("Unsupported function reached.\n"); return CKR_FUNCTION_NOT_SUPPORTED; } /* End code contributed by Corrent corp. */ #endif /* See the top of this file for the declarations of mech_list and * mech_list_len. */ CK_RV token_specific_get_mechanism_list(CK_MECHANISM_TYPE *pMechanismList, CK_ULONG *pulCount) { CK_ULONG i; if (pMechanismList == NULL) { (*pulCount) = mech_list_len; return CKR_OK; } if ((*pulCount) < mech_list_len) { (*pulCount) = mech_list_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } for (i = 0; i < mech_list_len; i++) pMechanismList[i] = mech_list[i].mech_type; (*pulCount) = mech_list_len; return CKR_OK; } CK_RV token_specific_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO *pInfo) { CK_ULONG i; for (i = 0; i < mech_list_len; i++) { if (mech_list[i].mech_type == type) { memcpy(pInfo, &mech_list[i].mech_info, sizeof(CK_MECHANISM_INFO)); return CKR_OK; } } TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } CK_RV build_update_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE_TYPE type, CK_BYTE *data, CK_ULONG data_len) { CK_ATTRIBUTE *attr; CK_RV rv; if ((rv = build_attribute(type, data, data_len, &attr))) { TRACE_DEVEL("Build attribute for type=%lu failed rv=0x%lx\n", type, rv); return rv; } template_update_attribute(tmpl, attr); return CKR_OK; } uint16_t cca_ec_privkey_offset(CK_BYTE *tok) { uint8_t privkey_id = CCA_PRIVKEY_ID, privkey_rec; privkey_rec = ntohs(*(uint8_t*)&tok[CCA_EC_HEADER_SIZE]); if ((memcmp(&privkey_rec, &privkey_id, sizeof(uint8_t)) == 0)) { return CCA_EC_HEADER_SIZE; } TRACE_WARNING("+++++++++ Token key private section is CORRUPTED\n"); return CCA_EC_HEADER_SIZE; } uint16_t cca_ec_publkey_offset(CK_BYTE *tok) { uint16_t priv_offset, privSec_len; uint8_t publkey_id = CCA_PUBLKEY_ID, publkey_rec; priv_offset = cca_ec_privkey_offset(tok); privSec_len = ntohs(*(uint16_t*)&tok[priv_offset + CCA_SECTION_LEN_OFFSET]); publkey_rec = ntohs(*(uint8_t*)&tok[priv_offset + privSec_len]); if ((memcmp(&publkey_rec, &publkey_id, sizeof(uint8_t)) == 0)) { return (priv_offset + privSec_len); } TRACE_WARNING("++++++++ Token key public section is CORRUPTED\n"); return (priv_offset + privSec_len); } CK_RV token_create_ec_keypair(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl, CK_ULONG tok_len, CK_BYTE *tok) { uint16_t pubkey_offset, qlen_offset, q_offset; CK_ULONG q_len; CK_BYTE q[CCATOK_EC_MAX_Q_LEN]; CK_RV rv; CK_ATTRIBUTE *attr = NULL; /* * The token includes the header section first, * the private key section in the middle, * and the public key section last. */ /* The pkcs#11v2.20: * CKA_ECDSA_PARAMS must be in public key's template when * generating key pair and added to private key template. * CKA_EC_POINT added to public key when key is generated. */ /* * Get Q data for public key. */ pubkey_offset = cca_ec_publkey_offset(tok); qlen_offset = pubkey_offset + CCA_EC_INTTOK_PUBKEY_Q_LEN_OFFSET; q_len = *(uint16_t *)&tok[qlen_offset]; q_len = ntohs(q_len); if (q_len > CCATOK_EC_MAX_Q_LEN) { TRACE_ERROR("Not enough room to return q. (Got %d, need %ld)\n", CCATOK_EC_MAX_Q_LEN, q_len); return CKR_FUNCTION_FAILED; } q_offset = pubkey_offset + CCA_EC_INTTOK_PUBKEY_Q_OFFSET; memcpy(q, &tok[q_offset], (size_t)q_len); if ((rv = build_update_attribute(publ_tmpl, CKA_EC_POINT, q, q_len))) { TRACE_DEVEL("build_update_attribute for q failed rv=0x%lx\n", rv); return rv; } /* Add ec params to private key */ if (!template_attribute_find(publ_tmpl, CKA_ECDSA_PARAMS, &attr)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } if ((rv = build_update_attribute(priv_tmpl, CKA_ECDSA_PARAMS, attr->pValue, attr->ulValueLen))) { TRACE_DEVEL("build_update_attribute for der data failed " "rv=0x%lx\n", rv); return rv; } /* * Save the CKA_IBM_OPAQUE for both keys. */ if ((rv = build_update_attribute(publ_tmpl, CKA_IBM_OPAQUE, tok, tok_len))) { TRACE_DEVEL("build_update_attribute for tok failed rv=0x%lx\n", rv); return rv; } if ((rv = build_update_attribute(priv_tmpl, CKA_IBM_OPAQUE, tok, tok_len))) { TRACE_DEVEL("build_update_attribute for tok failed rv=0x%lx\n", rv); return rv; } return CKR_OK; } CK_RV token_specific_ec_generate_keypair(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { long return_code, reason_code, rule_array_count, exit_data_len = 0; unsigned char *exit_data = NULL; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; long key_value_structure_length, private_key_name_length, key_token_length; unsigned char key_value_structure[CCA_EC_KEY_VALUE_STRUCT_SIZE] = { 0, }; unsigned char private_key_name[CCA_PRIVATE_KEY_NAME_SIZE] = { 0, }; unsigned char key_token[CCA_KEY_TOKEN_SIZE] = { 0, }; long regeneration_data_length, generated_key_token_length; unsigned char regeneration_data[CCA_REGENERATION_DATA_SIZE] = { 0, }; unsigned char transport_key_identifier[CCA_KEY_ID_SIZE] = { 0, }; unsigned char generated_key_token[CCA_KEY_TOKEN_SIZE] = { 0, }; unsigned int i; CK_BBOOL found = FALSE; CK_ATTRIBUTE *attr = NULL; CK_RV rv; long param1=0; unsigned char *param2=NULL; if (!template_attribute_find(publ_tmpl, CKA_ECDSA_PARAMS, &attr)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } for (i = 0; i < NUMEC; i++) { if ((attr->ulValueLen == der_ec_supported[i].data_size) && (memcmp(attr->pValue, der_ec_supported[i].data, attr->ulValueLen) == 0)) { found = TRUE; break; } } if(found == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } /* * See CCA doc: page 94 for offset of data in key_value_structure */ memcpy(key_value_structure, &(der_ec_supported[i].curve_type), sizeof(uint8_t)); memcpy(&key_value_structure[CCA_PKB_EC_LEN_OFFSET], &(der_ec_supported[i].len_bits), sizeof(uint16_t)); key_value_structure_length = CCA_EC_KEY_VALUE_STRUCT_SIZE; rule_array_count = 1; memcpy(rule_array, "ECC-PAIR", (size_t)(CCA_KEYWORD_SIZE)); private_key_name_length = 0; key_token_length = CCA_KEY_TOKEN_SIZE; CSNDPKB(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &key_value_structure_length, key_value_structure, &private_key_name_length, private_key_name, ¶m1, param2, ¶m1, param2, ¶m1, param2, ¶m1, param2, ¶m1, param2, &key_token_length, key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKB (EC KEY TOKEN BUILD) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } rule_array_count = 1; memset(rule_array, 0, sizeof(rule_array)); memcpy(rule_array, "MASTER ", (size_t)CCA_KEYWORD_SIZE); generated_key_token_length = CCA_KEY_TOKEN_SIZE; regeneration_data_length = 0; CSNDPKG(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, ®eneration_data_length, regeneration_data, &key_token_length, key_token, transport_key_identifier, &generated_key_token_length, generated_key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKG (EC KEY GENERATE) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } TRACE_DEVEL("ECC secure key token generated. size: %ld\n", generated_key_token_length); rv = token_create_ec_keypair(publ_tmpl, priv_tmpl, generated_key_token_length, generated_key_token); if (rv != CKR_OK) { TRACE_DEVEL("token_create_ec_keypair failed. rv: %lu\n", rv); return rv; } return rv; } CK_RV token_specific_ec_sign(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj ) { long return_code, reason_code, rule_array_count; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; long signature_bit_length; CK_ATTRIBUTE *attr; /* Find the secure key token */ if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } /* CCA doc: page 113 */ rule_array_count = 1; memcpy(rule_array, "ECDSA ", CCA_KEYWORD_SIZE); CSNDDSG(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, (long *)&(attr->ulValueLen), attr->pValue, (long *)&in_data_len, in_data, (long *)out_data_len, &signature_bit_length, out_data); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDDSG (EC SIGN) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { TRACE_WARNING("CSNDDSG (EC SIGN) succeeded, but" " returned reason:%ld\n", reason_code); } return CKR_OK; } CK_RV token_specific_ec_verify(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len, OBJECT * key_obj ) { long return_code, reason_code, rule_array_count; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; CK_ATTRIBUTE *attr; /* Find the secure key token */ if (!template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } /* CCA doc: page 118 */ rule_array_count = 1; memcpy(rule_array, "ECDSA ", CCA_KEYWORD_SIZE); CSNDDSV(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, (long *)&(attr->ulValueLen), attr->pValue, (long *)&in_data_len, in_data, (long *)&out_data_len, out_data); if (return_code == 4 && reason_code == 429) { return CKR_SIGNATURE_INVALID; } else if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDDSV (EC VERIFY) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { TRACE_WARNING("CSNDDSV (EC VERIFY) succeeded, but" " returned reason:%ld\n", reason_code); } return CKR_OK; } CK_RV token_specific_sha_init(DIGEST_CONTEXT *ctx, CK_MECHANISM *mech) { CK_ULONG hash_size; struct cca_sha_ctx *cca_ctx; switch(mech->mechanism) { case CKM_SHA_1: hash_size = SHA1_HASH_SIZE; break; case CKM_SHA256: hash_size = SHA2_HASH_SIZE; break; case CKM_SHA384: hash_size = SHA3_HASH_SIZE; break; case CKM_SHA512: hash_size = SHA5_HASH_SIZE; break; default: return CKR_MECHANISM_INVALID; } ctx->context = calloc(1, sizeof(struct cca_sha_ctx)); if (ctx->context == NULL) { TRACE_ERROR("malloc failed in sha digest init\n"); return CKR_HOST_MEMORY; } ctx->context_len = sizeof(struct cca_sha_ctx); cca_ctx = (struct cca_sha_ctx *)ctx->context; cca_ctx->chain_vector_len = CCA_CHAIN_VECTOR_LEN; cca_ctx->hash_len = hash_size; /* tail_len is already 0 */ return CKR_OK; } CK_RV token_specific_sha(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { struct cca_sha_ctx *cca_ctx; long return_code, reason_code, rule_array_count = 2; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; if (!in_data || !out_data) return CKR_ARGUMENTS_BAD; cca_ctx = (struct cca_sha_ctx *)ctx->context; if (*out_data_len < cca_ctx->hash_len) return CKR_BUFFER_TOO_SMALL; switch (ctx->mech.mechanism) { case CKM_SHA_1: memcpy(rule_array, "SHA-1 ONLY ", CCA_KEYWORD_SIZE * 2); cca_ctx->part = CCA_HASH_PART_ONLY; break; case CKM_SHA256: memcpy(rule_array, "SHA-256 ONLY ", CCA_KEYWORD_SIZE * 2); cca_ctx->part = CCA_HASH_PART_ONLY; break; case CKM_SHA384: memcpy(rule_array, "SHA-384 ONLY ", CCA_KEYWORD_SIZE * 2); cca_ctx->part = CCA_HASH_PART_ONLY; break; case CKM_SHA512: memcpy(rule_array, "SHA-512 ONLY ", CCA_KEYWORD_SIZE * 2); cca_ctx->part = CCA_HASH_PART_ONLY; break; default: return CKR_MECHANISM_INVALID; } CSNBOWH(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &in_data_len, in_data, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &cca_ctx->hash_len, cca_ctx->hash); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBOWH failed. return:%ld, reason:%ld\n", return_code, reason_code); free(cca_ctx->tail); return CKR_FUNCTION_FAILED; } memcpy(out_data, cca_ctx->hash, cca_ctx->hash_len); *out_data_len = cca_ctx->hash_len; /* ctx->context should get freed in digest_mgr_cleanup() */ return CKR_OK; } CK_RV token_specific_sha_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { struct cca_sha_ctx *cca_ctx; long return_code, reason_code, total, buffer_len, rule_array_count = 2; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; CK_RV rc = CKR_OK; unsigned char *buffer = NULL; int blocksz, blocksz_mask, use_buffer = 0; if (!in_data) return CKR_ARGUMENTS_BAD; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; switch(ctx->mech.mechanism) { case CKM_SHA_1: blocksz = SHA1_BLOCK_SIZE; blocksz_mask = SHA1_BLOCK_SIZE_MASK; break; case CKM_SHA256: blocksz = SHA2_BLOCK_SIZE; blocksz_mask = SHA2_BLOCK_SIZE_MASK; break; case CKM_SHA384: blocksz = SHA3_BLOCK_SIZE; blocksz_mask = SHA3_BLOCK_SIZE_MASK; break; case CKM_SHA512: blocksz = SHA5_BLOCK_SIZE; blocksz_mask = SHA5_BLOCK_SIZE_MASK; break; default: return CKR_MECHANISM_INVALID; } cca_ctx = (struct cca_sha_ctx *)ctx->context; /* just send if input a multiple of block size and * cca_ctx-> tail is empty. */ if ((cca_ctx->tail_len == 0) && ((in_data_len & blocksz_mask) == 0)) goto send; /* at this point, in_data is not multiple of blocksize * and/or there is saved data from previous update still * needing to be processed */ /* get totals */ total = cca_ctx->tail_len + in_data_len; /* see if we have enough to fill a block */ if (total >= blocksz) { int remainder; remainder = total & blocksz_mask; buffer_len = total - remainder; /* allocate a buffer for sending... */ if (!(buffer = malloc(buffer_len))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(buffer, cca_ctx->tail, cca_ctx->tail_len); memcpy(buffer + cca_ctx->tail_len, in_data, in_data_len - remainder); use_buffer = 1; /* save remainder data for next time */ if (remainder) memcpy(cca_ctx->tail, in_data + (in_data_len - remainder), remainder); cca_ctx->tail_len = remainder; } else { /* not enough to fill a block, save off data for next round */ memcpy(cca_ctx->tail + cca_ctx->tail_len, in_data, in_data_len); cca_ctx->tail_len += in_data_len; return CKR_OK; } send: switch(ctx->mech.mechanism) { case CKM_SHA_1: if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array, "SHA-1 FIRST ", CCA_KEYWORD_SIZE * 2); cca_ctx->part = CCA_HASH_PART_MIDDLE; } else { memcpy(rule_array, "SHA-1 MIDDLE ", CCA_KEYWORD_SIZE * 2); } break; case CKM_SHA256: if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array, "SHA-256 FIRST ", CCA_KEYWORD_SIZE * 2); cca_ctx->part = CCA_HASH_PART_MIDDLE; } else { memcpy(rule_array, "SHA-256 MIDDLE ", CCA_KEYWORD_SIZE * 2); } break; case CKM_SHA384: if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array, "SHA-384 FIRST ", CCA_KEYWORD_SIZE * 2); cca_ctx->part = CCA_HASH_PART_MIDDLE; } else { memcpy(rule_array, "SHA-384 MIDDLE ", CCA_KEYWORD_SIZE * 2); } break; case CKM_SHA512: if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array, "SHA-512 FIRST ", CCA_KEYWORD_SIZE * 2); cca_ctx->part = CCA_HASH_PART_MIDDLE; } else { memcpy(rule_array, "SHA-512 MIDDLE ", CCA_KEYWORD_SIZE * 2); } break; } CSNBOWH(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, use_buffer ? &buffer_len : (long *)&in_data_len, use_buffer ? buffer : in_data, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &cca_ctx->hash_len, cca_ctx->hash); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBOWH (SHA UPDATE) failed. return:%ld," " reason:%ld\n", return_code, reason_code); rc = CKR_FUNCTION_FAILED; } done: if (buffer) free(buffer); return rc; } CK_RV token_specific_sha_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len) { struct cca_sha_ctx *cca_ctx; long return_code, reason_code, rule_array_count = 2; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; unsigned char dummy_buf[1] = { 0 }; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; cca_ctx = (struct cca_sha_ctx *)ctx->context; if (*out_data_len < cca_ctx->hash_len) { TRACE_ERROR("out buf too small for hash: %lu\n", *out_data_len); return CKR_BUFFER_TOO_SMALL; } switch(ctx->mech.mechanism) { case CKM_SHA_1: if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array, "SHA-1 ONLY ", CCA_KEYWORD_SIZE * 2); } else { /* there's some extra data we need to hash to * complete the operation */ memcpy(rule_array, "SHA-1 LAST ", CCA_KEYWORD_SIZE * 2); } break; case CKM_SHA256: if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array, "SHA-256 ONLY ", CCA_KEYWORD_SIZE * 2); } else { /* there's some extra data we need to hash to * complete the operation */ memcpy(rule_array, "SHA-256 LAST ", CCA_KEYWORD_SIZE * 2); } break; case CKM_SHA384: if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array, "SHA-384 ONLY ", CCA_KEYWORD_SIZE * 2); } else { /* there's some extra data we need to hash to * complete the operation */ memcpy(rule_array, "SHA-384 LAST ", CCA_KEYWORD_SIZE * 2); } break; case CKM_SHA512: if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array, "SHA-512 ONLY ", CCA_KEYWORD_SIZE * 2); } else { /* there's some extra data we need to hash to * complete the operation */ memcpy(rule_array, "SHA-512 LAST ", CCA_KEYWORD_SIZE * 2); } break; default: return CKR_MECHANISM_INVALID; } TRACE_DEBUG("tail_len: %lu, tail: %p, cvl: %lu, sl: %lu\n", cca_ctx->tail_len, cca_ctx->tail ? cca_ctx->tail : dummy_buf, cca_ctx->chain_vector_len, cca_ctx->hash_len); CSNBOWH(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &cca_ctx->tail_len, cca_ctx->tail ? cca_ctx->tail : dummy_buf, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &cca_ctx->hash_len, cca_ctx->hash); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBOWH (SHA FINAL) failed. return:%ld," " reason:%ld\n", return_code, reason_code); free(cca_ctx->tail); return CKR_FUNCTION_FAILED; } memcpy(out_data, cca_ctx->hash, cca_ctx->hash_len); *out_data_len = cca_ctx->hash_len; /* ctx->context should get freed in digest_mgr_cleanup() */ return CKR_OK; } static long get_mac_len(CK_MECHANISM *mech) { switch (mech->mechanism) { case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: return *(CK_ULONG *)(mech->pParameter); case CKM_SHA_1_HMAC: return SHA1_HASH_SIZE; case CKM_SHA256_HMAC: return SHA2_HASH_SIZE; case CKM_SHA384_HMAC: return SHA3_HASH_SIZE; case CKM_SHA512_HMAC: return SHA5_HASH_SIZE; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return -1; } } static CK_RV ccatok_hmac_init(SIGN_VERIFY_CONTEXT *ctx, CK_MECHANISM *mech, CK_OBJECT_HANDLE key) { struct cca_sha_ctx *cca_ctx; long maclen = -1; maclen = get_mac_len(mech); if (maclen < 0) return CKR_MECHANISM_INVALID; ctx->context = calloc(1, sizeof(struct cca_sha_ctx)); if (ctx->context == NULL) { TRACE_ERROR("malloc failed in sha digest init\n"); return CKR_HOST_MEMORY; } ctx->context_len = sizeof(struct cca_sha_ctx); cca_ctx = (struct cca_sha_ctx *)ctx->context; memset(cca_ctx, 0, sizeof(struct cca_sha_ctx)); cca_ctx->chain_vector_len = CCA_CHAIN_VECTOR_LEN; cca_ctx->hash_len = maclen; return CKR_OK; } CK_RV token_specific_hmac_sign_init(SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE key) { return ccatok_hmac_init(&sess->sign_ctx, mech, key); } CK_RV token_specific_hmac_verify_init(SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE key) { return ccatok_hmac_init(&sess->verify_ctx, mech, key); } CK_RV ccatok_hmac(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG *sig_len, CK_BBOOL sign) { struct cca_sha_ctx *cca_ctx; long return_code = 0, reason_code = 0, rule_array_count = 3; unsigned char rule_array[CCA_RULE_ARRAY_SIZE]; OBJECT *key = NULL; CK_ATTRIBUTE *attr = NULL; CK_RV rc = CKR_OK; if (!ctx || !ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (sign && !sig_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1(ctx->key, &key); if (rc != CKR_OK) { TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (template_attribute_find(key->template, CKA_IBM_OPAQUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the key.\n"); return CKR_FUNCTION_FAILED; } cca_ctx = (struct cca_sha_ctx *)ctx->context; switch (ctx->mech.mechanism) { case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA_1_HMAC: memcpy(rule_array, "HMAC SHA-1 ONLY ", 3 * CCA_KEYWORD_SIZE); break; case CKM_SHA256_HMAC_GENERAL: case CKM_SHA256_HMAC: memcpy(rule_array, "HMAC SHA-256 ONLY ", 3 * CCA_KEYWORD_SIZE); break; case CKM_SHA384_HMAC_GENERAL: case CKM_SHA384_HMAC: memcpy(rule_array, "HMAC SHA-384 ONLY ", 3 * CCA_KEYWORD_SIZE); break; case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_HMAC: memcpy(rule_array, "HMAC SHA-512 ONLY ", 3 * CCA_KEYWORD_SIZE); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_INFO("ccatok_hmac: key length is %lu\n", attr->ulValueLen); TRACE_INFO("The mac length is %ld\n", cca_ctx->hash_len); if (sign) { CSNBHMG(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &attr->ulValueLen, attr->pValue, &in_data_len, in_data, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &cca_ctx->hash_len, cca_ctx->hash); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBHMG (HMAC GENERATE) failed. " "return:%ld, reason:%ld\n", return_code, reason_code); *sig_len = 0; return CKR_FUNCTION_FAILED; } /* Copy the signature into the user supplied variable. * For hmac general mechs, only copy over the specified * number of bytes for the mac. */ memcpy(signature, cca_ctx->hash, cca_ctx->hash_len); *sig_len = cca_ctx->hash_len; } else { // verify CSNBHMV(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &attr->ulValueLen, attr->pValue, &in_data_len, in_data, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &cca_ctx->hash_len, signature); if (return_code == 4 && (reason_code == 429 || reason_code == 1)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } else if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBHMV (HMAC VERIFY) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { TRACE_WARNING("CSNBHMV (HMAC VERIFY) succeeded, but" " returned reason:%ld\n", reason_code); } } return CKR_OK; } CK_RV token_specific_hmac_sign(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG *sig_len) { return ccatok_hmac(&sess->sign_ctx, in_data, in_data_len, signature, sig_len, TRUE); } CK_RV token_specific_hmac_verify(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { return ccatok_hmac(&sess->verify_ctx, in_data, in_data_len, signature, &sig_len, FALSE); } CK_RV ccatok_hmac_update(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BBOOL sign) { struct cca_sha_ctx *cca_ctx; long return_code, reason_code, total, buffer_len; long hsize, rule_array_count = 3; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; unsigned char *buffer = NULL; int blocksz, blocksz_mask, use_buffer = 0; OBJECT *key = NULL; CK_ATTRIBUTE *attr = NULL; CK_RV rc = CKR_OK; if (!ctx || !ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } /* if zero input data, then just do nothing and return. * "final" should catch if this is case of hashing zero input. */ if (in_data_len == 0) return CKR_OK; rc = object_mgr_find_in_map1(ctx->key, &key); if (rc != CKR_OK) { TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (template_attribute_find(key->template, CKA_IBM_OPAQUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the key.\n"); return CKR_FUNCTION_FAILED; } switch(ctx->mech.mechanism) { case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: blocksz = SHA1_BLOCK_SIZE; // set to 64 bytes blocksz_mask = SHA1_BLOCK_SIZE_MASK; // set to 63 break; case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: blocksz = SHA5_BLOCK_SIZE; // set to 128 bytes blocksz_mask = SHA5_BLOCK_SIZE_MASK; // set to 127 break; default: return CKR_MECHANISM_INVALID; } cca_ctx = (struct cca_sha_ctx *)ctx->context; /* just send if input a multiple of block size and * cca_ctx-> tail is empty. */ if ((cca_ctx->tail_len == 0) && ((in_data_len & blocksz_mask) == 0)) goto send; /* at this point, in_data is not multiple of blocksize * and/or there is saved data from previous update still * needing to be processed */ /* get totals */ total = cca_ctx->tail_len + in_data_len; /* see if we have enough to fill a block */ if (total >= blocksz) { int remainder; remainder = total & blocksz_mask; // save left over buffer_len = total - remainder; /* allocate a buffer for sending... */ if (!(buffer = malloc(buffer_len))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } /* copy data to send. * first get any data saved in tail from prior call, * then fill up remaining space in block with in_data */ memcpy(buffer, cca_ctx->tail, cca_ctx->tail_len); memcpy(buffer + cca_ctx->tail_len, in_data, in_data_len - remainder); use_buffer = 1; /* save remainder data for next time */ if (remainder) memcpy(cca_ctx->tail, in_data + (in_data_len - remainder), remainder); cca_ctx->tail_len = remainder; } else { /* not enough to fill a block, * so save off data for next round */ memcpy(cca_ctx->tail + cca_ctx->tail_len, in_data, in_data_len); cca_ctx->tail_len += in_data_len; return CKR_OK; } send: switch(ctx->mech.mechanism) { case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: hsize = SHA1_HASH_SIZE; memcpy(rule_array, "HMAC SHA-1 ", CCA_KEYWORD_SIZE * 2); break; case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: hsize = SHA2_HASH_SIZE; memcpy(rule_array, "HMAC SHA-256 ", CCA_KEYWORD_SIZE * 2); break; case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: hsize = SHA3_HASH_SIZE; memcpy(rule_array, "HMAC SHA-384 ", CCA_KEYWORD_SIZE * 2); break; case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: hsize = SHA5_HASH_SIZE; memcpy(rule_array, "HMAC SHA-512 ", CCA_KEYWORD_SIZE * 2); break; } if (cca_ctx->part == CCA_HASH_PART_FIRST) { memcpy(rule_array + (CCA_KEYWORD_SIZE*2), "FIRST ", CCA_KEYWORD_SIZE); cca_ctx->part = CCA_HASH_PART_MIDDLE; } else { memcpy(rule_array + (CCA_KEYWORD_SIZE*2), "MIDDLE ", CCA_KEYWORD_SIZE); } TRACE_INFO("CSNBHMG: key length is %lu\n", attr->ulValueLen); if (sign) { CSNBHMG(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &attr->ulValueLen, attr->pValue, use_buffer ? &buffer_len : (long *)&in_data_len, use_buffer ? buffer : in_data, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &hsize, cca_ctx->hash); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBHMG (HMAC SIGN UPDATE) failed. " "return:%ld, reason:%ld\n", return_code, reason_code); rc = CKR_FUNCTION_FAILED; } } else { // verify CSNBHMV(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &attr->ulValueLen, attr->pValue, use_buffer ? &buffer_len : (long *)&in_data_len, use_buffer ? buffer : in_data, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &hsize, cca_ctx->hash); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBHMG (HMAC VERIFY UPDATE) failed. " "return:%ld, reason:%ld\n", return_code, reason_code); rc = CKR_FUNCTION_FAILED; } } done: if (buffer) free(buffer); return rc; } CK_RV token_specific_hmac_sign_update(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len) { return ccatok_hmac_update(&sess->sign_ctx, in_data, in_data_len, TRUE); } CK_RV token_specific_hmac_verify_update(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len) { return ccatok_hmac_update(&sess->verify_ctx, in_data, in_data_len, FALSE); } CK_RV ccatok_hmac_final(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG *sig_len, CK_BBOOL sign) { struct cca_sha_ctx *cca_ctx; long return_code, reason_code, rule_array_count = 3; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; OBJECT *key = NULL; CK_ATTRIBUTE *attr = NULL; CK_RV rc = CKR_OK; if (!ctx || !ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } rc = object_mgr_find_in_map1(ctx->key, &key); if (rc != CKR_OK) { TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (template_attribute_find(key->template, CKA_IBM_OPAQUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_IBM_OPAQUE for the key.\n"); return CKR_FUNCTION_FAILED; } cca_ctx = (struct cca_sha_ctx *)ctx->context; switch(ctx->mech.mechanism) { case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: memcpy(rule_array, "HMAC SHA-1 ", CCA_KEYWORD_SIZE * 2); break; case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: memcpy(rule_array, "HMAC SHA-256 ", CCA_KEYWORD_SIZE * 2); break; case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: memcpy(rule_array, "HMAC SHA-384 ", CCA_KEYWORD_SIZE * 2); break; case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: memcpy(rule_array, "HMAC SHA-512 ", CCA_KEYWORD_SIZE * 2); break; default: return CKR_MECHANISM_INVALID; } if (cca_ctx->part == CCA_HASH_PART_FIRST) memcpy(rule_array + (CCA_KEYWORD_SIZE*2), "ONLY ", CCA_KEYWORD_SIZE); else memcpy(rule_array + (CCA_KEYWORD_SIZE*2), "LAST ", CCA_KEYWORD_SIZE); TRACE_INFO("CSNBHMG: key length is %lu\n", attr->ulValueLen); TRACE_INFO("The mac length is %ld\n", cca_ctx->hash_len); if (sign) { CSNBHMG(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &attr->ulValueLen, attr->pValue, &cca_ctx->tail_len, cca_ctx->tail, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &cca_ctx->hash_len, cca_ctx->hash); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBHMG (HMAC SIGN FINAL) failed. " "return:%ld, reason:%ld\n", return_code, reason_code); *sig_len = 0; return CKR_FUNCTION_FAILED; } /* Copy the signature into the user supplied variable. * For hmac general mechs, only copy over the specified * number of bytes for the mac. */ memcpy(signature, cca_ctx->hash, cca_ctx->hash_len); *sig_len = cca_ctx->hash_len; } else { // verify CSNBHMV(&return_code, &reason_code, NULL, NULL, &rule_array_count,rule_array, &attr->ulValueLen, attr->pValue, &cca_ctx->tail_len, cca_ctx->tail, &cca_ctx->chain_vector_len, cca_ctx->chain_vector, &cca_ctx->hash_len, signature); if (return_code == 4 && (reason_code == 429 || reason_code == 1)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } else if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBHMV (HMAC VERIFY) failed. return:%ld," " reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } else if (reason_code != 0) { TRACE_WARNING("CSNBHMV (HMAC VERIFY) succeeded, but" " returned reason:%ld\n", reason_code); } } return CKR_OK; } CK_RV token_specific_hmac_sign_final(SESSION *sess, CK_BYTE *signature, CK_ULONG *sig_len) { return ccatok_hmac_final(&sess->sign_ctx, signature, sig_len, TRUE); } CK_RV token_specific_hmac_verify_final(SESSION *sess, CK_BYTE *signature, CK_ULONG sig_len) { return ccatok_hmac_final(&sess->verify_ctx, signature, &sig_len, FALSE); } static CK_RV rsa_import_privkey_crt(TEMPLATE *priv_tmpl) { long return_code, reason_code, rule_array_count, total = 0; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; long offset, key_value_structure_length = CCA_KEY_VALUE_STRUCT_SIZE; long private_key_name_length, key_token_length, target_key_token_length; unsigned char key_value_structure[CCA_KEY_VALUE_STRUCT_SIZE] = { 0, }; unsigned char private_key_name[CCA_PRIVATE_KEY_NAME_SIZE] = { 0, }; unsigned char key_token[CCA_KEY_TOKEN_SIZE] = { 0, }; unsigned char target_key_token[CCA_KEY_TOKEN_SIZE] = { 0, }; unsigned char transport_key_identifier[CCA_KEY_ID_SIZE] = { 0, }; uint16_t size_of_e; uint16_t mod_bits, mod_bytes, bytes; CK_ATTRIBUTE *opaque_key = NULL, *pub_exp = NULL, *mod = NULL, *p_prime=NULL, *q_prime=NULL, *dmp1=NULL, *dmq1=NULL, *iqmp=NULL; CK_RV rc; /* Look for parameters to set key in the CRT format */ if (!template_attribute_find(priv_tmpl, CKA_PRIME_1, &p_prime)) { TRACE_ERROR("CKA_PRIME_1 attribute missing for CRT.\n"); return CKR_TEMPLATE_INCOMPLETE; } total += p_prime->ulValueLen; if (!template_attribute_find(priv_tmpl, CKA_PRIME_2, &q_prime)) { TRACE_ERROR("CKA_PRIME_2 attribute missing for CRT.\n"); return CKR_TEMPLATE_INCOMPLETE; } total += q_prime->ulValueLen; if (!template_attribute_find(priv_tmpl, CKA_EXPONENT_1, &dmp1)) { TRACE_ERROR("CKA_EXPONENT_1 attribute missing for CRT.\n"); return CKR_TEMPLATE_INCOMPLETE; } total += dmp1->ulValueLen; if (!template_attribute_find(priv_tmpl, CKA_EXPONENT_2, &dmq1)) { TRACE_ERROR("CKA_EXPONENT_2 attribute missing for CRT.\n"); return CKR_TEMPLATE_INCOMPLETE; } total += dmq1->ulValueLen; if (!template_attribute_find(priv_tmpl, CKA_COEFFICIENT, &iqmp)) { TRACE_ERROR("CKA_COEFFICIENT attribute missing for CRT.\n"); return CKR_TEMPLATE_INCOMPLETE; } total += iqmp->ulValueLen; if (!template_attribute_find(priv_tmpl, CKA_PUBLIC_EXPONENT, &pub_exp)) { TRACE_ERROR("CKA_PUBLIC_EXPONENT attribute missing for CRT.\n"); return CKR_TEMPLATE_INCOMPLETE; } total += pub_exp->ulValueLen; if (!template_attribute_find(priv_tmpl, CKA_MODULUS, &mod)) { TRACE_ERROR("CKA_MODULUS attribute missing for CRT.\n"); return CKR_TEMPLATE_INCOMPLETE; } total += mod->ulValueLen; /* check total length does not exceed key_value_structure_length */ if ((total + 18) > key_value_structure_length) { TRACE_ERROR("total length of key exceeds CCA_KEY_VALUE_STRUCT_SIZE.\n"); return CKR_KEY_SIZE_RANGE; } /* Build key token for RSA-PRIV format. * Fields according to Table 9. * PKA_Key_Token_Build key-values-structure */ memset(key_value_structure, 0, key_value_structure_length); /* Field #1 - Length of modulus in bits */ mod_bits = htons(mod->ulValueLen * 8); memcpy(&key_value_structure[0], &mod_bits, sizeof(uint16_t)); /* Field #2 - Length of modulus field in bytes */ mod_bytes = htons(mod->ulValueLen); memcpy(&key_value_structure[2], &mod_bytes, sizeof(uint16_t)); /* Field #3 - Length of public exponent field in bytes */ size_of_e = htons(pub_exp->ulValueLen); memcpy(&key_value_structure[4], &size_of_e, sizeof(uint16_t)); /* Field #4 - Reserved, binary zero, two bytes */ /* Field #5 - Length of prime P */ bytes = htons(p_prime->ulValueLen); memcpy(&key_value_structure[8], &bytes, sizeof(uint16_t)); /* Field #6 - Length of prime Q */ bytes = htons(q_prime->ulValueLen); memcpy(&key_value_structure[10], &bytes, sizeof(uint16_t)); /* Field #7 - Length of dp in bytes */ bytes = htons(dmp1->ulValueLen); memcpy(&key_value_structure[12], &bytes, sizeof(uint16_t)); /* Field #8 - Length of dq in bytes */ bytes = htons(dmq1->ulValueLen); memcpy(&key_value_structure[14], &bytes, sizeof(uint16_t)); /* Field #9 - Length of U in bytes */ bytes = htons(iqmp->ulValueLen); memcpy(&key_value_structure[16], &bytes, sizeof(uint16_t)); /* Field #10 - Modulus */ memcpy(&key_value_structure[18], mod->pValue, mod_bytes); offset = 18 + mod_bytes; /* Field #11 - Public Exponent */ memcpy(&key_value_structure[offset], pub_exp->pValue, pub_exp->ulValueLen); offset += pub_exp->ulValueLen; /* Field #12 - Prime numer, p */ memcpy(&key_value_structure[offset], p_prime->pValue, p_prime->ulValueLen); offset += p_prime->ulValueLen; /* Field #13 - Prime numer, q */ memcpy(&key_value_structure[offset], q_prime->pValue, q_prime->ulValueLen); offset += q_prime->ulValueLen; /* Field #14 - dp = dmod(p-1) */ memcpy(&key_value_structure[offset], dmp1->pValue, dmp1->ulValueLen); offset += dmp1->ulValueLen; /* Field #15 - dq = dmod(q-1) */ memcpy(&key_value_structure[offset], dmq1->pValue, dmq1->ulValueLen); offset += dmq1->ulValueLen; /* Field #16 - U = (q^-1)mod(p) */ memcpy(&key_value_structure[offset], iqmp->pValue, iqmp->ulValueLen); /* Now build a key token with the imported public key */ rule_array_count = 2; memcpy(rule_array, "RSA-CRT KEY-MGMT", (size_t)(CCA_KEYWORD_SIZE * 2)); private_key_name_length = 0; key_token_length = CCA_KEY_TOKEN_SIZE; CSNDPKB(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &key_value_structure_length, key_value_structure, &private_key_name_length, private_key_name, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, &key_token_length, key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKB (RSA KEY TOKEN BUILD RSA CRT) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } /* Now import the PKA key token */ rule_array_count = 0; /* memcpy(rule_array, " ", (size_t)(CCA_KEYWORD_SIZE * 1)); */ target_key_token_length = CCA_KEY_TOKEN_SIZE; key_token_length = CCA_KEY_TOKEN_SIZE; CSNDPKI(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &key_token_length, key_token, transport_key_identifier, &target_key_token_length, target_key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKI (RSA KEY TOKEN IMPORT) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } /* Add the key object to the template */ if ((rc = build_attribute(CKA_IBM_OPAQUE, target_key_token, target_key_token_length, &opaque_key))) { TRACE_DEVEL("build_attribute failed\n"); return rc; } rc = template_update_attribute(priv_tmpl, opaque_key); if (rc != CKR_OK) { TRACE_DEVEL("template_update_attribute failed\n"); return rc; } return CKR_OK; } static CK_RV rsa_import_pubkey(TEMPLATE *publ_tmpl) { long return_code, reason_code, rule_array_count; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0, }; long key_value_structure_length = CCA_KEY_VALUE_STRUCT_SIZE; long private_key_name_length, key_token_length; unsigned char key_value_structure[CCA_KEY_VALUE_STRUCT_SIZE] = { 0, }; unsigned char private_key_name[CCA_PRIVATE_KEY_NAME_SIZE] = { 0, }; unsigned char key_token[CCA_KEY_TOKEN_SIZE] = { 0, }; uint16_t size_of_e; uint16_t mod_bits, mod_bytes; CK_ATTRIBUTE *opaque_key = NULL, *pub_exp = NULL; CK_ATTRIBUTE *pub_mod = NULL, *attr = NULL; CK_RV rc; /* check that modulus and public exponent are available */ if (!template_attribute_find(publ_tmpl, CKA_PUBLIC_EXPONENT, &pub_exp)){ TRACE_ERROR("CKA_PUBLIC_EXPONENT attribute missing.\n"); return CKR_TEMPLATE_INCOMPLETE; } if (!template_attribute_find(publ_tmpl, CKA_MODULUS, &pub_mod)) { TRACE_ERROR("CKA_MODULUS attribute missing.\n" ); return CKR_TEMPLATE_INCOMPLETE; } if (!template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr)) { TRACE_ERROR("CKA_MODULUS_BITS attribute missing.\n"); return CKR_TEMPLATE_INCOMPLETE; } /* check total length does not exceed key_value_structure_length */ if ((pub_mod->ulValueLen + 8) > key_value_structure_length) { TRACE_ERROR("total length of key exceeds CCA_KEY_VALUE_STRUCT_SIZE.\n"); return CKR_KEY_SIZE_RANGE; } /* In case the application hasn't filled it */ if (*(CK_ULONG *)attr->pValue == 0) mod_bits = htons(pub_mod->ulValueLen * 8); else mod_bits = htons(*(CK_ULONG *)attr->pValue); /* Build key token for RSA-PUBL format */ memset(key_value_structure, 0, key_value_structure_length); /* Fields according to Table 9. * PKA_Key_Token_Build key-values-structure */ /* Field #1 - Length of modulus in bits */ memcpy(&key_value_structure[0], &mod_bits, sizeof(uint16_t)); /* Field #2 - Length of modulus field in bytes */ mod_bytes = htons(pub_mod->ulValueLen); memcpy(&key_value_structure[2], &mod_bytes, sizeof(uint16_t)); /* Field #3 - Length of public exponent field in bytes */ size_of_e = htons((uint16_t)pub_exp->ulValueLen); memcpy(&key_value_structure[4], &size_of_e, sizeof(uint16_t)); /* Field #4 - private key exponent length; skip */ /* Field #5 - Modulus */ memcpy(&key_value_structure[8], pub_mod->pValue, (size_t)pub_mod->ulValueLen); /* Field #6 - Public exponent. Its offset depends on modulus size */ memcpy(&key_value_structure[8 + mod_bytes], pub_exp->pValue, (size_t)pub_exp->ulValueLen); /* Field #7 - Private exponent. Skip */ rule_array_count = 1; memcpy(rule_array, "RSA-PUBL", (size_t)(CCA_KEYWORD_SIZE * 1)); private_key_name_length = 0; key_token_length = CCA_KEY_TOKEN_SIZE; // Create a key token for the public key. // Public keys do not need to be wrapped, so just call PKB. CSNDPKB(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &key_value_structure_length, key_value_structure, &private_key_name_length, private_key_name, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, &key_token_length, key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNDPKB (RSA KEY TOKEN BUILD RSA-PUBL) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } // Add the key object to the template. if ((rc = build_attribute(CKA_IBM_OPAQUE, key_token, key_token_length, &opaque_key))) { TRACE_DEVEL("build_attribute failed\n"); return rc; } rc = template_update_attribute(publ_tmpl, opaque_key); if (rc != CKR_OK) { TRACE_DEVEL("template_update_attribute failed\n"); return rc; } return CKR_OK; } static CK_RV import_symmetric_key(OBJECT *object, CK_ULONG keytype) { CK_RV rc; long return_code, reason_code, rule_array_count; unsigned char target_key_id[CCA_KEY_ID_SIZE] = { 0 }; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0 }; CK_ATTRIBUTE *opaque_key = NULL; CK_ATTRIBUTE *attr = NULL; rc = template_attribute_find(object->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Incomplete key template\n"); return CKR_TEMPLATE_INCOMPLETE; } switch(keytype) { case CKK_AES: memcpy(rule_array, "AES ", CCA_KEYWORD_SIZE); break; case CKK_DES: case CKK_DES3: memcpy(rule_array, "DES ", CCA_KEYWORD_SIZE); break; default: return CKR_KEY_FUNCTION_NOT_PERMITTED; } rule_array_count = 1; CSNBCKM(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &attr->ulValueLen, attr->pValue, target_key_id); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBCKM failed. return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } /* Add the key object to the template */ if ((rc = build_attribute(CKA_IBM_OPAQUE, target_key_id, CCA_KEY_ID_SIZE, &opaque_key))) { TRACE_DEVEL("build_attribute(CKA_IBM_OPAQUE) failed\n"); return rc; } rc = template_update_attribute(object->template, opaque_key); if (rc != CKR_OK) { TRACE_DEVEL("template_update_attribute(CKA_IBM_OPAQUE) failed\n"); return rc; } /* zero clear key value */ memset(attr->pValue, 0, attr->ulValueLen); return CKR_OK; } static CK_RV import_generic_secret_key(OBJECT *object) { CK_RV rc; long return_code, reason_code, rule_array_count; unsigned char key_token[CCA_KEY_TOKEN_SIZE] = { 0 }; unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0 }; long key_name_len = 0, clr_key_len = 0; long user_data_len = 0, key_part_len = 0; long token_data_len = 0, verb_data_len = 0; long key_token_len = sizeof(key_token); CK_ATTRIBUTE *opaque_key = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG keylen; rc = template_attribute_find(object->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Incomplete Generic Secret (HMAC) key template\n"); return CKR_TEMPLATE_INCOMPLETE; } keylen = attr->ulValueLen; /* key len needs to be 80-2048 bits */ if (8*keylen < 80 || 8*keylen > 2048) { TRACE_ERROR("HMAC key size of %lu bits not within" " CCA required range of 80-2048 bits\n", 8*keylen); return CKR_KEY_SIZE_RANGE; } memcpy(rule_array, "INTERNALNO-KEY HMAC MAC GENERATE", 5 * CCA_KEYWORD_SIZE); rule_array_count = 5; CSNBKTB2(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &clr_key_len, NULL, &key_name_len, NULL, &user_data_len, NULL, &token_data_len, NULL, &verb_data_len, NULL, &key_token_len, key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBKTB2 (HMAC KEY TOKEN BUILD) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } memcpy(rule_array, "HMAC FIRST MIN1PART", 3 * CCA_KEYWORD_SIZE); rule_array_count = 3; key_part_len = keylen * 8; key_token_len = sizeof(key_token); CSNBKPI2(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &key_part_len, attr->pValue, &key_token_len, key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBKPI2 (HMAC KEY IMPORT FIRST) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } memcpy(rule_array, "HMAC COMPLETE", 2 * CCA_KEYWORD_SIZE); rule_array_count = 2; key_part_len = 0; key_token_len = sizeof(key_token); CSNBKPI2(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &key_part_len, NULL, &key_token_len, key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBKPI2 (HMAC KEY IMPORT COMPLETE) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } /* Add the key object to the template */ if ((rc = build_attribute(CKA_IBM_OPAQUE, key_token, key_token_len, &opaque_key))) { TRACE_DEVEL("build_attribute(CKA_IBM_OPAQUE) failed\n"); return rc; } rc = template_update_attribute(object->template, opaque_key); if (rc != CKR_OK) { TRACE_DEVEL("template_update_attribute(CKA_IBM_OPAQUE) failed\n"); return rc; } /* zero clear key value */ memset(attr->pValue, 0, attr->ulValueLen); return CKR_OK; } CK_RV token_specific_object_add(OBJECT *object) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_OBJECT_CLASS keyclass; if (!object) { TRACE_ERROR("Invalid argument\n"); return CKR_FUNCTION_FAILED; } rc = template_attribute_find(object->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { // not a key, so nothing to do. Just return. TRACE_DEVEL("object not a key, no need to import.\n"); return CKR_OK; } keytype = *(CK_KEY_TYPE *)attr->pValue; switch (keytype) { case CKK_RSA: rc = template_attribute_find(object->template, CKA_CLASS, &attr); if (rc == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } else keyclass = *(CK_OBJECT_CLASS *)attr->pValue; switch(keyclass) { case CKO_PUBLIC_KEY: // do import public key and create opaque object rc = rsa_import_pubkey(object->template); break; case CKO_PRIVATE_KEY: // do import keypair and create opaque object rc = rsa_import_privkey_crt(object->template); break; default: TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } if (rc != CKR_OK) { TRACE_DEVEL("rsa import failed\n"); return rc; } break; case CKK_AES: case CKK_DES: case CKK_DES3: rc = import_symmetric_key(object, keytype); if (rc != CKR_OK) { TRACE_DEVEL("Symmetric key import failed, rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } TRACE_INFO("symmetric key with len=%ld successful imported\n", attr->ulValueLen); break; case CKK_GENERIC_SECRET: rc = import_generic_secret_key(object); if (rc != CKR_OK) { TRACE_DEVEL("Generic Secret (HMAC) key import failed " " with rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } TRACE_INFO("Generic Secret (HMAC) key with len=%ld successfully" " imported\n", attr->ulValueLen); break; default: /* unknown/unsupported key type */ TRACE_ERROR("Unknown/unsupported key type 0x%lx\n", keytype); return CKR_KEY_FUNCTION_NOT_PERMITTED; } return CKR_OK; } CK_RV token_specific_generic_secret_key_gen (TEMPLATE *template) { CK_RV rc; long return_code, reason_code, rule_array_count; long zero_length = 0; long key_name_length = 0, clear_key_length = 0, user_data_length = 0; CK_ATTRIBUTE *opaque_key = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG keylength = 0; unsigned char key_type1[8] = {0}; unsigned char key_type2[8] = {0}; unsigned char key_token[CCA_KEY_TOKEN_SIZE] = { 0 }; long key_token_length = sizeof(key_token); unsigned char rule_array[CCA_RULE_ARRAY_SIZE] = { 0 }; rc = template_attribute_find(template, CKA_VALUE_LEN, &attr); if (rc == FALSE) { TRACE_ERROR("Incomplete Generic Secret (HMAC) key template\n"); return CKR_TEMPLATE_INCOMPLETE; } keylength = *(CK_ULONG *)attr->pValue; /* HMAC key length needs to be 80-2048 bits */ if (((8*keylength) < 80) || ((8*keylength) > 2048)) { TRACE_ERROR("HMAC key size of %lu bits not within CCA required " "range of 80-2048 bits\n", 8*keylength); return CKR_KEY_SIZE_RANGE; } rule_array_count = 4; memcpy(rule_array, "INTERNALHMAC MAC GENERATE", 4 * CCA_KEYWORD_SIZE); CSNBKTB2(&return_code, &reason_code, NULL, NULL, &rule_array_count, rule_array, &clear_key_length, NULL, &key_name_length, NULL, &user_data_length, NULL, &zero_length, NULL, &zero_length, NULL, &key_token_length, key_token); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBKTB2 (HMAC KEY TOKEN BUILD) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } /** generate the hmac key here **/ /* reset some values usually previously */ rule_array_count = 2; memset(rule_array, 0, sizeof(rule_array)); key_token_length = sizeof(key_token); /* create rule_array with 2 keywords */ memcpy(rule_array, "HMAC OP ", 2 * CCA_KEYWORD_SIZE); /* ask to create the hmac key with application * specified key length in bits */ clear_key_length = keylength * 8; memcpy(key_type1, "TOKEN ", CCA_KEYWORD_SIZE); /* for only one copy of key generated, specify 8 spaces in * key_type2 per CCA basic services guide */ memcpy(key_type2, " ", CCA_KEYWORD_SIZE); CSNBKGN2(&return_code, &reason_code, &zero_length, NULL, &rule_array_count, rule_array, &clear_key_length, key_type1, key_type2, &key_name_length, NULL, &key_name_length, NULL, &user_data_length, NULL, &user_data_length, NULL, &zero_length, NULL, &zero_length, NULL, &key_token_length, key_token, &zero_length, NULL); if (return_code != CCA_SUCCESS) { TRACE_ERROR("CSNBKGN2 (HMAC KEY GENERATE) failed." " return:%ld, reason:%ld\n", return_code, reason_code); return CKR_FUNCTION_FAILED; } /* Add the key object to the template */ rc = build_attribute(CKA_IBM_OPAQUE, key_token, key_token_length, &opaque_key); if (rc != CKR_OK) { TRACE_DEVEL("build_attribute(CKA_IBM_OPAQUE) failed\n"); return rc; } rc = template_update_attribute(template, opaque_key); if (rc != CKR_OK) { TRACE_DEVEL("template_update_attribute(CKA_IBM_OPAQUE) failed.\n"); return rc; } return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/cca_stdll/defs.h0000755000175000017500000000137712630407154021015 0ustar xnoxxnox /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ // File: defs.h // // Contains various definitions needed by both the host-side // and coprocessor-side code. // #ifndef _CCA_DEFS_H #define _CCA_DEFS_H #include "../common/defs.h" #undef MAX_PIN_LEN #undef MIN_PIN_LEN #define MAX_PIN_LEN 128 #define MIN_PIN_LEN 4 #define CCA_CHAIN_VECTOR_LEN 128 #define CCA_HASH_PART_FIRST 0 #define CCA_HASH_PART_MIDDLE 1 #define CCA_HASH_PART_LAST 2 #define CCA_HASH_PART_ONLY 3 struct cca_sha_ctx { unsigned char chain_vector[CCA_CHAIN_VECTOR_LEN]; long chain_vector_len; unsigned char tail[MAX_SHA_BLOCK_SIZE]; long tail_len; unsigned char hash[MAX_SHA_HASH_SIZE]; long hash_len; int part; }; #endif opencryptoki+dfsg/usr/lib/pkcs11/cca_stdll/cca_stdll.h0000644000175000017500000000636412630407154022022 0ustar xnoxxnox /* * Licensed materials, Property of IBM Corp. * * openCryptoki CCA token * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2006 * * Author: Kent E. Yoder * */ #ifndef __CCA_STDLL_H__ #define __CCA_STDLL_H__ /* CCA library constants */ #define CCA_PRIVATE_KEY_NAME_SIZE 64 #define CCA_REGENERATION_DATA_SIZE 64 #define CCA_KEY_TOKEN_SIZE 2500 #define CCA_KEY_VALUE_STRUCT_SIZE 2500 #define CCA_RULE_ARRAY_SIZE 256 #define CCA_KEYWORD_SIZE 8 #define CCA_KEY_ID_SIZE 64 #define CCA_RNG_SIZE 8 #define CCA_OCV_SIZE 18 #define CCA_SUCCESS 0 #define CCA_PKB_E_OFFSET 18 #define CCA_PKB_E_SIZE 2 #define CCA_PKB_E_SIZE_OFFSET 4 #define CCA_CHAIN_VECTOR_LEN 128 /* Elliptic Curve constants */ /* CCA spec: page 94 */ #define CCA_EC_KEY_VALUE_STRUCT_SIZE 8 #define CCA_PKB_EC_TYPE_OFFSET 0 #define CCA_PKB_EC_LEN_OFFSET 2 #define CCA_PKB_EC_PRIV_KEY_LEN_OFFSET 4 #define CCA_PKB_EC_PUBL_KEY_LEN_OFFSET 6 #define CCATOK_EC_MAX_D_LEN 66 #define CCATOK_EC_MAX_Q_LEN 133 /* Key token generated by CSNDPKG */ /* CCA spec: page 460 & 470 & 471 */ #define CCA_PRIVKEY_ID 0x20 #define CCA_PUBLKEY_ID 0x21 #define CCA_SECTION_LEN_OFFSET 2 #define CCA_EC_HEADER_SIZE 8 #define CCA_PRIV_P_LEN_OFFSET 12 #define CCA_PUBL_P_LEN_OFFSET 10 /* Offset into the EC public key section to length of q */ #define CCA_EC_INTTOK_PUBKEY_Q_LEN_OFFSET 12 /* Offset into the EC public key section to q */ #define CCA_EC_INTTOK_PUBKEY_Q_OFFSET 14 /* CCA Internal Key Token parsing constants */ /* Size of an RSA internal key token header */ #define CCA_RSA_INTTOK_HDR_LENGTH 8 /* Offset into an RSA internal key token of the private key area */ #define CCA_RSA_INTTOK_PRIVKEY_OFFSET 8 /* Offset into an RSA key area of the total length */ #define CCA_RSA_INTTOK_PRIVKEY_LENGTH_OFFSET 2 #define CCA_RSA_INTTOK_PUBKEY_LENGTH_OFFSET 2 /* Offset into an RSA private key area of the length of n, the modulus */ #define CCA_RSA_INTTOK_PRIVKEY_N_LENGTH_OFFSET 64 /* Offset into an RSA public key area of the length of e, the public exponent */ #define CCA_RSA_INTTOK_PUBKEY_E_LENGTH_OFFSET 6 /* Offset into an RSA public key area of the value of e, the public exponent */ #define CCA_RSA_INTTOK_PUBKEY_E_OFFSET 12 /* Offset into the rule_array returned by the STATCCAE command for the * Current Symmetric Master Key register status */ #define CCA_STATCCAE_SYM_CMK_OFFSET 8 /* Offset into the rule_array returned by the STATCCAE command for the * Current Asymmetric Master Key register status */ #define CCA_STATCCAE_ASYM_CMK_OFFSET 56 /* CCA STDLL constants */ #define CCATOK_MAX_N_LEN 512 #define CCATOK_MAX_E_LEN 256 enum cca_key_type { CCA_AES_KEY, CCA_DES_KEY }; /* CCA STDLL debug logging definitions */ #ifdef DEBUG #define CCADBG(fn, rc, reason) ock_logit("CCA_TOK DEBUG %s:%d %s failed. return: %ld, reason: %ld\n", __FUNCTION__, __LINE__, fn, rc, reason) #define DBG(fmt, ...) ock_logit("CCA_TOK DEBUG %s:%d %s " fmt "\n", \ __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) #else #define CCADBG(...) do { } while (0) #define DBG(...) do { } while (0) #endif #endif opencryptoki+dfsg/usr/lib/pkcs11/cca_stdll/tok_struct.h0000644000175000017500000000616612630407154022273 0ustar xnoxxnox /* * Licensed materials, Property of IBM Corp. * * openCryptoki CCA token * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2006 * */ #ifndef __TOK_STRUCT_H #define __TOK_STRUCT_H #include #include "tok_spec_struct.h" #ifndef CCA_CONFIG_PATH #ifndef CONFIG_PATH #warning CONFIG_PATH not set, using default (/usr/local/var/lib/opencryptoki) #define CONFIG_PATH "/usr/local/var/lib/opencryptoki" #endif // #ifndef CONFIG_PATH #define CCA_CONFIG_PATH CONFIG_PATH "/ccatok" #endif // #ifndef CCA_CONFIG_PATH token_spec_t token_specific = { CCA_CONFIG_PATH, "ccatok", 64, // Token data info: { FALSE, // Don't use per guest data store TRUE, // Use master key CKM_DES3_CBC, // Data store encryption "12345678", // Default initialization vector for pins "10293847", // Default initialization vector for objects }, NULL, // creatlock NULL, // attach_shm &token_specific_init, NULL, // init_token_data NULL, // load_token_data NULL, // save_token_data &token_specific_rng, &token_specific_final, NULL, // init_token NULL, // login NULL, // logout NULL, // init_pin NULL, // set_pin // DES &token_specific_des_key_gen, &token_specific_des_ecb, &token_specific_des_cbc, // Triple DES &token_specific_tdes_ecb, &token_specific_tdes_cbc, NULL, // tdes_ofb NULL, // tdes_cfb NULL, // tdes_mac // RSA &token_specific_rsa_decrypt, &token_specific_rsa_encrypt, &token_specific_rsa_sign, &token_specific_rsa_verify, NULL, // rsa_verify_recover NULL, // rsa_x509_decrypt NULL, // rsa_x509_encrypt NULL, // rsa_x509_sign NULL, // rsa_x509_verify NULL, // rsa_x509_verify_recover NULL, // rsa_oaep_decrypt NULL, // rsa_oaep_encrypt NULL, // rsa_pss_sign NULL, // rsa_pss_verify &token_specific_rsa_generate_keypair, // Elliptic Curve &token_specific_ec_sign, &token_specific_ec_verify, &token_specific_ec_generate_keypair, #ifndef NODH /* Begin code contributed by Corrent corp. */ // DH &token_specific_dh_pkcs_derive, &token_specific_dh_pkcs_key_pair_gen, /* End code contributed by Corrent corp. */ #else NULL, NULL, #endif // SHA token_specific_sha_init, token_specific_sha, token_specific_sha_update, token_specific_sha_final, // HMAC &token_specific_hmac_sign_init, &token_specific_hmac_sign, &token_specific_hmac_sign_update, &token_specific_hmac_sign_final, &token_specific_hmac_verify_init, &token_specific_hmac_verify, &token_specific_hmac_verify_update, &token_specific_hmac_verify_final, &token_specific_generic_secret_key_gen, #ifndef NOAES // AES &token_specific_aes_key_gen, &token_specific_aes_ecb, &token_specific_aes_cbc, #else NULL, NULL, NULL, #endif NULL, // aes_ctr NULL, // aes_gcm_init, NULL, // aes_gcm NULL, // aes_gcm_update NULL, // aes_gcm_final NULL, // aes_ofb NULL, // aes_cfb NULL, // aes_mac // DSA NULL, // dsa_generate_keypair NULL, // dsa_sign NULL, // dsa_verify &token_specific_get_mechanism_list, &token_specific_get_mechanism_info, &token_specific_object_add }; #endif opencryptoki+dfsg/usr/lib/pkcs11/cca_stdll/LICENSE0000644000175000017500000002653512630407154020730 0ustar xnoxxnoxCommon Public License Version 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. opencryptoki+dfsg/usr/lib/pkcs11/cca_stdll/csulincl.h0000644000175000017500000016313112630407154021702 0ustar xnoxxnox/******************************************************************************/ /* Licensed Materials Property of IBM */ /* (C) Copyright IBM Corporation, 1997, 2005 */ /* All Rights Reserved */ /* US Government Users Restricted Rights - */ /* Use, duplication or disclosure restricted by */ /* GSA ADP Schedule Contract with IBM Corp. */ /******************************************************************************/ /* */ /* This header file contains the Security API C language */ /* prototypes. See the user publications for more information. */ /* */ /******************************************************************************/ #ifndef __CSULINCL #define __CSULINCL /* * define system linkage macros for the target platform */ #define SECURITYAPI /* * define system linkage to the security API */ #define CSNBCKI CSNBCKI_32 #define CSNBCKM CSNBCKM_32 #define CSNBDKX CSNBDKX_32 #define CSNBDKM CSNBDKM_32 #define CSNBMKP CSNBMKP_32 #define CSNBKEX CSNBKEX_32 #define CSNBKGN CSNBKGN_32 #define CSNBKGN2 CSNBKGN2_32 #define CSNBKIM CSNBKIM_32 #define CSNBKPI CSNBKPI_32 #define CSNBKPI2 CSNBKPI2_32 #define CSNBKRC CSNBKRC_32 #define CSNBAKRC CSNBAKRC_32 #define CSNBKRD CSNBKRD_32 #define CSNBKRL CSNBKRL_32 #define CSNBKRR CSNBKRR_32 #define CSNBKRW CSNBKRW_32 #define CSNDKRC CSNDKRC_32 #define CSNDKRD CSNDKRD_32 #define CSNDKRL CSNDKRL_32 #define CSNDKRR CSNDKRR_32 #define CSNDKRW CSNDKRW_32 #define CSNBKYT CSNBKYT_32 #define CSNBKSI CSNBKSI_32 #define CSNBKTC CSNBKTC_32 #define CSNBKTR CSNBKTR_32 #define CSNBRNG CSNBRNG_32 #define CSNBDEC CSNBDEC_32 #define CSNBENC CSNBENC_32 #define CSNBMGN CSNBMGN_32 #define CSNBMVR CSNBMVR_32 #define CSNBKTB CSNBKTB_32 #define CSNBKTB2 CSNBKTB2_32 #define CSNDPKG CSNDPKG_32 #define CSNDPKB CSNDPKB_32 #define CSNBOWH CSNBOWH_32 #define CSNDPKI CSNDPKI_32 #define CSNDDSG CSNDDSG_32 #define CSNDDSV CSNDDSV_32 #define CSNDKTC CSNDKTC_32 #define CSNDPKX CSNDPKX_32 #define CSNDSYI CSNDSYI_32 #define CSNDSYX CSNDSYX_32 #define CSUACFQ CSUACFQ_32 #define CSUACFC CSUACFC_32 #define CSNDSBC CSNDSBC_32 #define CSNDSBD CSNDSBD_32 #define CSUALCT CSUALCT_32 #define CSUAACM CSUAACM_32 #define CSUAACI CSUAACI_32 #define CSNDPKH CSNDPKH_32 #define CSNDPKR CSNDPKR_32 #define CSUAMKD CSUAMKD_32 #define CSNDRKD CSNDRKD_32 #define CSNDRKL CSNDRKL_32 #define CSNBPTR CSNBPTR_32 #define CSNBCPE CSNBCPE_32 #define CSNBCPA CSNBCPA_32 #define CSNBPGN CSNBPGN_32 #define CSNBPVR CSNBPVR_32 #define CSNDSYG CSNDSYG_32 #define CSNBDKG CSNBDKG_32 #define CSNBEPG CSNBEPG_32 #define CSNBCVE CSNBCVE_32 #define CSNBCSG CSNBCSG_32 #define CSNBCSV CSNBCSV_32 #define CSNBCVG CSNBCVG_32 #define CSNBKTP CSNBKTP_32 #define CSNDPKE CSNDPKE_32 #define CSNDPKD CSNDPKD_32 #define CSNBPEX CSNBPEX_32 #define CSNBPEXX CSNBPEXX_32 #define CSUARNT CSUARNT_32 #define CSNBCVT CSNBCVT_32 #define CSNBMDG CSNBMDG_32 #define CSUACRA CSUACRA_32 #define CSUACRD CSUACRD_32 #define CSNBTRV CSNBTRV_32 #define CSUAPCV CSUAPCV_32 #define CSNBKYTX CSNBKYTX_32 #define CSNBSPN CSNBSPN_32 #define CSNBSKY CSNBSKY_32 #define CSNBPCU CSNBPCU_32 #define CSUAPRB CSUAPRB_32 #define CSUADHK CSUADHK_32 #define CSUADHQ CSUADHQ_32 #define CSNDTBC CSNDTBC_32 #define CSNDRKX CSNDRKX_32 #define CSNBKET CSNBKET_32 #define CSNBSAE CSNBSAE_32 #define CSNBSAD CSNBSAD_32 #define CSNBHMG CSNBHMG_32 #define CSNBHMV CSNBHMV_32 /* * security API prototypes */ /* Clear Key Import */ extern void SECURITYAPI CSNBCKI_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * clear_key, unsigned char * target_key_identifier); /* Clear Key Import Multiple */ extern void SECURITYAPI CSNBCKM_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * clear_key_length, unsigned char * clear_key, unsigned char * target_key_identifier); /* Data Key Export */ extern void SECURITYAPI CSNBDKX_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * source_key_identifier, unsigned char * exporter_key_identifier, unsigned char * target_key_token); /* Data Key Import */ extern void SECURITYAPI CSNBDKM_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * source_key_token, unsigned char * importer_key_identifier, unsigned char * target_key_identifier); /* DES Master Key Process */ extern void SECURITYAPI CSNBMKP_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_part); /* Key Export */ extern void SECURITYAPI CSNBKEX_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_type, unsigned char * source_key_identifier, unsigned char * exporter_key_identifier, unsigned char * target_key_token); /* Key Generate */ extern void SECURITYAPI CSNBKGN_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_form, unsigned char * key_length, unsigned char * key_type_1, unsigned char * key_type_2, unsigned char * KEK_key_identifier_1, unsigned char * KEK_key_identifier_2, unsigned char * generated_key_identifier_1, unsigned char * generated_key_identifier_2); /* Key Generate2 */ extern void SECURITYAPI CSNBKGN2_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * clear_key_bit_length, unsigned char * key_type_1, unsigned char * key_type_2, long * key_name_1_length, unsigned char * key_name_1, long * key_name_2_length, unsigned char * key_name_2, long * user_associated_data_1_length, unsigned char * user_associated_data_1, long * user_associated_data_2_length, unsigned char * user_associated_data_2, long * key_encrypting_key_identifier_1_length, unsigned char * key_encrypting_key_identifier_1, long * key_encrypting_key_identifier_2_length, unsigned char * key_encrypting_key_identifier_2, long * generated_key_identifier_1_length, unsigned char * generated_key_identifier_1, long * generated_key_identifier_2_length, unsigned char * generated_key_identifier_2); /* Key Import */ extern void SECURITYAPI CSNBKIM_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_type, unsigned char * source_key_token, unsigned char * importer_key_identifier, unsigned char * target_key_identifier); /* Key Part Import */ extern void SECURITYAPI CSNBKPI_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_part, unsigned char * key_identifier); /* Key Part Import2 */ extern void SECURITYAPI CSNBKPI2_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * clear_key_part_length, unsigned char * clear_key_part, long * key_identifier_length, unsigned char * key_identifier); /* Key Storage Initialization */ extern void SECURITYAPI CSNBKSI_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * file_name_length, unsigned char * file_name, long * description_length, unsigned char * description, unsigned char * clear_master_key); /* Key Record Create */ extern void SECURITYAPI CSNBKRC_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_label); /* AES Key Record Create */ extern void SECURITYAPI CSNBAKRC_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_label, long * key_token_length, unsigned char * key_token); /* Key Record Delete */ extern void SECURITYAPI CSNBKRD_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_identifier); /* Key Record List */ extern void SECURITYAPI CSNBKRL_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_label, long * data_set_name_length, unsigned char * data_set_name, unsigned char * security_server_name); /* Key Record Read */ extern void SECURITYAPI CSNBKRR_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_label, unsigned char * key_token); /* Key Record Write */ extern void SECURITYAPI CSNBKRW_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_token, unsigned char * key_label); /* PKA Key Record Create */ extern void SECURITYAPI CSNDKRC_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_label, long * key_token_length, unsigned char * key_token); /* PKA Key Record Delete */ extern void SECURITYAPI CSNDKRD_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_identifier); /* PKA Key Record List */ extern void SECURITYAPI CSNDKRL_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_label, long * data_set_name_length, unsigned char * data_set_name, unsigned char * security_server_name); /* PKA Key Record Read */ extern void SECURITYAPI CSNDKRR_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_label, long * key_token_length, unsigned char * key_token); /* PKA Key Record Write */ extern void SECURITYAPI CSNDKRW_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_label, long * key_token_length, unsigned char * key_token ); /* Key Test */ extern void SECURITYAPI CSNBKYT_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_identifier, unsigned char * random_number, unsigned char * verification_pattern); /* Key Test Extended @b3a*/ extern void SECURITYAPI CSNBKYTX_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_identifier, unsigned char * random_number, unsigned char * verification_pattern, unsigned char * kek_key_identifier); /* Des Key Token Change */ extern void SECURITYAPI CSNBKTC_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_identifier); /* Key Translate */ extern void SECURITYAPI CSNBKTR_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * input_key_token, unsigned char * input_KEK_key_identifier, unsigned char * output_KEK_key_identifier, unsigned char * output_key_token); /* Random Number Generate */ extern void SECURITYAPI CSNBRNG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * form, unsigned char * random_number); extern void SECURITYAPI CSNBSAE_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * key_identifier_length, unsigned char * key_identifier, long * key_params_length, unsigned char * key_params, long * block_size, long * initialization_vector_length, unsigned char * initialization_vector, long * chaining_vector_length, unsigned char * chaining_vector, long * text_length, unsigned char * text, long * ciphertext_length, unsigned char * ciphertext, long * optional_data_length, unsigned char * optional_data); extern void SECURITYAPI CSNBSAD_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * key_identifier_length, unsigned char * key_identifier, long * key_params_length, unsigned char * key_params, long * block_size, long * initialization_vector_length, unsigned char * initialization_vector, long * chaining_vector_length, unsigned char * chaining_vector, long * ciphertext_length, unsigned char * ciphertext, long * text_length, unsigned char * text, long * optional_data_length, unsigned char * optional_data); /* Decipher */ extern void SECURITYAPI CSNBDEC_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_identifier, long * text_length, unsigned char * ciphertext, unsigned char * initialization_vector, long * rule_array_count, unsigned char * rule_array, unsigned char * chaining_vector, unsigned char * plaintext); /* Encipher */ extern void SECURITYAPI CSNBENC_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_identifier, long * text_length, unsigned char * plaintext, unsigned char * initialization_vector, long * rule_array_count, unsigned char * rule_array, long * pad_character, unsigned char * chaining_vector, unsigned char * ciphertext); /* MAC Generate */ extern void SECURITYAPI CSNBMGN_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_identifier, long * text_length, unsigned char * text, long * rule_array_count, unsigned char * rule_array, unsigned char * chaining_vector, unsigned char * MAC); /* MAC Verify */ extern void SECURITYAPI CSNBMVR_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_identifier, long * text_length, unsigned char * text, long * rule_array_count, unsigned char * rule_array, unsigned char * chaining_vector, unsigned char * MAC); /* Key Token Build */ extern void SECURITYAPI CSNBKTB_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_token, unsigned char * key_type, long * rule_array_count, unsigned char * rule_array, unsigned char * key_value, void * reserved_field_1, long * reserved_field_2, unsigned char * reserved_field_3, unsigned char * control_vector, unsigned char * reserved_field_4, long * reserved_field_5, unsigned char * reserved_field_6, unsigned char * master_key_verification_number ); /* Key Token Build2 */ extern void SECURITYAPI CSNBKTB2_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * clear_key_bit_length, unsigned char * clear_key_value, long * key_name_length, unsigned char * key_name, long * user_associated_data_length, unsigned char * user_associated_data, long * token_data_length, unsigned char * token_data, long * reserved_length, unsigned char * reserved, long * target_key_token_length, unsigned char * target_key_token); /* PKA Key Generate */ extern void SECURITYAPI CSNDPKG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * regeneration_data_length, unsigned char * regeneration_data, long * skeleton_key_token_length, unsigned char * skeleton_key_token, unsigned char * transport_key_identifier, long * generated_key_identifier_length, unsigned char * generated_key_identifier); /* PKA Key Token Build */ extern void SECURITYAPI CSNDPKB_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * key_values_structure_length, unsigned char * key_values_structure, long * key_name_ln, unsigned char * key_name, long * reserved_1_length, unsigned char * reserved_1, long * reserved_2_length, unsigned char * reserved_2, long * reserved_3_length, unsigned char * reserved_3, long * reserved_4_length, unsigned char * reserved_4, long * reserved_5_length, unsigned char * reserved_5, long * token_length, unsigned char * token); /* One Way Hash */ extern void SECURITYAPI CSNBOWH_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * text_length, unsigned char * text, long * chaining_vector_length, unsigned char * chaining_vector, long * hash_length, unsigned char * hash); /* PKA Key Import */ extern void SECURITYAPI CSNDPKI_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * source_key_token_length, unsigned char * source_key_token, unsigned char * importer_key_identifier, long * target_key_identifier_length, unsigned char * target_key_identifier); /* Digital Signature Generate */ extern void SECURITYAPI CSNDDSG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * PKA_private_key_id_length, unsigned char * PKA_private_key_id, long * hash_length, unsigned char * hash, long * signature_field_length, long * signature_bit_length, unsigned char * signature_field); /* Digital Signature Verify */ extern void SECURITYAPI CSNDDSV_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * PKA_public_key_id_length, unsigned char * PKA_public_key_id, long * hash_length, unsigned char * hash, long * signature_field_length, unsigned char * signature_field); /* PKA Key Token Change */ extern void SECURITYAPI CSNDKTC_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * key_id_length, unsigned char * key_id); /* PKA Public Key Extract */ extern void SECURITYAPI CSNDPKX_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * source_key_identifier_length, unsigned char * source_key_identifier, long * target_key_token_length, unsigned char * target_key_token); /* PKA Symmetric Key Import */ extern void SECURITYAPI CSNDSYI_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * RSA_enciphered_key_length, unsigned char * RSA_enciphered_key, long * RSA_private_key_identifier_len, unsigned char * RSA_private_key_identifier, long * target_key_identifier_length, unsigned char * target_key_identifier); /* PKA Symmetric Key Export */ extern void SECURITYAPI CSNDSYX_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * source_key_identifier_length, unsigned char * source_key_identifier, long * RSA_public_key_identifier_len, unsigned char * RSA_public_key_identifier, long * RSA_enciphered_key_length, unsigned char * RSA_enciphered_key); /* Crypto Facility Query */ extern void CSUACFQ_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * verb_data_length, unsigned char * verb_data); /* Crypto Facility Control */ extern void SECURITYAPI CSUACFC_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * verb_data_length, unsigned char * verb_data); /* Compose SET Block */ extern void SECURITYAPI CSNDSBC_32(long * ReturnCode, long * ReasonCode, long * ExitDataLength, unsigned char * ExitData, long * RuleArrayCount, unsigned char * RuleArray, unsigned char * BlockContentsIdentifier, long * XDataStringLength, unsigned char * XDataString, long * DataToEncryptLength, unsigned char * DataToEncrypt, long * DataToHashLength, unsigned char * DataToHash, unsigned char * InitializationVector, long * RSAPublicKeyIdentifierLength, unsigned char * RSAPublicKeyIdentifier, long * DESKeyBLockLength, unsigned char * DESKeyBlock, long * RSAOAEPBlockLength, unsigned char * RSAOAEPBlock, unsigned char * ChainingVector, unsigned char * DESEncryptedDataBlock ); /* Decompose SET Block */ extern void SECURITYAPI CSNDSBD_32(long * ReturnCode, long * ReasonCode, long * ExitDataLength, unsigned char * ExitData, long * RuleArrayCount, unsigned char * RuleArray, long * RSAOAEPBlockLength, unsigned char * RSAOAEPBlock, long * DESEncryptedDataBlockLength, unsigned char * DESEncryptedDataBlock, unsigned char * InitializationVector, long * RSAPrivateKeyIdentifierLength, unsigned char * RSAPrivateKeyIdentifier, long * DESKeyBLockLength, unsigned char * DESKeyBlock, unsigned char * BlockContentsIdentifier, long * XDataStringLength, unsigned char * XDataString, unsigned char * ChainingVector, unsigned char * DataBlock, long * HashBlockLength, unsigned char * HashBlock ); /* Access Control Logon */ extern void SECURITYAPI CSUALCT_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * user_id, long * auth_parm_length, unsigned char * auth_parm, long * auth_data_length, unsigned char * auth_data); /* Access Control Maintenance */ extern void SECURITYAPI CSUAACM_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * name, long * output_data_length, unsigned char * output_data); /* Access Control Initialization */ extern void SECURITYAPI CSUAACI_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * verb_data_1_length, unsigned char * verb_data_1, long * verb_data_2_length, unsigned char * verb_data_2); /* PKA Public Key Hash Register */ extern void SECURITYAPI CSNDPKH_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * public_key_name, long * hash_data_length, unsigned char * hash_data); /* PKA Public Key Register */ extern void SECURITYAPI CSNDPKR_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * public_key_name, long * public_key_certificate_length, unsigned char * public_key_certificate); /* Master Key Distribution */ extern void SECURITYAPI CSUAMKD_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * share_index, unsigned char * private_key_name, unsigned char * certifying_key_name, long * certificate_length, unsigned char * certificate, long * clone_info_encrypting_key_length, unsigned char * clone_info_encrypting_key, long * clone_info_length, unsigned char * clone_info); /* Retained Key Delete */ extern void SECURITYAPI CSNDRKD_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_label); /* Retained Key List */ extern void SECURITYAPI CSNDRKL_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_label_mask, long * retained_keys_count, long * key_labels_count, unsigned char * key_labels); /* Symmetric Key Generate */ extern void SECURITYAPI CSNDSYG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * key_encrypting_key, long * rsapub_key_length, unsigned char * rsapub_key, long * locenc_key_length, unsigned char * locenc_key, long * rsaenc_key_length, unsigned char * rsaenc_key); /* Encrypted PIN Translate */ extern void SECURITYAPI CSNBPTR_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * in_PIN_enc_key_id, unsigned char * out_PIN_enc_key_id, unsigned char * in_PIN_profile, unsigned char * in_PAN_data, unsigned char * in_PIN_blk, long * rule_array_count, unsigned char * rule_array, unsigned char * out_PIN_profile, unsigned char * out_PAN_data, long * sequence_number, unsigned char * put_PIN_blk); /* Clear PIN Encrypt */ extern void SECURITYAPI CSNBCPE_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * PIN_enc_key_id, long * rule_array_count, unsigned char * rule_array, unsigned char * clear_PIN, unsigned char * PIN_profile, unsigned char * PAN_data, long * sequence_number, unsigned char * encrypted_PIN_blk); /* Clear PIN Generate Alternate */ extern void SECURITYAPI CSNBCPA_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * PIN_enc_key_id, unsigned char * PIN_gen_key_id, unsigned char * PIN_profile, unsigned char * PAN_data, unsigned char * encrypted_PIN_blk, long * rule_array_count, unsigned char * rule_array, long * PIN_check_length, unsigned char * data_array, unsigned char * returned_result); /* Clear PIN Generate */ extern void SECURITYAPI CSNBPGN_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * PIN_gen_key_id, long * rule_array_count, unsigned char * rule_array, long * PIN_length, long * PIN_check_length, unsigned char * data_array, unsigned char * returned_result); /* Encrypted PIN Verify */ extern void SECURITYAPI CSNBPVR_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * PIN_enc_key_id, unsigned char * PIN_ver_key_id, unsigned char * PIN_profile, unsigned char * PAN_data, unsigned char * encrypted_PIN_blk, long * rule_array_count, unsigned char * rule_array, long * PIN_check_length, unsigned char * data_array); /* Diversified Key Generate */ extern void SECURITYAPI CSNBDKG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * generating_key_id, long * data_length, unsigned char * data, unsigned char * decrypting_key_id, unsigned char * generated_key_id); /* Encrypted PIN Generate */ extern void SECURITYAPI CSNBEPG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * PIN_gen_key_id, unsigned char * outPIN_enc_key_id, long * rule_array_count, unsigned char * rule_array, long * PIN_length, unsigned char * data_array, unsigned char * outPIN_profile, unsigned char * PAN_data, long * sequence_number, unsigned char * encrypted_PIN_blk); /* Cryptographic Variable Encipher */ extern void SECURITYAPI CSNBCVE_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * cvarenc_key_id, long * text_length, unsigned char * plain_text, unsigned char * init_vector, unsigned char * cipher_text); /* CVV Generate */ extern void SECURITYAPI CSNBCSG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * PAN_data, unsigned char * expiration_date, unsigned char * service_code, unsigned char * key_a_id, unsigned char * key_b_id, unsigned char * generated_cvv); /* CVV Verify */ extern void SECURITYAPI CSNBCSV_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * PAN_data, unsigned char * expiration_date, unsigned char * service_code, unsigned char * key_a_id, unsigned char * key_b_id, unsigned char * generated_cvv); /* Control Vector Generate */ extern void SECURITYAPI CSNBCVG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_type, long * rule_array_count, unsigned char * rule_array, unsigned char * reserved_field_1, unsigned char * control_vector); /* Key Token Parse */ extern void SECURITYAPI CSNBKTP_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_token, unsigned char * key_type, long * rule_array_count, unsigned char * rule_array, unsigned char * key_value, void * master_key_verification_pattern_v03, long * reserved_field_1, unsigned char * reserved_field_2, unsigned char * control_vector, unsigned char * reserved_field_3, long * reserved_field_4, unsigned char * reserved_field_5, unsigned char * master_key_verification_pattern_v00); /* PKA Encrypt */ extern void SECURITYAPI CSNDPKE_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * key_value_length, unsigned char * key_value, long * data_struct_length, unsigned char * data_struct, long * RSA_public_key_length, unsigned char * RSA_public_key, long * RSA_encipher_length, unsigned char * RSA_encipher); /* PKA Decrypt */ extern void SECURITYAPI CSNDPKD_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * enciphered_key_length, unsigned char * enciphered_key, long * data_struct_length, unsigned char * data_struct, long * RSA_private_key_length, unsigned char * RSA_private_key, long * key_value_length, unsigned char * key_value); /* Prohibit Export */ extern void SECURITYAPI CSNBPEX_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * key_identifier); /* Prohibit Export Extended */ extern void SECURITYAPI CSNBPEXX_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * Source_key_token, unsigned char * Kek_key_identifier); /* Random Number/Known Answer Test */ extern void SECURITYAPI CSUARNT_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array); /* Control Vector Translate */ extern void SECURITYAPI CSNBCVT_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, unsigned char * kek_key_identifier, unsigned char * source_key_token, unsigned char * array_key_left, unsigned char * mask_array_left, unsigned char * array_key_right, unsigned char * mask_array_right, long * rule_array_count, unsigned char * rule_array, unsigned char * target_key_token); /* MDC Generate */ extern void SECURITYAPI CSNBMDG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * text_length, unsigned char * text_data, long * rule_array_count, unsigned char * rule_array, unsigned char * chaining_vector, unsigned char * MDC); /* Cryptographic Resource Allocate */ extern void SECURITYAPI CSUACRA_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * resource_name_length, unsigned char * resource_name); /* Cryptographic Resource Deallocate */ extern void SECURITYAPI CSUACRD_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * resource_name_length, unsigned char * resource_name); /* Transaction Validation */ extern void SECURITYAPI CSNBTRV_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * transaction_key_length, unsigned char * transaction_key, long * transaction_info_length, unsigned char * transaction_info, long * validation_values_length, unsigned char * validation_values); /* Secure Messaging for Keys */ extern void SECURITYAPI CSNBSKY_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * input_key_indentifier, unsigned char * key_encrypting_key, unsigned char * session_key, long * text_length, unsigned char * clear_text, unsigned char * initialization_vector, long * key_offset, long * key_offset_field_length, unsigned char * cipher_text, unsigned char * output_chaining_value); /* Secure Messaging for PINs */ extern void SECURITYAPI CSNBSPN_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, unsigned char * in_PIN_blk, unsigned char * in_PIN_enc_key_id, unsigned char * in_PIN_profile, unsigned char * in_PAN_data, unsigned char * secmsg_key, unsigned char * out_PIN_profile, unsigned char * out_PAN_data, long * text_length, unsigned char * clear_text, unsigned char * initialization_vector, long * PIN_offset, long * PIN_offset_field_length, unsigned char * cipher_text, unsigned char * output_chaining_value); /* PIN Change/Unblock */ extern void SECURITYAPI CSNBPCU_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * authenticationMasterKeyLength, unsigned char * authenticationMasterKey, long * issuerMasterKeyLength, unsigned char * issuerMasterKey, long * keyGenerationDataLength, unsigned char * keyGenerationData, long * newRefPinKeyLength, unsigned char * newRefPinKey, unsigned char * newRefPinBlock, unsigned char * newRefPinProfile, unsigned char * newRefPanData, long * currentRefPinKeyLength, unsigned char * currentRefPinKey, unsigned char * currentRefPinBlock, unsigned char * currentRefPinProfile, unsigned char * currentRefPanData, long * outputPinDataLength, unsigned char * outputPinData, unsigned char * outputPinProfile, long * outputPinMessageLength, unsigned char * outputPinMessage); /* PCF/CUSP Key Conversion */ extern void SECURITYAPI CSUAPCV_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * KEK_key_identifier_length, unsigned char * KEK_key_identifier, long * PCF_key_list_length, unsigned char * PCF_key_list, long * output_key_list_length, unsigned char * output_key_list); /*Process Request Block*/ extern void SECURITYAPI CSUAPRB_32(long * pReturnCode, long * pReasonCode, long * pExitDataLength, unsigned char * pExitData, long * pRuleArrayCount, unsigned char * pRuleArray, long * pSourceLength, unsigned char * pSource, long * pOutFileNameLength, unsigned char * pOutFileName, long * pReplyLength, unsigned char * pReply); /* Diffie-Hellman Key Load */ extern void SECURITYAPI CSUADHK_32(long * ReturnCode, long * ReasonCode, long * ExitDataLength, unsigned char * ExitData, long * RuleArrayCount, unsigned char * RuleArray, unsigned char * DHModulus, unsigned char * DHGenerator, unsigned char * DHKeyPart, long * TransportKeyHashLength, unsigned char * TransportKeyHash, unsigned char * Reserved1, unsigned char * Reserved2, unsigned char * Reserved3, unsigned char * Reserved4); /* Diffie-Hellman Key Query */ extern void SECURITYAPI CSUADHQ_32(long * ReturnCode, long * ReasonCode, long * ExitDataLength, unsigned char * ExitData, long * RuleArrayCount, unsigned char * RuleArray, unsigned char * DHModulus, unsigned char * DHGenerator, unsigned char * DHKeyPart, long * TransportKeyHashLength, unsigned char * TransportKeyHash, unsigned char * Reserved1, unsigned char * Reserved2, unsigned char * Reserved3, unsigned char * Reserved4); /* Trusted Block Create */ extern void SECURITYAPI CSNDTBC_32 ( long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * input_block_length, unsigned char * input_block_identifier, unsigned char * transport_key_identifier, long * trusted_blokc_length, unsigned char * trusted_blokc_identifier ); /* Remote Key Export */ extern void SECURITYAPI CSNDRKX_32 ( long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * trusted_block_length, unsigned char * trusted_block_identifier, long * certificate_length, unsigned char * certificate, long * certificate_parms_length, unsigned char * certificate_parms, long * transport_key_length, unsigned char * transport_key_identifier, long * rule_id_length, unsigned char * rule_id, long * export_key_kek_length, unsigned char * export_key_kek_identifier, long * export_key_length, unsigned char * export_key_identifier, long * asym_encrypted_key_length, unsigned char * asym_encrypted_key, long * sym_encrypted_key_length, unsigned char * sym_encrypted_key, long * extra_data_length, unsigned char * extra_data, long * key_check_parameters_length, unsigned char * key_check_parameters, long * key_check_length, unsigned char * key_check_value ); /* Key Encryption Translate */ extern void SECURITYAPI CSNBKET_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * kek_identifier_length, unsigned char * kek_identifier, long * key_in_length, unsigned char * key_in, long * key_out_length, unsigned char * key_out); #endif /* HMAC Generate */ extern void SECURITYAPI CSNBHMG_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * key_identifier_length, unsigned char * key_identifier, long * message_text_length, unsigned char * message_text, long * chaining_vector_length, unsigned char * chaining_vector, long * MAC_length, unsigned char * MAC_text); /* HMAC Verify */ extern void SECURITYAPI CSNBHMV_32(long * return_code, long * reason_code, long * exit_data_length, unsigned char * exit_data, long * rule_array_count, unsigned char * rule_array, long * key_identifier_length, unsigned char * key_identifier, long * message_text_length, unsigned char * message_text, long * chaining_vector_length, unsigned char * chaining_vector, long * MAC_length, unsigned char * MAC_text); opencryptoki+dfsg/usr/lib/pkcs11/cca_stdll/Makefile.am0000644000175000017500000000524312630407154021750 0ustar xnoxxnox# Makefile.am for common functions for openCryptoki # Michael A. Halcrow # # The PKCS#11 STDLL library # nobase_lib_LTLIBRARIES=opencryptoki/stdll/libpkcs11_cca.la # Not all versions of automake observe libname_CFLAGS opencryptoki_stdll_libpkcs11_cca_la_CFLAGS = -DLINUX -DNOCDMF \ -DNODSA -DNODH -DNOECB \ -I. -I../../../include \ -I../../../include/pkcs11 \ -I../common \ -DSTDLL_NAME=\"ccatok\" opencryptoki_stdll_libpkcs11_cca_la_LDFLAGS = -shared -Wl,-Bsymbolic \ -lcrypto -lpthread \ -nostartfiles \ -Wl,-soname,$@ \ -lrt opencryptoki_stdll_libpkcs11_cca_la_SOURCES = ../common/asn1.c \ ../common/btree.c \ ../common/dig_mgr.c \ ../common/hwf_obj.c \ ../common/trace.c \ ../common/key.c \ ../common/mech_dh.c \ ../common/mech_rng.c \ ../common/new_host.c \ ../common/sign_mgr.c \ ../common/cert.c \ ../common/dp_obj.c \ ../common/mech_aes.c \ ../common/mech_rsa.c \ ../common/mech_ec.c \ ../common/obj_mgr.c \ ../common/template.c \ ../common/data_obj.c \ ../common/encr_mgr.c \ ../common/key_mgr.c \ ../common/mech_md2.c \ ../common/mech_sha.c \ ../common/object.c \ ../common/decr_mgr.c \ ../common/globals.c \ ../common/loadsave.c \ ../common/utility.c \ ../common/mech_des.c \ ../common/mech_des3.c \ ../common/mech_md5.c \ ../common/mech_ssl3.c \ ../common/sess_mgr.c \ ../common/verify_mgr.c \ ../common/p11util.c \ ../common/sw_crypt.c \ ../common/shared_memory.c \ cca_specific.c noinst_HEADERS = defs.h \ csulincl.h \ cca_stdll.h install-data-hook: cd $(DESTDIR)/$(libdir)/opencryptoki/stdll && \ ln -sf libpkcs11_cca.so PKCS11_CCA.so $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/opencryptoki/ccatok/TOK_OBJ $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/ccatok/TOK_OBJ $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/ccatok $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/ccatok/TOK_OBJ $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/ccatok $(MKDIR_P) $(DESTDIR)$(lockdir)/ccatok $(CHGRP) pkcs11 $(DESTDIR)$(lockdir)/ccatok $(CHMOD) 0770 $(DESTDIR)$(lockdir)/ccatok uninstall-hook: if test -d $(DESTDIR)/$(libdir)/opencryptoki/stdll; then \ cd $(DESTDIR)/$(libdir)/opencryptoki/stdll && \ rm -f PKCS11_CCA.so; fi opencryptoki+dfsg/usr/lib/pkcs11/api/0000755000175000017500000000000012630407154016531 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/api/api_interface.c0000755000175000017500000041775612630407154021515 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #if NGPTH #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "trace.h" void api_init(); // NOTES: // In many cases the specificaiton does not allow returns // of CKR_ARGUMENTSB_BAD. We break the spec, since validation of parameters // to the function are best represented by this return code (where // specific RC's such as CKR_INVALID_SESSION do not exist). // NOTE NOTE NOTE NOTE // The parameter checking on the update operations may need to be // modified (as well as the encrypt/decrypt) to call the stdll // anyway with sanatized parameters since on error, the encrypt/decrypt // sign operations are all supposed to complete. // Therefor the parameter checking here might need to be done in // the STDLL instead of the API. // This would affect ALL the Multipart operations which have // an init followed by one or more operations. // Globals for the API API_Proc_Struct_t *Anchor = NULL; // Initialized to NULL unsigned int Initialized = 0; // Initialized flag pthread_mutex_t GlobMutex; // Global Mutex CK_FUNCTION_LIST FuncList; int slot_loaded[NUMBER_SLOTS_MANAGED]; // Array of flags to indicate // if the STDLL loaded // For linux only at this time... if it works out we can get rid // of the stupid pid tracking.... Linux we kind of have to do this // since new threads are processes also, and we will be hosed void child_fork_initializer() { if (Anchor) { free(Anchor); Anchor = NULL; } } //------------------------------------------------------------------------ // API function C_CancelFunction //------------------------------------------------------------------------ // This is a legacy function and performs no operations per the // specification. CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession) { TRACE_INFO("C_CancelFunction\n"); if (API_Initialized() == FALSE) { TRACE_ERROR( "%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL)); return CKR_FUNCTION_NOT_PARALLEL; // PER PKCS#11v2.20,Sec 11.16 } //------------------------------------------------------------------------ // API function C_CloseAllSessions //------------------------------------------------------------------------ // Netscape Required // // This is a special one since the API can do this by removing // all active sessions on the slot... The STDLL does not have to implement // this. however this function will fail if any Session removal fails // in the walk. Which could lead to undetermined results. // //------------------------------------------------------------------------ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) { // Although why does modutil do a close all sessions. It is a single // application it can only close its sessions... // And all sessions should be closed anyhow. TRACE_INFO("CloseAllSessions\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } /* for every node in the API-level session tree, if the session's slot matches slotID, * close it */ CloseAllSessions(slotID); return CKR_OK; } // end of C_CloseAllSessions //------------------------------------------------------------------------ // API function C_CloseSession //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_CloseSession\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_CloseSession) { // Map the Session to the slot session rv = fcn->ST_CloseSession(&rSession); TRACE_DEVEL("Called STDLL rv = 0x%lx\n", rv); // If the STDLL successfuly closed the session // we can free it.. Otherwise we will have to leave it // lying arround. if (rv == CKR_OK) { RemoveFromSessionList(hSession); // Need to decrement the global slot session count as well // as the per process slot session count to allow for // proper tracking of the number of sessions on a slot. // This allows things like InitToken to properly work in case // other applications have the token active. decr_sess_counts(rSession.slotID); } else TRACE_DEVEL("fcn->ST_CloseSession failed:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_CloseSession //------------------------------------------------------------------------ // API function C_CopyObject //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_CopyObject\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } if (!phNewObject) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } // null template with a count... will cause the lower layer // to have problems // Template with 0 count is not a problem. we can let // the STDLL handle that... if (!pTemplate && ulCount) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_CopyObject) { // Map the Session to the slot session rv = fcn->ST_CopyObject(&rSession, hObject, pTemplate, ulCount, phNewObject); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_CopyObject //------------------------------------------------------------------------ // API function C_CreateObject //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_CreateObject\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // Null template is invalid... An object needs a minimal // template for creation. if (!pTemplate) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } // A 0 count for the template is bad if (ulCount == 0) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } // A Null pointer to return the handle in is also bad // since we could de-reference incorrectly. if (!phObject) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_CreateObject) { // Map the Session to the slot session rv = fcn->ST_CreateObject(&rSession, pTemplate, ulCount, phObject); TRACE_DEVEL("fcn->ST_CreateObject returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_CreateObject //------------------------------------------------------------------------ // API function C_Decrypt //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_Decrypt\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // Null encrypted data is invalid, null pData buffer is invalid // as is null location to put the response into. if (!pEncryptedData || !pulDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Decrypt) { // Map the Session to the slot session rv = fcn->ST_Decrypt(&rSession, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen); TRACE_DEVEL("fcn->ST_Decrypt returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_Decrypt //------------------------------------------------------------------------ // API function C_DecryptDigestUpdate //------------------------------------------------------------------------ // Netscape Required CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DecryptDigestUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // This may have to go to the STDLL for validation if (!pEncryptedPart || !pulPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptDigestUpdate) { // Map the Session to the slot session rv = fcn->ST_DecryptDigestUpdate(&rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); TRACE_DEVEL("fcn->ST_DecryptDigestUpdate returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_DecryptFinal //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DecryptFinal\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // This may have to go to the STDLL for validation // It is acceptable to have a Null pointer for the data since // it is trying to get the length of the last part.... // The spec is unclear if a second call to Final is needed // if there is no data in the last part. if (!pulLastPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptFinal) { // Map the Session to the slot session rv = fcn->ST_DecryptFinal(&rSession, pLastPart, pulLastPartLen); TRACE_DEVEL("fcn->ST_DecryptFinal returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_DecryptFinal //------------------------------------------------------------------------ // API function C_DecryptInit //------------------------------------------------------------------------ // // // //------------------------------------------------------------------------ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DecryptInit\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // Null mechanism pointer is not good if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptInit) { // Map the Session to the slot session rv = fcn->ST_DecryptInit(&rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_DecryptInit returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_DecryptInit //------------------------------------------------------------------------ // API function C_DecryptUpdate //------------------------------------------------------------------------ // // // //------------------------------------------------------------------------ CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DecryptUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // May have to let these go through and let the STDLL handle them if (!pulPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptUpdate) { // Map the Session to the slot session rv = fcn->ST_DecryptUpdate(&rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); TRACE_DEVEL("fcn->ST_DecryptUpdate:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_DecryptUpdate //------------------------------------------------------------------------ // API function C_DecryptVerifyUpdate //------------------------------------------------------------------------ CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DecryptVerifyUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // May have to let these go through and let the STDLL handle them if (!pEncryptedPart || !pulPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DecryptVerifyUpdate) { // Map the Session to the slot session rv = fcn->ST_DecryptVerifyUpdate(&rSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); TRACE_DEVEL("fcn->ST_DecryptVerifyUpdate returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_DeriveKey //------------------------------------------------------------------------ CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DeriveKey\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // Null phKey is invalid // Null mechanism pointer is invalid // This is allowed for some SSL3 mechs. the STDLL has to catch this // condition since it validates the mechanism //if (!phKey ) return CKR_ARGUMENTS_BAD; if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } // Null template with attribute count is bad // but we will let a template with len 0 pass through if (!pTemplate && ulAttributeCount) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DeriveKey) { // Map the Session to the slot session rv = fcn->ST_DeriveKey(&rSession, pMechanism, hBaseKey, pTemplate, ulAttributeCount, phKey); TRACE_DEVEL("fcn->ST_DeriveKey returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_DestroyObject //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DestrypObject\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DestroyObject) { // Map the Session to the slot session rv = fcn->ST_DestroyObject(&rSession, hObject); TRACE_DEVEL("fcn->ST_DestroyObject returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_DestroyObject //------------------------------------------------------------------------ // API function C_Digest //------------------------------------------------------------------------ CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_Digest\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // Null data for digest is bad if (!pData || !pulDigestLen) return CKR_ARGUMENTS_BAD; sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Digest) { // Map the Session to the slot session rv = fcn->ST_Digest(&rSession, pData, ulDataLen, pDigest, pulDigestLen); TRACE_DEVEL("fcn->ST_Digest:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_DigestEncryptUpdate //------------------------------------------------------------------------ CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DigestEncryptUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } // May have to pass on through to the STDLL if (!pPart || !pulEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestEncryptUpdate) { // Map the Session to the slot session rv = fcn->ST_DigestEncryptUpdate(&rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); TRACE_DEVEL("fcn->ST_DigestEncryptUpdate returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_DigestFinal //------------------------------------------------------------------------ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DigestFinal\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pulDigestLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestFinal) { // Map the Session to the slot session rv = fcn->ST_DigestFinal(&rSession, pDigest, pulDigestLen); TRACE_DEVEL("fcn->ST_DigestFinal returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_DigestInit //------------------------------------------------------------------------ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DigestInit\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestInit) { // Map the Session to the slot session rv = fcn->ST_DigestInit(&rSession, pMechanism); TRACE_DEVEL("fcn->ST_DigestInit returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_DigestKey //------------------------------------------------------------------------ CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DigestKey\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestKey) { // Map the Session to the slot session rv = fcn->ST_DigestKey(&rSession, hKey); TRACE_DEBUG("fcn->ST_DigestKey returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_DigestUpdate //------------------------------------------------------------------------ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_DigestUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_DigestUpdate) { // Map the Session to the slot session rv = fcn->ST_DigestUpdate(&rSession, pPart, ulPartLen); TRACE_DEVEL("fcn->ST_DigestUpdate returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_Encrypt //------------------------------------------------------------------------ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_Encrypt\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pData || !pulEncryptedDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Encrypt) { // Map the Session to the slot session rv = fcn->ST_Encrypt(&rSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); TRACE_DEVEL("fcn->ST_Encrypt returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_EncryptFinal //------------------------------------------------------------------------ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_EncryptFinal\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } // See comments for DecryptFinal if (!pulLastEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_EncryptFinal) { // Map the Session to the slot session rv = fcn->ST_EncryptFinal(&rSession, pLastEncryptedPart, pulLastEncryptedPartLen); TRACE_DEVEL("fcn->ST_EncryptFinal: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_EncryptInit //------------------------------------------------------------------------ CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_EncryptInit\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_EncryptInit) { // Map the Session to the slot session rv = fcn->ST_EncryptInit(&rSession, pMechanism, hKey); TRACE_INFO("fcn->ST_EncryptInit returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_EncryptUpdate //------------------------------------------------------------------------ CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_EncryptUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pulEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_EncryptUpdate) { // Map the Session to the slot session rv = fcn->ST_EncryptUpdate(&rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); TRACE_DEVEL("fcn->ST_EncryptUpdate returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_Finalize //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_Finalize(CK_VOID_PTR pReserved) { API_Slot_t *sltp; CK_SLOT_ID slotID; TRACE_INFO("C_Finalize\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (pReserved != NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } pthread_mutex_lock(&GlobMutex); // Grab Process level Global MUTEX Terminate_All_Process_Sessions(); // Terminate the sessions // unload all the STDLL's from the application // This is in case the APP decides to do the re-initialize and // continue on // // for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) { sltp = &(Anchor->SltList[slotID]); if (sltp->pSTcloseall) { #if 0 (void)sltp->pSTcloseall(slotID); // call the terminate function.. #else /* pSTcloseall is just a pointer to the STDLL's SC_CloseAllSessions() function, so calling * it won't clean up shared memory, or the API layer's session btree. Instead, call * CloseAllSessions, which will clean everything up */ CloseAllSessions(slotID); #endif } if (sltp->pSTfini) { sltp->pSTfini(slotID); // call the terminate function.. } DL_UnLoad(sltp, slotID); } // Un register from Slot D API_UnRegister(); detach_shared_memory(Anchor->SharedMemP); free(Anchor); // Free API Proc Struct Anchor = NULL; // Unlock pthread_mutex_unlock(&GlobMutex); trace_finalize(); return CKR_OK; } // end of C_Finalize //------------------------------------------------------------------------ // API function C_FindObjects //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_FindObjects\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!phObject || !pulObjectCount) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_FindObjects) { // Map the Session to the slot session rv = fcn->ST_FindObjects(&rSession, phObject, ulMaxObjectCount, pulObjectCount); TRACE_DEVEL("fcn->ST_FindObjects returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_FindObjects //------------------------------------------------------------------------ // API function C_FindObjectsFinal //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_FindObjectsFinal\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_FindObjectsFinal) { // Map the Session to the slot session rv = fcn->ST_FindObjectsFinal(&rSession); TRACE_DEVEL("fcn->ST_FindObjectsFinal returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_FindObjectsFinal //------------------------------------------------------------------------ // API function // C_FindObjectsInit //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_FindObjectsInit\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } // What does a NULL template really mean if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_FindObjectsInit) { // Map the Session to the slot session rv = fcn->ST_FindObjectsInit(&rSession, pTemplate, ulCount); TRACE_DEVEL("fcn->ST_FindObjectsInit returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_FindObjectsInit //------------------------------------------------------------------------ // API function C_GenerateKey //------------------------------------------------------------------------ // Netscape Required CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_GenerateKey\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!phKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GenerateKey) { // Map the Session to the slot session rv = fcn->ST_GenerateKey(&rSession, pMechanism, pTemplate, ulCount, phKey); TRACE_DEVEL("fcn->ST_GenerateKey returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_GenerateKeyPair //------------------------------------------------------------------------ // Netscape Required 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) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_GenerateKeyPair\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!phPublicKey || !phPrivateKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } // what other validation of parameters ... What about // template pointers is a Null template pointer valid in generate // key... Are there defaults. if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GenerateKeyPair) { // Map the Session to the slot session rv = fcn->ST_GenerateKeyPair(&rSession, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); TRACE_DEVEL("fcn->ST_GenerateKeyPair returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_GenerateRandom //------------------------------------------------------------------------ // Netscape Required CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_GenerateRandom\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!RandomData) return CKR_ARGUMENTS_BAD; if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GenerateRandom) { // Map the Session to the slot session rv = fcn->ST_GenerateRandom(&rSession, RandomData, ulRandomLen); TRACE_DEVEL("fcn->ST_GenerateRandom returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_GetAttributeValue //------------------------------------------------------------------------ // Netscape Required // // //------------------------------------------------------------------------ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_GetAttributeValue\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pTemplate) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } if (ulCount == 0) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetAttributeValue) { // Map the Session to the slot session rv = fcn->ST_GetAttributeValue(&rSession, hObject, pTemplate, ulCount); TRACE_DEVEL("fcn->ST_GetAttributeValue returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_GetAttributeValue //------------------------------------------------------------------------ // API function C_GetFunctionList //------------------------------------------------------------------------ // Netscape Required CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) { api_init(); TRACE_INFO("C_GetFunctionList\n"); FuncList.version.major = VERSION_MAJOR; FuncList.version.minor = VERSION_MINOR; FuncList.C_Initialize = C_Initialize; FuncList.C_Finalize = C_Finalize; FuncList.C_GetInfo = C_GetInfo; FuncList.C_GetFunctionList = C_GetFunctionList; FuncList.C_GetSlotList = C_GetSlotList; FuncList.C_GetSlotInfo = C_GetSlotInfo; FuncList.C_GetTokenInfo = C_GetTokenInfo; FuncList.C_GetMechanismList = C_GetMechanismList; FuncList.C_GetMechanismInfo = C_GetMechanismInfo; FuncList.C_InitToken = C_InitToken; FuncList.C_InitPIN = C_InitPIN; FuncList.C_SetPIN = C_SetPIN; FuncList.C_OpenSession = C_OpenSession; FuncList.C_CloseSession = C_CloseSession; FuncList.C_CloseAllSessions = C_CloseAllSessions; FuncList.C_GetSessionInfo = C_GetSessionInfo; FuncList.C_GetOperationState = C_GetOperationState; FuncList.C_SetOperationState = C_SetOperationState; FuncList.C_Login = C_Login; FuncList.C_Logout = C_Logout; FuncList.C_CreateObject = C_CreateObject; FuncList.C_CopyObject = C_CopyObject; FuncList.C_DestroyObject = C_DestroyObject; FuncList.C_GetObjectSize = C_GetObjectSize; FuncList.C_GetAttributeValue = C_GetAttributeValue; FuncList.C_SetAttributeValue = C_SetAttributeValue; FuncList.C_FindObjectsInit = C_FindObjectsInit; FuncList.C_FindObjects = C_FindObjects; FuncList.C_FindObjectsFinal = C_FindObjectsFinal; FuncList.C_EncryptInit = C_EncryptInit; FuncList.C_Encrypt = C_Encrypt; FuncList.C_EncryptUpdate = C_EncryptUpdate; FuncList.C_EncryptFinal = C_EncryptFinal; FuncList.C_DecryptInit = C_DecryptInit; FuncList.C_Decrypt = C_Decrypt; FuncList.C_DecryptUpdate = C_DecryptUpdate; FuncList.C_DecryptFinal = C_DecryptFinal; FuncList.C_DigestInit = C_DigestInit; FuncList.C_Digest = C_Digest; FuncList.C_DigestUpdate = C_DigestUpdate; FuncList.C_DigestKey = C_DigestKey; FuncList.C_DigestFinal = C_DigestFinal; FuncList.C_SignInit = C_SignInit; FuncList.C_Sign = C_Sign; FuncList.C_SignUpdate = C_SignUpdate; FuncList.C_SignFinal = C_SignFinal; FuncList.C_SignRecoverInit = C_SignRecoverInit; FuncList.C_SignRecover = C_SignRecover; FuncList.C_VerifyInit = C_VerifyInit; FuncList.C_Verify = C_Verify; FuncList.C_VerifyUpdate = C_VerifyUpdate; FuncList.C_VerifyFinal = C_VerifyFinal; FuncList.C_VerifyRecoverInit = C_VerifyRecoverInit; FuncList.C_VerifyRecover = C_VerifyRecover; FuncList.C_DigestEncryptUpdate = C_DigestEncryptUpdate; FuncList.C_DecryptDigestUpdate = C_DecryptDigestUpdate; FuncList.C_SignEncryptUpdate = C_SignEncryptUpdate; FuncList.C_DecryptVerifyUpdate = C_DecryptVerifyUpdate; FuncList.C_GenerateKey = C_GenerateKey; FuncList.C_GenerateKeyPair = C_GenerateKeyPair; FuncList.C_WrapKey = C_WrapKey; FuncList.C_UnwrapKey = C_UnwrapKey; FuncList.C_DeriveKey = C_DeriveKey; FuncList.C_SeedRandom = C_SeedRandom; FuncList.C_GenerateRandom = C_GenerateRandom; FuncList.C_GetFunctionStatus = C_GetFunctionStatus; FuncList.C_CancelFunction = C_CancelFunction; FuncList.C_WaitForSlotEvent = C_WaitForSlotEvent; if (ppFunctionList) { (*ppFunctionList) = &FuncList; return CKR_OK; } else { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } } //------------------------------------------------------------------------ // API function C_GetFunctionStatus //------------------------------------------------------------------------ CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession) { TRACE_INFO("C_GetFunctionStatus\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL)); return CKR_FUNCTION_NOT_PARALLEL; // PER Specification PG 170 } //------------------------------------------------------------------------ // API function C_GetInfo //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_GetInfo(CK_INFO_PTR pInfo) { Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); TRACE_INFO("C_GetInfo\n"); if (!API_Initialized()) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } CK_Info_From_Internal(pInfo, &(shData->ck_info)); return CKR_OK; } // end of C_GetInfo //------------------------------------------------------------------------ // API function C_GetMechanismInfo //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; TRACE_INFO("C_GetMechansimInfo %lu %lx %p\n", slotID, type, pInfo); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } sltp = &(Anchor->SltList[slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetMechanismInfo) { rv = fcn->ST_GetMechanismInfo(slotID, type, pInfo); TRACE_DEVEL("fcn->ST_GetMechanismInfo returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_GetMechanismInfo //------------------------------------------------------------------------ // API function C_GetMechanismList //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; TRACE_INFO("C_GetMechanismList (%lu %p %lu)\n", slotID, pMechanismList, *pulCount); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } // Always have to have a pulCount if (!pulCount) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } // Null PMechanism is valid to get a count of mechanisms if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } sltp = &(Anchor->SltList[slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetMechanismList) { rv = fcn->ST_GetMechanismList(slotID, pMechanismList, pulCount); TRACE_DEVEL("fcn->ST_GetMechanismList returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } if (rv == CKR_OK) { if (pMechanismList) { unsigned long i; for (i = 0; i < *pulCount; i++) { TRACE_DEVEL("Mechanism[%lu] 0x%08lX \n", i, pMechanismList[i]); } } } return rv; } // end of C_GetMechanismList //------------------------------------------------------------------------ // API function C_GetObjectSize //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_GetObjectSize\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pulSize) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetObjectSize) { // Map the Session to the slot session rv = fcn->ST_GetObjectSize(&rSession, hObject, pulSize); TRACE_DEVEL("fcn->ST_GetObjectSize retuned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_GetObjectSize //------------------------------------------------------------------------ // API function C_GetOperationState //------------------------------------------------------------------------ CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_GetOperateionState\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } // NULL pOperationState is valid to get buffer // size if (!pulOperationStateLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetOperationState) { // Map the Session to the slot session rv = fcn->ST_GetOperationState(&rSession, pOperationState, pulOperationStateLen); TRACE_DEVEL("fcn->ST_GetOperationState returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_GetSessionInfo //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_GetSessionInfo %lx %p\n", hSession, pInfo); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetSessionInfo) { // Map the Session to the slot session rv = fcn->ST_GetSessionInfo(&rSession, pInfo); TRACE_DEVEL("fcn->ST_GetSessionInfo returned: 0x%lx\n", rv); TRACE_DEVEL("Slot %lu State %lx Flags %lx DevErr %lx\n", pInfo->slotID, pInfo->state, pInfo->flags, pInfo->ulDeviceError); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_GetSessionInfo //------------------------------------------------------------------------ // API function C_GetSlotInfo //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ #ifdef PKCS64 CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { Slot_Info_t_64 *sinfp; Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); TRACE_INFO("C_GetSlotInfo Slot=%lu ptr=%p\n", slotID, pInfo); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } sinfp = shData->slot_info; sinfp += slotID; if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } // Netscape and others appear to call // this for every slot. If the slot does not have // a registered STDLL, then this is a FUnction Failed case if (sinfp->present == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } #ifdef __64BIT__ memcpy(pInfo, (char *)&(sinfp->pk_slot), sizeof(CK_SLOT_INFO)); #else memcpy((char *)&(pInfo->slotDescription[0]), (char *)&(sinfp->pk_slot.slotDescription[0]), 64); memcpy((char *)&(pInfo->manufacturerID[0]), (char *)&(sinfp->pk_slot.manufacturerID[0]), 32); pInfo->flags = sinfp->pk_slot.flags; pInfo->hardwareVersion = sinfp->pk_slot.hardwareVersion; pInfo->firmwareVersion = sinfp->pk_slot.firmwareVersion; #endif return CKR_OK; } // end of C_GetSlotInfo #else CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { uint16 count; uint16 index; uint16 sindx; Slot_Info_t *sinfp; Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); TRACE_INFO("C_GetSlotInfo Slot=%d ptr=%x\n", slotID, pInfo); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } sinfp = shData->slot_info; sinfp += slotID; count = 0; if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } // Netscape and others appear to call // this for every slot. If the slot does not have // a registered STDLL, then this is a FUnction Failed case if (sinfp->present == FALSE) { TRACE_ERROR("%s: No STDLL present.\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } memcpy(pInfo, (char *)&(sinfp->pk_slot), sizeof(CK_SLOT_INFO)); return CKR_OK; } // end of C_GetSlotInfo #endif //------------------------------------------------------------------------ // API function C_GetSlotList //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { CK_ULONG count; uint16 index; uint16 sindx; Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); #ifdef PKCS64 Slot_Info_t_64 *sinfp; #else Slot_Info_t *sinfp; #endif TRACE_INFO("C_GetSlotList\n"); TRACE_DEVEL(" Pres %d Count %lu\n", tokenPresent, *pulCount); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } // Null pSlotList is valid to get count for array allocation if (pulCount == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } sinfp = shData->slot_info; count = 0; // Count the slots based off the present flag // Go through all the slots and count them up // Remember if the tokenPresent Flag is set do not count the // not present ones. // // ------------------------------------------------------------ // // Present indicates that the slot is managed by the Slot manager // and that an appropriate registration has been made in the DB // // It does not imply that a token is present. // Slots with STDLL's are ALWAYS present in the system wether they // have a token or not is determined from the token functions. // // According to the spec the tokenPresent flag indicates if all // slots are wanted, or those which have tokens present. We will // use this to mean if a STDLL is present or not. All slots // are in the system, if a STDLL is attached to a slot, then it is // present( not to be confused with the Tokens flags indicating // presence). Presence of a STDLL on a slot indicates that there // is a "token reader" available. // // Note: All slots should be named by the slot manager with the // slot id in them... // ------------------------------------------------------------ // // Note: The CK_INFO_STRUCT present flag indicates that a token is present // in the reader located in the slot. Right now we are dealing only // with non-removable tokens, so the slot flags set in the slot DB // are fixed by the STDLL. Ultimately when we get to removable tokens, the // slot manager will have to monitor the device in the slot and set the flag // accordingly. // // This does however change the reporting back of Slot Lists... // // We were using the presence of a STDLL to indicate if a Token is present // or not. however we need to report back based on 2 flags. // // First a stdll must be in the table, second the slot info flags must be // set to present to return. // ---------------------------------------------- // // Also need to validate that the STDLL successfuly loaded. for (index = 0; index < NUMBER_SLOTS_MANAGED; index++) { // if there is a STDLL in the slot then we have to count it // otherwise the slot is NOT counted. if (sinfp[index].present == TRUE && slot_loaded[index] == TRUE) { if (tokenPresent) { if ((sinfp[index].pk_slot. flags & CKF_TOKEN_PRESENT)) { count++; } } else { count++; } } } *pulCount = count; // If only the count is wanted then we set the value and exit if (pSlotList == NULL) { return CKR_OK; } else { // Verify that the buffer passed is large enough if (*pulCount < count) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } // Walk through the slot manager information and copy in the // slot id to the list of slot indexes. // // This is incorrectly going to assume that the slots are // sequentialy allocated. While most likely we should be robust // and handle it. // Count should correct based on the first loop. // for (sindx = 0, index = 0; (index < NUMBER_SLOTS_MANAGED) && (sindx < count); index++) { if (sinfp[index].present == TRUE && slot_loaded[index] == TRUE) { if (tokenPresent) { if (sinfp[index].pk_slot. flags & CKF_TOKEN_PRESENT) { pSlotList[sindx] = sinfp[index].slot_number; sindx++; // only increment when we have used it. } } else { pSlotList[sindx] = sinfp[index].slot_number; sindx++; // only increment when we have used it. } } } } return CKR_OK; } // end of C_GetSlotList //------------------------------------------------------------------------ // API function C_GetTokenInfo //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); #ifdef PKCS64 Slot_Info_t_64 *sinfp; #else Slot_Info_t *sinfp; #endif TRACE_INFO("C_GetTokenInfo\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } sltp = &(Anchor->SltList[slotID]); TRACE_DEVEL("Slot p = %p id %lu\n", sltp, slotID); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } // Need to check if the slot is not populated // then we can return the proper return code for a // slot that has no content. sinfp = shData->slot_info; if (sinfp[slotID].present == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_GetTokenInfo) { rv = fcn->ST_GetTokenInfo(slotID, pInfo); if (rv == CKR_OK) { get_sess_count(slotID, &(pInfo->ulSessionCount)); } TRACE_DEVEL("rv %lu CK_TOKEN_INFO Flags %lx\n", rv, pInfo->flags); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_GetTokenInfo void Call_Finalize() { C_Finalize(NULL); return; } //------------------------------------------------------------------------ // API function C_Initialize //------------------------------------------------------------------------ // Netscape Required // // //------------------------------------------------------------------------ CK_RV C_Initialize(CK_VOID_PTR pVoid) { CK_C_INITIALIZE_ARGS *pArg; char fcnmap = 0; trace_initialize(); TRACE_INFO("C_Initialize\n"); //if ( API_Proc_Struct NOT allocated ) // allocate Structure // if ( allocation fails ) // return CKR_HOST_MEMORY //else // if ( API_Proc_Struct owned by current process ) // process has called C_Initialize twice Fail routine // return CKR_FUNCTION_FAILED if (!Anchor) { Anchor = (API_Proc_Struct_t *) malloc(sizeof(API_Proc_Struct_t)); if (Anchor == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } } else { // Linux the atfork routines handle this TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_ALREADY_INITIALIZED)); return CKR_CRYPTOKI_ALREADY_INITIALIZED; } memset(slot_loaded, 0, sizeof(int) * NUMBER_SLOTS_MANAGED); // Clear out the load list TRACE_DEBUG("Anchor allocated at %s\n", (char *)Anchor); // Validation of the parameters passed // if pVoid is NULL, then everything is OK. The applicaiton // will not be doing multi thread accesses. We can use the OS // locks anyhow. // if (pVoid != NULL) { TRACE_DEVEL("Initialization arg = %p Flags %lu\n", pVoid, ((CK_C_INITIALIZE_ARGS *) pVoid)->flags); pArg = (CK_C_INITIALIZE_ARGS *) pVoid; // Check for a pReserved set if (pArg->pReserved != NULL) { free(Anchor); Anchor = NULL; TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } // Set up a bit map indicating the presense of the functions. fcnmap = (pArg->CreateMutex ? 0x01 << 0 : 0); fcnmap |= (pArg->DestroyMutex ? 0x01 << 1 : 0); fcnmap |= (pArg->LockMutex ? 0x01 << 2 : 0); fcnmap |= (pArg->UnlockMutex ? 0x01 << 3 : 0); // Verify that all or none of the functions are set if (fcnmap != 0) { if (fcnmap != 0x0f) { free(Anchor); Anchor = NULL; OCK_SYSLOG(LOG_ERR, "C_Initialize: Invalid " "number of functions passed in " "argument structure.\n"); return CKR_ARGUMENTS_BAD; } } // If we EVER need to create threads from this library we must // check the Flags for the Can_Create_OS_Threads flag // Right now the library DOES NOT create threads and therefore this // check is irrelavant. if (pArg->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) { TRACE_DEVEL("Can't create OS threads...This is OK\n"); } // Since this is an initialization path, we will be verbose in the // code rather than efficient. // // in reality, we only need to check for case 3 since all others // are acceptable to us... for one reason or another. // // Case 1 Flag not set and functiopn pointers NOT supplied if (!(pArg->flags & CKF_OS_LOCKING_OK) && !(fcnmap)) { ; // This is COOL. Same as a NUL pointer Locking is irrelavent. } else { // Case 2. Flags set and Fcn pointers NOT supplied. if ((pArg->flags & CKF_OS_LOCKING_OK) && !(fcnmap)) { ; // This to is COOL since we require native locking } else { // Case 3 Flag Not set and pointers supplied. Can't handle this // one. if (!(pArg->flags & CKF_OS_LOCKING_OK) && fcnmap) { free(Anchor); Anchor = NULL; OCK_SYSLOG(LOG_ERR, "C_Initialize: " "Application specified that " "OS locking is invalid. " "PKCS11 Module requires OS " "locking.\n"); // Only support Native OS locking. return CKR_CANT_LOCK; } else { // Case 4 Flag set and fcn pointers set if ((pArg->flags & CKF_OS_LOCKING_OK) && fcnmap) { ; // This is also cool. } else { // Were really hosed here since this should not have // occured free(Anchor); Anchor = NULL; TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); return CKR_GENERAL_ERROR; } } } } } else { // Pointer to void... // This is OK we can go on from here. ; } // Create the shared memory lock. if (CreateXProcLock() != CKR_OK) { free((void *)Anchor); Anchor = NULL; TRACE_ERROR("Process Lock Failed.\n"); return CKR_FUNCTION_FAILED; } //Zero out API_Proc_Struct //Map Shared Memory Region //if ( Shared Memory Mapped not Successful ) // Free allocated Memory // Return CKR_HOST_MEMORY memset((char *)Anchor, 0, sizeof(API_Proc_Struct_t)); pthread_mutex_init(&(Anchor->ProcMutex), NULL); // This is not shared across apps. pthread_mutex_init(&(Anchor->SessListMutex), NULL); // This is not shared across apps. pthread_mutex_init(&GlobMutex, NULL); pthread_mutex_lock(&GlobMutex); Anchor->Pid = getpid(); if ((Anchor->SharedMemP = attach_shared_memory()) == NULL) { // Get shared memory free((void *)Anchor); Anchor = NULL; pthread_mutex_unlock(&GlobMutex); OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to attach to " "shared memory. Verify that the slot management " "daemon is running, errno=%d\n", errno); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } TRACE_DEBUG("Shared memory %p \n", Anchor->SharedMemP); if (!init_socket_data()) { OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to create a " "socket. Verify that the slot management daemon is " "running.\n"); TRACE_ERROR("Cannot attach to socket.\n"); detach_shared_memory(Anchor->SharedMemP); free((void *)Anchor); Anchor=NULL; pthread_mutex_unlock(&GlobMutex); return CKR_FUNCTION_FAILED; } // Initialize structure values //Register with pkcsslotd if (!API_Register()) { // free memory allocated // return CKR_FUNCTION_FAILED // return CKR_FUNCTION_NOT_SUPPORTED; detach_shared_memory(Anchor->SharedMemP); free((void *)Anchor); Anchor = NULL; pthread_mutex_unlock(&GlobMutex); TRACE_ERROR("Failed to register process with pkcsslotd.\n"); return CKR_FUNCTION_FAILED; } // // load all the slot DLL's here { CK_SLOT_ID slotID; API_Slot_t *sltp; for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) { sltp = &(Anchor->SltList[slotID]); slot_loaded[slotID] = DL_Load_and_Init(sltp, slotID); } } // Attempt to force C_Finalize to be called // This causes Netscape to core dump since it unloads the module //atexit(*Call_Finalize); pthread_mutex_unlock(&GlobMutex); return CKR_OK; // Good return code. } // end of C_Initialize //------------------------------------------------------------------------ // API function C_InitPIN //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_InitPin\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } // A Null Pin with a Len is invalid // A Null pin with a 0 len is no pin at all? if (!pPin && ulPinLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } // XXX Remove me, this test should be completely unnecessary // Move this to after the session validation... if (rSession.slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_InitPIN) { // Map the Session to the slot session rv = fcn->ST_InitPIN(&rSession, pPin, ulPinLen); TRACE_DEVEL("fcn->ST_InitPIN returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_InitPIN //------------------------------------------------------------------------ // API function C_InitToken //------------------------------------------------------------------------ //Netscape NEVER Calls this according to the Netscape documentation CK_RV C_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; TRACE_INFO("C_InitToken\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } // Null pPin and a pinlen is a problem if (!pPin && ulPinLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!pLabel) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } // Prior to invoking the Tokens initialization, the // API needs to verify that NO other applications have any // sessions established with this particular slot // // Hooks into the shared memory to determine how many sessions // on a given token are open need to be added. // When a session is opened, it increments the count. When // closed it decrements the count. Protected by an MUTEX // In the shared memory region the slot_info[slotID].sesscount // variable needs to be checked, and held locked until the operation // is complete. if (sessions_exist(slotID)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_EXISTS)); return CKR_SESSION_EXISTS; } sltp = &(Anchor->SltList[slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_InitToken) { rv = fcn->ST_InitToken(slotID, pPin, ulPinLen, pLabel); TRACE_DEVEL("fcn->ST_InitToken returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_Login //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_Login\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } #if 0 /* Allow incorrect PIN checks to fall into the SC_Login * function, since v2.11 requires flags to be set. - KEY */ if (!pPin) { return CKR_PIN_INCORRECT; } #endif if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Login) { // Map the Session to the slot session rv = fcn->ST_Login(&rSession, userType, pPin, ulPinLen); TRACE_DEVEL("fcn->ST_Login returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_Login //------------------------------------------------------------------------ // API function C_Logout //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_Logout(CK_SESSION_HANDLE hSession) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_Logout\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Logout) { // Map the Session to the slot session rv = fcn->ST_Logout(&rSession); TRACE_DEVEL("fcn->ST_Logout returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_Logout //------------------------------------------------------------------------ // API function C_OpenSession //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ // // Note: Need to worry about handling the Notify and Applicaiton call backs // that are here... STDLL will NEVER deal with these... The // usage of them appears to be optional from the specification // but we may need to do something with them at a later date. // CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T *apiSessp; TRACE_INFO("C_OpenSession %lu %lx %p %p %p\n", slotID, flags, pApplication, Notify, phSession); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (slotID >= NUMBER_SLOTS_MANAGED) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); return CKR_SLOT_ID_INVALID; } if (!phSession) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; // // Need to handle the failure of a load here... } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((apiSessp = (ST_SESSION_T *) malloc(sizeof(ST_SESSION_T))) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } if (fcn->ST_OpenSession) { rv = fcn->ST_OpenSession(slotID, flags, &(apiSessp->sessionh)); TRACE_DEVEL("fcn->ST_OpenSession returned: 0x%lx\n", rv); // If the session allocation is successful, then we need to // complete the API session block and return. Otherwise // we free the API session block and exit if (rv == CKR_OK) { /* add a refernece to this handle/slot_id pair to the binary tree we maintain at the * API level, returning the API-level object's handle as the session handle the app * will get */ *phSession = AddToSessionList(apiSessp); if (*phSession == 0) { /* failed to add the object to the API-level tree, close the STDLL-level session * and return failure */ fcn->ST_CloseSession(apiSessp); free(apiSessp); rv = CKR_HOST_MEMORY; goto done; } apiSessp->slotID = slotID; // NOTE: Need to add Session counter to the shared // memory slot value.... Atomic operation. // sharedmem->slot_info[slotID].sessioncount incremented // when ever a session is attached. // Also increment the per process slot counter to indicate // how many sessions this process owns of the total amount. This // way if the process abends garbage collection in the slot manager // can adequatly clean up the total count value... incr_sess_counts(slotID); } else { free(apiSessp); } } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); free(apiSessp); rv = CKR_FUNCTION_NOT_SUPPORTED; } done: return rv; } // end of C_OpenSession //------------------------------------------------------------------------ // API function C_SeedRandom //------------------------------------------------------------------------ CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SeedRandom\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pSeed && ulSeedLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SeedRandom) { // Map the Session to the slot session rv = fcn->ST_SeedRandom(&rSession, pSeed, ulSeedLen); TRACE_DEVEL("fcn->ST_SeedRandom returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_SetAttributeValue //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SetAttributeValue\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } if (!pTemplate) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } if (!ulCount) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SetAttributeValue) { // Map the Session to the slot session rv = fcn->ST_SetAttributeValue(&rSession, hObject, pTemplate, ulCount); TRACE_DEVEL("fcn->ST_SetAttributeValue returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_SetAttributeValue //------------------------------------------------------------------------ // API function C_SetOperationState //------------------------------------------------------------------------ CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SetOperationState\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } if (!pOperationState || ulOperationStateLen == 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SetOperationState) { // Map the Session to the slot session rv = fcn->ST_SetOperationState(&rSession, pOperationState, ulOperationStateLen, hEncryptionKey, hAuthenticationKey); TRACE_DEVEL("fcn->ST_SetOperationState returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_SetPIN //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SetPIN\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pOldPin || !pNewPin) return CKR_PIN_INVALID; if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SetPIN) { // Map the Session to the slot session rv = fcn->ST_SetPIN(&rSession, pOldPin, ulOldLen, pNewPin, ulNewLen); TRACE_DEVEL("fcn->ST_SetPIN returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_SetPIN //------------------------------------------------------------------------ // API function C_Sign //------------------------------------------------------------------------ // Netscape Required // // // //------------------------------------------------------------------------ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_Sign\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pData || !pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Sign) { // Map the Session to the slot session rv = fcn->ST_Sign(&rSession, pData, ulDataLen, pSignature, pulSignatureLen); TRACE_DEVEL("fcn->ST_Sign returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_Sign //------------------------------------------------------------------------ // API function C_SignEncryptUpdate //------------------------------------------------------------------------ CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SignEncryptUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pPart || !pulEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignEncryptUpdate) { // Map the Session to the slot session rv = fcn->ST_SignEncryptUpdate(&rSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); TRACE_DEVEL("fcn->ST_SignEncryptUpdate return: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_SignFinal //------------------------------------------------------------------------ // // // //------------------------------------------------------------------------ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SignEncryptUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignFinal) { // Map the Session to the slot session rv = fcn->ST_SignFinal(&rSession, pSignature, pulSignatureLen); TRACE_DEVEL("fcn->ST_SignFinal returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } // end of C_SignFinal //------------------------------------------------------------------------ // API function C_SignInit //------------------------------------------------------------------------ // // // //------------------------------------------------------------------------ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SignInit\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignInit) { // Map the Session to the slot session rv = fcn->ST_SignInit(&rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_SignInit returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } // end of C_SignInit //------------------------------------------------------------------------ // API function C_SignRecover //------------------------------------------------------------------------ CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SignRecover\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pData || !pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignRecover) { // Map the Session to the slot session rv = fcn->ST_SignRecover(&rSession, pData, ulDataLen, pSignature, pulSignatureLen); TRACE_DEVEL("fcn->ST_SignRecover returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_SignRecoverInit //------------------------------------------------------------------------ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SignRecoverInit\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignRecoverInit) { // Map the Session to the slot session rv = fcn->ST_SignRecoverInit(&rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_SignRecoverInit returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_SignUpdate //------------------------------------------------------------------------ // // // //------------------------------------------------------------------------ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_SignUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_SignUpdate) { // Map the Session to the slot session rv = fcn->ST_SignUpdate(&rSession, pPart, ulPartLen); TRACE_DEVEL("fcn->ST_SignUpdate returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } // end of C_SignUpdate //------------------------------------------------------------------------ // API function C_UnwrapKey //------------------------------------------------------------------------ // Netscape Required CK_RV C_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) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_UnwrapKey\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!phKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } // what about the other pointers... probably need // to be set correctly if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_UnwrapKey) { // Map the Session to the slot session rv = fcn->ST_UnwrapKey(&rSession, pMechanism, hUnwrappingKey, pWrappedKey, ulWrappedKeyLen, pTemplate, ulAttributeCount, phKey); TRACE_DEVEL("fcn->ST_UnwrapKey returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_Verify //------------------------------------------------------------------------ // Netscape Required CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_Verify\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pData || !pSignature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_Verify) { // Map the Session to the slot session rv = fcn->ST_Verify(&rSession, pData, ulDataLen, pSignature, ulSignatureLen); TRACE_DEVEL("fcn->ST_Verify returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_VerifyFinal //------------------------------------------------------------------------ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_VerifyFinal\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pSignature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyFinal) { // Map the Session to the slot session rv = fcn->ST_VerifyFinal(&rSession, pSignature, ulSignatureLen); TRACE_DEVEL("fcn->ST_VerifyFinal returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } //------------------------------------------------------------------------ // API function C_VerifyInit //------------------------------------------------------------------------ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_VerifyInit\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyInit) { // Map the Session to the slot session rv = fcn->ST_VerifyInit(&rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_VerifyInit returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_VerifyRecover //------------------------------------------------------------------------ // Netscape Required CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_VerifyRecover\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pSignature || !pulDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyRecover) { // Map the Session to the slot session rv = fcn->ST_VerifyRecover(&rSession, pSignature, ulSignatureLen, pData, pulDataLen); TRACE_DEVEL("fcn->ST_VerifyRecover returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_VerifyRecoverInit //------------------------------------------------------------------------ CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_VerifyRecoverInit\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyRecoverInit) { // Map the Session to the slot session rv = fcn->ST_VerifyRecoverInit(&rSession, pMechanism, hKey); TRACE_DEVEL("fcn->ST_VerifyRecoverInit returned:0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_VerifyUpdate //------------------------------------------------------------------------ CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_VerifyUpdate\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_VerifyUpdate) { // Map the Session to the slot session rv = fcn->ST_VerifyUpdate(&rSession, pPart, ulPartLen); TRACE_DEVEL("fcn->ST_VerifyUpdate returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } //------------------------------------------------------------------------ // API function C_WaitForSlotEvent //------------------------------------------------------------------------ // // //NOTE: We need to implement this one even though Netscape does not //make use of this... // //Standard code template won't work with this. We need to look at //the slot manager and the shared memory indicating the slot bitmap //Blocking needs to be worked out. At the initial release do not //support BLocked calls on wait for slot event. // //Support Note: //This function is really used for removable tokens, and is pretty //inefficient. It may be best to return CKR_FUNCTION_UNSUPPORTED //if it becomes a field issue, until removable token support is fully //implemented. Be forewarned. //------------------------------------------------------------------------ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) { #ifdef PLUGGABLE_TOKENS_SUPPORTED #ifdef PKCS64 Slot_Mgr_Proc_t_64 *procp; #else Slot_Mgr_Proc_t *procp; #endif #endif TRACE_INFO("C_WaitForSlotEvent\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } #ifndef PLUGGABLE_TOKENS_SUPPORTED // Since there are no tokens which we support that have the // ability to create slot events, and slotd does not // fully support this (it needs to be aware of the functions exported // by an STDLL to poll the slot for a token event and this // has not been fully implemented at this time, although the // design and structure of the shared memory in slotd do. TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; #else // Get the pointer to the process element.. // This could be done in a single line, but for readability we do it // in 2 steps. shm = Anchor->SharedMemP; procp = &shm->proc_table[Anchor->MgrProcIndex]; // Grab the mutex for the application in shared memory // Check the bit mask for non-zero. If the bit mask is non-zero // find the first slot which is set and set the pSlot value // and return CKR_OK. // for now we will just lock the whole shared memory // REally should be the procp->proc_mutex // but this is such an infrequent thing that we will simply get // the global shared memory lock XProcLock(); if (procp->slotmap) { // find the first bit set // This will have to change if more than 32 slots ever get supported // including the test for a bit turned on.. for (i = 0; NUMBER_SLOTS_MANAGED; i++) { if (procp->slotmap & (1 << i)) { break; } } *pSlot = i; // set the flag XProcUnLock(); return CKR_OK; } else { if (flags & CKF_DONT_BLOCK) { XProcUnLock(); return CKR_NO_EVENT; } else { // WE need to // 1. Set the blocking variable in the system map to true. // 2. clear the condition variable // // Note: for now we will just poll the bitmap every // second or look for the error field to go to true. // Check first if we are already blocking on another thread // for this process. According to the spec this behavior is undefined. // We will choose to fail the call. if (procp->blocking) { TRACE_DEVEL("WaitForSlot event called by process twice.\n"); XProcUnLock(); // Unlock aftersetting TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } procp->error = 0; procp->blocking = 0x01; XProcUnLock(); // Unlock aftersetting // NOTE: We need to have an asynchronous mechanism for // the slot manager to wake up anyone blocking on this. // But Since we are not supporting removable tokens, this // call should be almos never made. It might be best to // return CKR_FUNCTION_UNSUPPORTED, but we'll wait and see. while (!procp->slotmap && !procp->error) { sleep(1); // Note This is really bad form. But what the heck } XProcLock(); procp->blocking = 0; if (procp->error) { XProcUnLock(); TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR)); return CKR_GENERAL_ERROR; // We bailed on this because we were terminating // General error should cause the calling thread to not try anything // else... We need to look at how this holds up in practice. } else { // must have fallen out of loop because of a slot getting an // event for (i = 0; NUMBER_SLOTS_MANAGED; i++) { if (procp->slotmap & (1 << i)) { break; } } *pSlot = i; // set the flag XProcUnLock(); return CKR_OK; } } } #endif } // end of C_WaitForSlotEvent //------------------------------------------------------------------------ // API function // C_WrapKey //------------------------------------------------------------------------ // Netscape Required CK_RV C_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) { CK_RV rv; API_Slot_t *sltp; STDLL_FcnList_t *fcn; ST_SESSION_T rSession; TRACE_INFO("C_WrapKey\n"); if (API_Initialized() == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } // other pointers??? if (!Valid_Session(hSession, &rSession)) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } sltp = &(Anchor->SltList[rSession.slotID]); if (sltp->DLLoaded == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if ((fcn = sltp->FcnList) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_TOKEN_NOT_PRESENT)); return CKR_TOKEN_NOT_PRESENT; } if (fcn->ST_WrapKey) { // Map the Session to the slot session rv = fcn->ST_WrapKey(&rSession, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen); TRACE_DEVEL("fcn->ST_WrapKey returned: 0x%lx\n", rv); } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); rv = CKR_FUNCTION_NOT_SUPPORTED; } return rv; } #ifdef __sun #pragma init(api_init) #else void api_init(void) __attribute__ ((constructor)); #endif void api_init(void) { // Should only have to do the atfork stuff at load time... if (!Initialized) { pthread_atfork(NULL, NULL, (void (*)())child_fork_initializer); Initialized = 1; } } #ifdef __sun #pragma fini(api_fini) #else void api_fini(void) __attribute__ ((destructor)); #endif void api_fini() { if (API_Initialized() == TRUE) { Call_Finalize(); } } opencryptoki+dfsg/usr/lib/pkcs11/api/apiutil.c0000755000175000017500000007257612630407154020370 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ // // //AIX Pkcs11 Api Utility functions // #if NGPTH #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include // Function prototypes for PKCS11 #include #include #include #include #include #include #include static int xplfd = -1; #include #define LIBLOCATION LIB_PATH extern API_Proc_Struct_t *Anchor; #include #include "trace.h" CK_RV CreateXProcLock(void) { struct stat statbuf; if (xplfd == -1) { /* The slot mgr daemon should have already created lock, * so just open it so we can get a lock... */ if (stat(OCK_API_LOCK_FILE, &statbuf) == 0) xplfd = open(OCK_API_LOCK_FILE, O_RDONLY); if (xplfd == -1) { OCK_SYSLOG(LOG_ERR, "Could not open %s\n", OCK_API_LOCK_FILE); return CKR_FUNCTION_FAILED; } } return CKR_OK; } CK_RV XProcLock(void) { if (xplfd != -1) flock(xplfd, LOCK_EX); else TRACE_DEVEL("No file descriptor to lock with.\n"); return CKR_OK; } CK_RV XProcUnLock(void) { if (xplfd != -1) flock(xplfd, LOCK_UN); else TRACE_DEVEL("No file descriptor to unlock with.\n"); return CKR_OK; } unsigned long AddToSessionList(ST_SESSION_T * pSess) { unsigned long handle; pthread_mutex_lock(&(Anchor->SessListMutex)); handle = bt_node_add(&(Anchor->sess_btree), pSess); pthread_mutex_unlock(&(Anchor->SessListMutex)); return handle; } void RemoveFromSessionList(CK_SESSION_HANDLE handle) { pthread_mutex_lock(&(Anchor->SessListMutex)); bt_node_free(&(Anchor->sess_btree), handle, free); pthread_mutex_unlock(&(Anchor->SessListMutex)); } /* CloseMe * * Callback function used to close an individual session for a slot */ void CloseMe(void *node_value, unsigned long node_handle, void *arg) { CK_RV rv; CK_SLOT_ID slot_id = *(CK_SLOT_ID *) arg; ST_SESSION_T *s = (ST_SESSION_T *) node_value; API_Slot_t *sltp; STDLL_FcnList_t *fcn; if (s->slotID == slot_id) { /* the single ugliest part about moving to a binary tree: these are the guts of * the C_CloseSession function, copied here without tests for validity, since if we're * here, they must already have been valid */ sltp = &(Anchor->SltList[slot_id]); fcn = sltp->FcnList; rv = fcn->ST_CloseSession(s); if (rv == CKR_OK) { decr_sess_counts(slot_id); bt_node_free(&(Anchor->sess_btree), node_handle, free); } } } /* CloseAllSessions * * Run through all the nodes in the binary tree and call CloseMe on each one. CloseMe will look at * @slot_id and if it matches, will close the session. Once all the nodes are closed, we check * to see if the tree is empty and if so, destroy it */ void CloseAllSessions(CK_SLOT_ID slot_id) { pthread_mutex_lock(&(Anchor->SessListMutex)); /* for every node in the API-level session tree, call CloseMe on it */ bt_for_each_node(&(Anchor->sess_btree), CloseMe, (void *)&slot_id); if (bt_is_empty(&(Anchor->sess_btree))) bt_destroy(&(Anchor->sess_btree), NULL); pthread_mutex_unlock(&(Anchor->SessListMutex)); } int Valid_Session(CK_SESSION_HANDLE handle, ST_SESSION_T * rSession) { ST_SESSION_T *tmp; pthread_mutex_lock(&(Anchor->SessListMutex)); tmp = bt_get_node_value(&(Anchor->sess_btree), handle); if (tmp) { rSession->slotID = tmp->slotID; rSession->sessionh = tmp->sessionh; } pthread_mutex_unlock(&(Anchor->SessListMutex)); return (tmp ? TRUE : FALSE); } int API_Initialized() { if (Anchor == NULL) return FALSE; return TRUE; } int slot_present(CK_SLOT_ID id) { Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); #ifdef PKCS64 Slot_Info_t_64 *sinfp; #else Slot_Info_t *sinfp; #endif sinfp = &(shData->slot_info[id]); if (sinfp->present == FALSE) { return FALSE; } return TRUE; } void get_sess_count(CK_SLOT_ID slotID, CK_ULONG * ret) { Slot_Mgr_Shr_t *shm; shm = Anchor->SharedMemP; XProcLock(); *ret = shm->slot_global_sessions[slotID]; XProcUnLock(); } void incr_sess_counts(CK_SLOT_ID slotID) { Slot_Mgr_Shr_t *shm; #ifdef PKCS64 Slot_Mgr_Proc_t_64 *procp; #else Slot_Mgr_Proc_t *procp; #endif // Get the slot mutex shm = Anchor->SharedMemP; XProcLock(); shm->slot_global_sessions[slotID]++; procp = &shm->proc_table[Anchor->MgrProcIndex]; procp->slot_session_count[slotID]++; XProcUnLock(); } void decr_sess_counts(CK_SLOT_ID slotID) { Slot_Mgr_Shr_t *shm; #ifdef PKCS64 Slot_Mgr_Proc_t_64 *procp; #else Slot_Mgr_Proc_t *procp; #endif // Get the slot mutex shm = Anchor->SharedMemP; XProcLock(); if (shm->slot_global_sessions[slotID] > 0) { shm->slot_global_sessions[slotID]--; } procp = &shm->proc_table[Anchor->MgrProcIndex]; if (procp->slot_session_count[slotID] > 0) { procp->slot_session_count[slotID]++; } XProcUnLock(); } // Check if any sessions from other applicaitons exist on this particular // token.... This will also validate our own sessions as well. // There might be an issue with the fact that a session is created but the // number is not incremented until the session allocation is completed by // the token. The API may need to lock the shared memory prior to creating // the session and then unlock when the stdll has completed its work. // Closing sessions should probably behave the same way. int sessions_exist(CK_SLOT_ID slotID) { Slot_Mgr_Shr_t *shm; uint32 numSessions; // Get the slot mutex shm = Anchor->SharedMemP; XProcLock(); numSessions = shm->slot_global_sessions[slotID]; XProcUnLock(); return numSessions != 0; } // Terminates all sessions associated with a given process // this cleans up any lingering sessions with the process // and does not // // It is only called from the C_Finalize routine void Terminate_All_Process_Sessions() { CK_SLOT_ID id; CK_RV rv; TRACE_DEBUG("Terminate_All_Process_Sessions\n"); for (id = 0; id < NUMBER_SLOTS_MANAGED; id++) { // Check if the slot is present in the slot manager // if not just skip it... if (slot_present(id) == TRUE) { rv = C_CloseAllSessions(id); } else { continue; } // If the return code is not OK, we are really hosed // since we are terminating the session. // For now we will just log it if (rv != CKR_OK) { TRACE_DEBUG("Terminate_All_Process_Sessions RV %lx\n", rv); } } } // Register the process with PKCSSLOTD in the // shared memory. // This call must be made with the API Global Mutex Locked // and the Anchor control block initialized with the // shared memory. No checking for shared memory validity is done int API_Register() { long int reuse = -1, free = -1; Slot_Mgr_Shr_t *shm; #ifdef PKCS64 Slot_Mgr_Proc_t_64 *procp; #else Slot_Mgr_Proc_t *procp; #endif uint16 indx; // Grab the Shared Memory lock to prevent other updates to the // SHM Process // The registration is done to allow for future handling of // the Slot Event List. Which is maintained by the Slotd. shm = Anchor->SharedMemP; XProcLock(); procp = shm->proc_table; for (indx = 0; indx < NUMBER_PROCESSES_ALLOWED; indx++, procp++) { // Is the entry in use if (procp->inuse == TRUE) { // Handle the weird case of the process terminating without // un-registering, and restarting with exactly the same PID // before the slot manager garbage collection can performed. // To eliminate the race condition between garbage collection // the lock should protect us. // This should be a VERY rare (if ever) occurance, given the // way AIX deals with re-allocation of PID;s, however if this // ever gets ported over to another platform we want to deal // with this accordingly since it may re-use pids differently // (Linux appears to re-use pids more rapidly). if (procp->proc_id == getpid()) { if (reuse == -1) { reuse = indx; } } } else { //Already found the first free if (free == -1) { free = indx; } } } // If we did not find a free entry then we fail the routine if ((reuse == -1) && (free == -1)) { XProcUnLock(); return FALSE; } // check if we are reusing a control block or taking the first free. // Since th mutex is helt, we don;t have to worry about some other // process grabbing the slot... Garbage collection from // the slotd should not affect this since it will grab the mutex // before doing its thing. if (reuse != -1) { procp = &(shm->proc_table[reuse]); indx = reuse; } else { procp = &(shm->proc_table[free]); indx = free; } #ifdef PKCS64 memset((char *)procp, 0, sizeof(Slot_Mgr_Proc_t_64)); #else memset((char *)procp, 0, sizeof(Slot_Mgr_Proc_t)); #endif procp->inuse = TRUE; procp->proc_id = getpid(); procp->reg_time = time(NULL); Anchor->MgrProcIndex = indx; TRACE_DEVEL("API_Register MgrProcIndc %d pid %ld \n", procp->proc_id, (long int)Anchor->MgrProcIndex); //??? What to do about the Mutex and cond variable //Does initializing them in the slotd allow for them to not be //initialized in the application. XProcUnLock(); return TRUE; } // DeRegister the process with PKCSSLOTD in the // shared memory. // This call must be made with the API Global Mutex Locked // and the Anchor control block initialized with the // shared memory. No checking for shared memory validity is done void API_UnRegister() { Slot_Mgr_Shr_t *shm; #ifdef PKCS64 Slot_Mgr_Proc_t_64 *procp; #else Slot_Mgr_Proc_t *procp; #endif // Grab the Shared Memory lock to prevent other updates to the // SHM Process // The registration is done to allow for future handling of // the Slot Event List. Which is maintained by the Slotd. shm = Anchor->SharedMemP; XProcLock(); procp = &(shm->proc_table[Anchor->MgrProcIndex]); #ifdef PKCS64 memset((char *)procp, 0, sizeof(Slot_Mgr_Proc_t_64)); #else memset((char *)procp, 0, sizeof(Slot_Mgr_Proc_t)); #endif Anchor->MgrProcIndex = 0; //??? What to do about the Mutex and cond variable //Does initializing them in the slotd allow for them to not be //initialized in the application. XProcUnLock(); } void DL_UnLoad(API_Slot_t *sltp, CK_SLOT_ID slotID) { Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); #ifdef PKCS64 Slot_Info_t_64 *sinfp; #else Slot_Info_t *sinfp; #endif sinfp = &(shData->slot_info[slotID]); if (sinfp->present == FALSE) { return; } if (!sltp->dlop_p) { return; } // Call the routine to properly unload the DLL DL_Unload(sltp); return; } int DL_Loaded(location, dllload) char *location; DLL_Load_t *dllload; { int i; for (i = 0; i < NUMBER_SLOTS_MANAGED; i++) { if (dllload[i].dll_name != NULL) { TRACE_DEBUG("DL_LOADED Looking for index %d name %s\n", i, dllload[i].dll_name); if (strcmp(location, dllload[i].dll_name) == 0) { return i; // Return the index of the dll } } } return -1; // Indicate failure to find the dll } int DL_Load(sinfp, sltp, dllload) #ifdef PKCS64 Slot_Info_t_64 *sinfp; #else Slot_Info_t *sinfp; #endif API_Slot_t *sltp; DLL_Load_t *dllload; { int i; TRACE_DEBUG("DL_LOAD\n"); for (i = 0; i < NUMBER_SLOTS_MANAGED; i++) { if (dllload[i].dll_name == NULL) { TRACE_DEBUG("Empty slot at %d \n", i); break; } } if (i == NUMBER_SLOTS_MANAGED) { TRACE_DEBUG("No empty slots.\n"); return 0; // Failed to find it.. } dllload[i].dll_name = sinfp->dll_location; // Point to the location dllload[i].dlop_p = dlopen(sinfp->dll_location, (RTLD_GLOBAL | RTLD_LAZY)); if (dllload[i].dlop_p != NULL) { sltp->dlop_p = dllload[i].dlop_p; sltp->dll_information = &dllload[i]; dllload[i].dll_load_count = 1;; } else { char *e = dlerror(); OCK_SYSLOG(LOG_ERR, "%s: dlopen() failed for [%s]; dlerror = [%s]\n", __FUNCTION__, sinfp->dll_location, e); TRACE_DEVEL("DL_Load of %s failed, dlerror: %s\n", sinfp->dll_location, e); sltp->dlop_p = NULL; return 0; } return 1; } void DL_Unload(sltp) API_Slot_t *sltp; { DLL_Load_t *dllload; // Decrement the count of loads. When 0 then unload this thing; // dllload = sltp->dll_information; dllload->dll_load_count--; if (dllload->dll_load_count == 0) { dlclose(dllload->dlop_p); dllload->dll_name = NULL; } // Clear out the slot information sltp->DLLoaded = FALSE; sltp->dlop_p = NULL; sltp->pSTfini = NULL; sltp->pSTcloseall = NULL; } int DL_Load_and_Init(API_Slot_t *sltp, CK_SLOT_ID slotID) { Slot_Mgr_Socket_t *shData = &(Anchor->SocketDataP); #ifdef PKCS64 Slot_Info_t_64 *sinfp; #else Slot_Info_t *sinfp; #endif int (*pSTinit) (); void (*pSTfini) (); CK_RV rv; int dll_len, dl_index; DLL_Load_t *dllload; // Get pointer to shared memory from the anchor block // sinfp = &(shData->slot_info[slotID]); dllload = Anchor->DLLs; // list of dll's in the system if (sinfp->present == FALSE) { return FALSE; } if ((dll_len = strlen(sinfp->dll_location))) { // Check if this DLL has been loaded already.. If so, just increment // the counter in the dllload structure and copy the data to // the slot pointer. if ((dl_index = DL_Loaded(sinfp->dll_location, dllload)) != -1) { dllload[dl_index].dll_load_count++; sltp->dll_information = &dllload[dl_index]; sltp->dlop_p = dllload[dl_index].dlop_p; } else { TRACE_DEBUG("DL_Load_and_Init dll_location %s\n", sinfp->dll_location); DL_Load(sinfp, sltp, dllload); } } else { return FALSE; } if (!sltp->dlop_p) { TRACE_DEBUG("DL_Load_and_Init pointer %p\n", sltp->dlop_p); return FALSE; } pSTinit = (int (*)())dlsym(sltp->dlop_p, "ST_Initialize"); if (!pSTinit) { // Unload the DLL DL_Unload(sltp); return FALSE; } // Returns true or false rv = pSTinit(&(sltp->FcnList), slotID, sinfp->confname, trace); TRACE_DEBUG("return from STDDLL Init = %lx\n", rv); if (rv != CKR_OK) { // clean up and unload DL_Unload(sltp); sltp->DLLoaded = FALSE; return FALSE; } else { sltp->DLLoaded = TRUE; // Check if a SC_Finalize function has been exported pSTfini = (void (*)())dlsym(sltp->dlop_p, "SC_Finalize"); sltp->pSTfini = pSTfini; sltp->pSTcloseall = (CK_RV(*)())dlsym(sltp->dlop_p, "SC_CloseAllSessions"); return TRUE; } return TRUE; } // copies internal representation of ck_info structure to local process // representation void CK_Info_From_Internal (CK_INFO_PTR dest, CK_INFO_PTR_64 src) { memset(dest, 0, sizeof(*dest)); dest->cryptokiVersion = src->cryptokiVersion; memset(dest->manufacturerID, '\0', 32); memcpy(dest->manufacturerID, src->manufacturerID, 32); dest->flags = src->flags; memcpy(dest->libraryDescription, src->libraryDescription, 32); dest->libraryVersion = src->libraryVersion; } opencryptoki+dfsg/usr/lib/pkcs11/api/socket_client.c0000644000175000017500000004172512630407154021534 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT Google Inc. 2013 */ // // Pkcs11 Api Socket client routines // #include #include #include #include #include #include #include #include #include #include #include "apiproto.h" #include "slotmgr.h" #include "apictl.h" extern API_Proc_Struct_t *Anchor; // // Will fill out the Slot_Mgr_Socket_t structure in the Anchor global data // structure with the values passed by the pkcsslotd via a socket RPC. int init_socket_data() { int socketfd; struct sockaddr_un daemon_address; struct stat file_info; struct group *grp; int bytes_received; Slot_Mgr_Socket_t daemon_socket_data; if (stat(SOCKET_FILE_PATH, &file_info)) { OCK_SYSLOG(LOG_ERR, "init_socket_data: failed to find socket file, errno=%d", errno); return FALSE; } grp = getgrnam("pkcs11"); if ( !grp ) { OCK_SYSLOG(LOG_ERR, "init_socket_data: pkcs11 group does not exist, errno=%d", errno); return FALSE; } if (file_info.st_uid != 0 || file_info.st_gid != grp->gr_gid) { OCK_SYSLOG(LOG_ERR, "init_socket_data: incorrect permissions on socket file"); return FALSE; } if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { OCK_SYSLOG(LOG_ERR, "init_socket_data: failed to create socket, errno=%d", errno); return FALSE; } memset(&daemon_address, 0, sizeof(struct sockaddr_un)); daemon_address.sun_family = AF_UNIX; strcpy(daemon_address.sun_path, SOCKET_FILE_PATH); if (connect(socketfd, (struct sockaddr *) &daemon_address, sizeof(struct sockaddr_un)) != 0) { OCK_SYSLOG(LOG_ERR, "init_socket_data: failed to connect to slot manager daemon, errno=%d", errno); close(socketfd); return FALSE; } bytes_received = read(socketfd, &daemon_socket_data, sizeof(daemon_socket_data)); if (bytes_received != sizeof(daemon_socket_data)) { OCK_SYSLOG(LOG_ERR, "init_socket_data: did not recieve expected number of bytes from slot manager daemon. Expected %zd bytes, got %d bytes.", sizeof(daemon_socket_data), bytes_received); } close(socketfd); memcpy(&(Anchor->SocketDataP), &daemon_socket_data, sizeof(Slot_Mgr_Socket_t)); return TRUE; } opencryptoki+dfsg/usr/lib/pkcs11/api/apiproto.h0000755000175000017500000004006712630407154020551 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/lib/pkcs11/api/apiproto.h,v 1.2 2006/04/05 20:07:45 kyoder Exp $ */ // /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ // // API local internal function prototypes // // // #ifndef _APIEXT_H #define _APIEXT_H #include "apictl.h" void *attach_shared_memory(); void detach_shared_memory(char *); int API_Initialized(); void Terminate_All_Process_Sessions(); int API_Register(); void API_UnRegister(); int DL_Load_and_Init(API_Slot_t *, CK_SLOT_ID); CK_RV CreateXProcLock(void); CK_RV XProcLock(void); CK_RV XProcUnLock(void); void _init(void); void get_sess_count(CK_SLOT_ID, CK_ULONG *); void incr_sess_counts(CK_SLOT_ID); void decr_sess_counts(CK_SLOT_ID); unsigned long AddToSessionList(ST_SESSION_T *); void RemoveFromSessionList(CK_SESSION_HANDLE); int Valid_Session(CK_SESSION_HANDLE, ST_SESSION_T *); void DL_UnLoad( API_Slot_t *, CK_SLOT_ID); void DL_Unload(API_Slot_t *); void CK_Info_From_Internal (CK_INFO_PTR dest, CK_INFO_PTR_64 src); int sessions_exist(CK_SLOT_ID); void CloseAllSessions(CK_SLOT_ID slot_id); int init_socket_data(); #define OCK_SYSLOG(priority, fmt, ...) \ syslog(priority, "%s " fmt, __FILE__, ##__VA_ARGS__); #endif opencryptoki+dfsg/usr/lib/pkcs11/api/Makefile.am0000644000175000017500000000303612630407154020567 0ustar xnoxxnoxnobase_lib_LTLIBRARIES = opencryptoki/libopencryptoki.la SO_CURRENT=0 SO_REVISION=0 SO_AGE=0 opencryptoki_libopencryptoki_la_LDFLAGS = -shared -Wl,-Bsymbolic -lc -ldl \ -lpthread -version-info \ $(SO_CURRENT):$(SO_REVISION):$(SO_AGE) # Not all versions of automake observe libname_CFLAGS opencryptoki_libopencryptoki_la_CFLAGS = -DAPI -DDEV -D_THREAD_SAFE \ -fPIC -I../. -I../../../include/pkcs11 \ -I ../common -DSTDLL_NAME=\"api\" opencryptoki_libopencryptoki_la_SOURCES = api_interface.c shrd_mem.c \ socket_client.c apiutil.c \ ../common/btree.c ../common/trace.c install-data-hook: $(MKDIR_P) $(DESTDIR)$(libdir)/opencryptoki/stdll $(MKDIR_P) $(DESTDIR)$(libdir)/pkcs11 cd $(DESTDIR)$(libdir)/opencryptoki && \ ln -sf libopencryptoki.so PKCS11_API.so cd $(DESTDIR)$(libdir)/opencryptoki && \ ln -sf $(sbindir) methods cd $(DESTDIR)$(libdir)/pkcs11 && \ ln -sf $(sbindir) methods cd $(DESTDIR)$(libdir)/pkcs11 && \ ln -sf ../opencryptoki/libopencryptoki.so PKCS11_API.so cd $(DESTDIR)$(libdir)/pkcs11 && \ ln -sf ../opencryptoki/libopencryptoki.so libopencryptoki.so cd $(DESTDIR)$(libdir)/pkcs11 && \ ln -sf ../opencryptoki/stdll/ stdll uninstall-hook: if test -d $(DESTDIR)$(libdir)/opencryptoki/stdll; then \ cd $(DESTDIR)$(libdir)/opencryptoki && \ rm -f PKCS11_API.so && \ rm -f methods; fi if test -d $(DESTDIR)$(libdir)/pkcs11; then \ cd $(DESTDIR)$(libdir)/pkcs11 && \ rm -f methods && \ rm -f PKCS11_API.so && \ rm -f libopencryptoki.so && \ rm -f stdll; fi opencryptoki+dfsg/usr/lib/pkcs11/api/shrd_mem.c.in0000644000175000017500000004335412630407154021111 0ustar xnoxxnoxstatic const char rcsid[] = "$Header: /cvsroot/opencryptoki/opencryptoki/usr/lib/pkcs11/api/shrd_mem.c.in,v 1.3 2007/09/06 15:40:10 tlendacky Exp $"; // /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ // // Pkcs11 Api Shared Memory Routines // #if NGPTH #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAPFILENAME "@CONFIG_PATH@/.apimap" extern API_Proc_Struct_t *Anchor; // // Will attach to the shared memory that has been created // by the slot manager daemon. // A NULL pointer will return if the memory region is invalid // for any reason void * attach_shared_memory() { int shmid; char *shmp; struct stat statbuf; struct group *grp; struct passwd *pw, *epw; uid_t uid, euid; #if !(MMAP) // Really should fstat the tok_path, since it will be the actual // executable of the slotmgr, however at this time we won't bother // for the prototype. /tmp/slotmgr will have to be an existing file. if (stat(TOK_PATH,&statbuf) < 0 ){ // The Stat token origin file does not work... Kick it out return NULL; } uid = getuid(); euid = geteuid(); // only check group membership if not root user if (uid != 0 && euid != 0) { int i, member=0; grp = getgrnam("pkcs11"); if (!grp) { // group pkcs11 not known to the system return NULL; } pw = getpwuid(uid); epw = getpwuid(euid); for (i=0; grp->gr_mem[i]; i++) { if (pw) { if (!strncmp(pw->pw_name, grp->gr_mem[i],strlen(pw->pw_name))) { member = 1; break; } } if (epw) { if (!strncmp(epw->pw_name, grp->gr_mem[i],strlen(epw->pw_name))) { member = 1; break; } } } if (!member) { return NULL; } } Anchor->shm_tok = ftok(TOK_PATH,'b'); // Get the shared memory id. shmid = shmget(Anchor->shm_tok,sizeof(Slot_Mgr_Shr_t), S_IWUSR|S_IWGRP|S_IRGRP|S_IRUSR); if ( shmid < 0 ) { return NULL; } shmp = (void *)shmat(shmid,NULL,0); if ( !shmp ) { return NULL; } return shmp; #else int fd; #warning "EXPERIMENTAL" fd = open(MAPFILENAME,O_RDWR); if (fd < 0 ){ return NULL; //Failed the file should exist and be valid } shmp = (char *)mmap(NULL,sizeof(Slot_Mgr_Shr_t),PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); close(fd); if ( ! shmp ) { return NULL; } return shmp; #endif } // //Detach the shared memory from the api when finished. // void detach_shared_memory( shmp ) char *shmp; { #if !(MMAP) shmdt(shmp); #else munmap(shmp,sizeof(Slot_Mgr_Shr_t)); #endif } opencryptoki+dfsg/usr/lib/pkcs11/tpm_stdll/0000755000175000017500000000000012630407154017762 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/tpm_stdll/tpm_util.c0000644000175000017500000001763212630407154021774 0ustar xnoxxnox /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 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 * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11/pkcs11types.h" #include "pkcs11/stdll.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" #include "tpm_specific.h" extern TSS_HCONTEXT tspContext; static struct { TSS_FLAG mode; const char *str; } tss_modes[] = { {TSS_SECRET_MODE_NONE, "TSS_SECRET_MODE_NONE"}, {TSS_SECRET_MODE_SHA1, "TSS_SECRET_MODE_SHA1"}, {TSS_SECRET_MODE_PLAIN,"TSS_SECRET_MODE_PLAIN"}, {TSS_SECRET_MODE_POPUP, "TSS_SECRET_MODE_POPUP"}, {TSS_SECRET_MODE_CALLBACK, "TSS_SECRET_MODE_CALLBACK"}, }; UINT32 util_get_keysize_flag(CK_ULONG size) { switch (size) { case 512: return TSS_KEY_SIZE_512; break; case 1024: return TSS_KEY_SIZE_1024; break; case 2048: return TSS_KEY_SIZE_2048; break; default: break; } return 0; } CK_BYTE * util_create_id(int type) { CK_BYTE *ret = NULL; int size = 0; switch (type) { case TPMTOK_PRIVATE_ROOT_KEY: size = TPMTOK_PRIVATE_ROOT_KEY_ID_SIZE + 1; if ((ret = malloc(size)) == NULL) { TRACE_ERROR("malloc of %d bytes failed.", size); break; } sprintf((char *)ret, "%s", TPMTOK_PRIVATE_ROOT_KEY_ID); break; case TPMTOK_PUBLIC_ROOT_KEY: size = TPMTOK_PUBLIC_ROOT_KEY_ID_SIZE + 1; if ((ret = malloc(size)) == NULL) { TRACE_ERROR("malloc of %d bytes failed.", size); break; } sprintf((char *)ret, "%s", TPMTOK_PUBLIC_ROOT_KEY_ID); break; case TPMTOK_PUBLIC_LEAF_KEY: size = TPMTOK_PUBLIC_LEAF_KEY_ID_SIZE + 1; if ((ret = malloc(size)) == NULL) { TRACE_ERROR("malloc of %d bytes failed.", size); break; } sprintf((char *)ret, "%s", TPMTOK_PUBLIC_LEAF_KEY_ID); break; case TPMTOK_PRIVATE_LEAF_KEY: size = TPMTOK_PRIVATE_LEAF_KEY_ID_SIZE + 1; if ((ret = malloc(size)) == NULL) { TRACE_ERROR("malloc of %d bytes failed.", size); break; } sprintf((char *)ret, "%s", TPMTOK_PRIVATE_LEAF_KEY_ID); break; default: TRACE_ERROR("Unknown type: %d\n", type); break; } return ret; } int util_set_file_mode(char *filename, mode_t mode) { struct stat file_stat; if (stat(filename, &file_stat) == -1) { TRACE_ERROR("stat failed: %s\n", strerror(errno)); return -1; } else if ((file_stat.st_mode ^ mode) != 0) { if (chmod(filename, mode) == -1) { TRACE_ERROR("chmod(%s) failed: %s\n", filename, strerror(errno)); return -1; } } return 0; } /* make sure the public exponent attribute is 65537 */ CK_ULONG util_check_public_exponent(TEMPLATE *tmpl) { CK_BBOOL flag; CK_ATTRIBUTE *publ_exp_attr; CK_BYTE pubexp_bytes[] = { 1, 0, 1 }; CK_ULONG publ_exp, rc = 1; flag = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &publ_exp_attr); if (!flag){ TRACE_ERROR("Couldn't find public exponent attribute.\n"); return CKR_TEMPLATE_INCOMPLETE; } switch (publ_exp_attr->ulValueLen) { case 3: rc = memcmp(pubexp_bytes, publ_exp_attr->pValue, 3); break; case sizeof(CK_ULONG): publ_exp = *((CK_ULONG *)publ_exp_attr->pValue); if (publ_exp == 65537) rc = 0; break; default: break; } return rc; } TSS_RESULT util_set_public_modulus(TSS_HKEY hKey, unsigned long size_n, unsigned char *n) { UINT64 offset; UINT32 blob_size; BYTE *blob, pub_blob[1024]; TCPA_PUBKEY pub_key; TSS_RESULT result; /* Get the TCPA_PUBKEY blob from the key object. */ result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blob_size, &blob); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_GetAttribData failed: rc=0x%x", result); return result; } offset = 0; result = Trspi_UnloadBlob_PUBKEY(&offset, blob, &pub_key); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_GetAttribData failed: rc=0x%x", result); return result; } Tspi_Context_FreeMemory(tspContext, blob); /* Free the first dangling reference, putting 'n' in its place */ free(pub_key.pubKey.key); pub_key.pubKey.keyLength = size_n; pub_key.pubKey.key = n; offset = 0; Trspi_LoadBlob_PUBKEY(&offset, pub_blob, &pub_key); /* Free the second dangling reference */ free(pub_key.algorithmParms.parms); /* set the public key data in the TSS object */ result = Tspi_SetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, (UINT32)offset, pub_blob); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_SetAttribData failed: rc=0x%x", result); return result; } return TSS_SUCCESS; } TSS_FLAG get_srk_mode(void) { char *mode = NULL; int i; int num_modes = sizeof(tss_modes)/sizeof(tss_modes[0]); mode = getenv("OCK_SRK_MODE"); if (mode == NULL) return 0; /* parse */ for (i = 0; i < num_modes; i++) { if (strncmp(mode, tss_modes[i].str, strlen(mode)) == 0) return tss_modes[i].mode; } TRACE_ERROR("Unknown TSS mode set in OCK_SRK_MODE, %s.\n", mode); return -1; } int get_srk_info(struct srk_info *srk) { char *passwd_ptr = NULL; char *secret = NULL; int i; srk->mode = get_srk_mode(); if (srk->mode == -1) return -1; srk->secret = NULL; passwd_ptr = getenv("OCK_SRK_SECRET"); /* If nothing is set, then use original opencryptoki default of * secret is NULL and TSS_SECRET_MODE_PLAIN. */ if (passwd_ptr == NULL) { srk->len = 0; if (srk->mode == 0) { srk->mode = TSS_SECRET_MODE_PLAIN; return 0; } } else srk->len = strlen(passwd_ptr); /* A mode required at this point... */ if (srk->mode == 0) { TRACE_ERROR("SRK policy's secret mode is not set.\n"); return -1; } /* * getenv() returns a ptr to the actual string in our env, * so be sure to make a copy to avoid problems. */ if (srk->len != 0) { if ((secret = (char *)malloc(srk->len)) == NULL) { TRACE_ERROR("malloc of %d bytes failed.\n", srk->len); return -1; } memcpy(secret, passwd_ptr, srk->len); srk->secret = secret; } /* Secrets that are a hash, need to be converted from a * hex string to an array of bytes. */ if (srk->mode == TSS_SECRET_MODE_SHA1) { char *secret_h; int h_len = TPM_SHA1_160_HASH_LEN; if ((secret_h = (char *)malloc(h_len)) == NULL) { TRACE_ERROR("malloc of %d bytes failed.\n", h_len); goto error; } /* reuse passwd ptr since we dont need it anymore. */ passwd_ptr = secret; /* Assume hash is read in as string of hexidecimal digits. * 2 hex digits are required to represent a byte. * thus we need 2 * TPM_SHA1_160_HASH_LEN to * represent the hash. */ if (srk->len != (h_len * 2)) { free(secret_h); TRACE_DEVEL("Hashed secret is %d bytes, expected %d.\n", srk->len, h_len*2); goto error; } /* convert hexadecimal string into a byte array... */ for (i = 0; i < h_len; i++) { sscanf(passwd_ptr, "%2hhx", &secret_h[i]); passwd_ptr += 2; } srk->len = h_len; srk->secret = secret_h; free(secret); } return 0; error: if (secret) free(secret); return -1; } opencryptoki+dfsg/usr/lib/pkcs11/tpm_stdll/defs.h0000755000175000017500000000056712630407154021067 0ustar xnoxxnox /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ // File: defs.h // // Contains various definitions needed by both the host-side // and coprocessor-side code. // #ifndef _TPM_DEFS_H #define _TPM_DEFS_H #include "../common/defs.h" #undef MAX_PIN_LEN #undef MIN_PIN_LEN #define MAX_PIN_LEN 127 #define MIN_PIN_LEN 6 #endif opencryptoki+dfsg/usr/lib/pkcs11/tpm_stdll/tpm_specific.c0000644000175000017500000030215312630407154022577 0ustar xnoxxnox /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 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 * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* * tpm_specific.c * * Feb 10, 2005 * * Author: Kent Yoder * * Encryption routines are based on ../soft_stdll/soft_specific.c. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef NODH #include #endif #include #include #include #include #include #include #include #include #include "pkcs11/pkcs11types.h" #include "pkcs11/stdll.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_specific.h" #include "tok_spec_struct.h" #include "tok_struct.h" #include "trace.h" #include "tpm_specific.h" #include "../api/apiproto.h" TSS_RESULT util_set_public_modulus(TSS_HKEY, unsigned long, unsigned char *); CK_CHAR manuf[] = "IBM Corp."; CK_CHAR model[] = "TPM v1.1 Token"; CK_CHAR descr[] = "Token for the Trusted Platform Module"; CK_CHAR label[] = "IBM PKCS#11 TPM Token"; MECH_LIST_ELEMENT mech_list[] = { {CKM_RSA_PKCS_KEY_PAIR_GEN, {512, 2048, CKF_GENERATE_KEY_PAIR}}, {CKM_DES_KEY_GEN, {0, 0, CKF_GENERATE}}, {CKM_DES3_KEY_GEN, {0, 0, CKF_GENERATE}}, {CKM_RSA_PKCS, {512, 2048, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP|CKF_SIGN|CKF_VERIFY|CKF_SIGN_RECOVER| CKF_VERIFY_RECOVER}}, {CKM_MD5_RSA_PKCS, {512, 2048, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA1_RSA_PKCS, {512, 2048, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_DES_ECB, {0, 0, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES_CBC, {0, 0, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES_CBC_PAD, {0, 0, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES3_ECB, {0, 0, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES3_CBC, {0, 0, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES3_CBC_PAD, {0, 0, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_SHA_1, {0, 0, CKF_DIGEST}}, {CKM_SHA_1_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA_1_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_MD5, {0, 0, CKF_DIGEST}}, {CKM_MD5_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_MD5_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_SSL3_PRE_MASTER_KEY_GEN, {48, 48, CKF_GENERATE}}, {CKM_SSL3_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}}, {CKM_SSL3_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}}, {CKM_SSL3_MD5_MAC, {384, 384, CKF_SIGN|CKF_VERIFY}}, {CKM_SSL3_SHA1_MAC, {384, 384, CKF_SIGN|CKF_VERIFY}}, {CKM_AES_KEY_GEN, {16, 32, CKF_GENERATE}}, {CKM_AES_ECB, {16, 32, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_AES_CBC, {16, 32, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_AES_CBC_PAD, {16, 32, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, }; CK_ULONG mech_list_len = (sizeof(mech_list) / sizeof(MECH_LIST_ELEMENT)); CK_BYTE master_key_private[MK_SIZE]; /* The context we'll use globally to connect to the TSP */ TSS_HCONTEXT tspContext = NULL_HCONTEXT; /* TSP key handles */ TSS_HKEY hSRK = NULL_HKEY; TSS_HKEY hPublicRootKey = NULL_HKEY; TSS_HKEY hPublicLeafKey = NULL_HKEY; TSS_HKEY hPrivateRootKey = NULL_HKEY; TSS_HKEY hPrivateLeafKey = NULL_HKEY; /* TSP policy handles */ TSS_HPOLICY hDefaultPolicy = NULL_HPOLICY; /* PKCS#11 key handles */ CK_OBJECT_HANDLE ckPublicRootKey = 0; CK_OBJECT_HANDLE ckPublicLeafKey = 0; CK_OBJECT_HANDLE ckPrivateRootKey = 0; CK_OBJECT_HANDLE ckPrivateLeafKey = 0; int not_initialized = 0; CK_BYTE current_user_pin_sha[SHA1_HASH_SIZE]; CK_BYTE current_so_pin_sha[SHA1_HASH_SIZE]; CK_RV token_specific_rng(CK_BYTE *output, CK_ULONG bytes) { TSS_RESULT rc; TSS_HTPM hTPM; BYTE *random_bytes = NULL; if ((rc = Tspi_Context_GetTpmObject(tspContext, &hTPM))) { TRACE_ERROR("Tspi_Context_GetTpmObject: %x\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = Tspi_TPM_GetRandom(hTPM, bytes, &random_bytes))) { TRACE_ERROR("Tspi_TPM_GetRandom failed. rc=0x%x\n", rc); return CKR_FUNCTION_FAILED; } memcpy(output, random_bytes, bytes); Tspi_Context_FreeMemory(tspContext, random_bytes); return CKR_OK; } CK_RV token_specific_init(CK_SLOT_ID SlotNumber, char *conf_name) { TSS_RESULT result; char path_buf[PATH_MAX], fname[PATH_MAX]; struct stat statbuf; // if the user specific directory doesn't exist, create it sprintf(path_buf, "%s", get_pk_dir(fname)); if (stat(path_buf, &statbuf) < 0) { if (mkdir(path_buf, S_IRUSR|S_IWUSR|S_IXUSR) == -1) { TRACE_ERROR("mkdir(%s): %s\n", path_buf, strerror(errno)); return CKR_FUNCTION_FAILED; } } // now create userdir/TOK_OBJ if it doesn't exist strncat(path_buf, "/", 1); strncat(path_buf, PK_LITE_OBJ_DIR, strlen(PK_LITE_OBJ_DIR)); if (stat(path_buf, &statbuf) < 0) { if (mkdir(path_buf, S_IRUSR|S_IWUSR|S_IXUSR) == -1) { TRACE_ERROR("mkdir(%s): %s\n", path_buf, strerror(errno)); return CKR_FUNCTION_FAILED; } } if ((result = Tspi_Context_Create(&tspContext))) { TRACE_ERROR("Tspi_Context_Create failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_Context_Connect(tspContext, NULL))) { TRACE_ERROR("Tspi_Context_Connect failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_Context_GetDefaultPolicy(tspContext, &hDefaultPolicy))) { TRACE_ERROR("Tspi_Context_GetDefaultPolicy failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } OpenSSL_add_all_algorithms(); return CKR_OK; } CK_RV token_find_key(int key_type, CK_OBJECT_CLASS class, CK_OBJECT_HANDLE *handle) { CK_BYTE *key_id = util_create_id(key_type); CK_RV rc = CKR_OK; CK_BBOOL true = TRUE; CK_ATTRIBUTE tmpl[] = { {CKA_ID, key_id, strlen((char *)key_id)}, {CKA_CLASS, &class, sizeof(class)}, {CKA_HIDDEN, &true, sizeof(CK_BBOOL)} }; CK_OBJECT_HANDLE hObj; CK_ULONG ulObjCount; SESSION dummy_sess; /* init the dummy session state to something that will find any object on * the token */ memset(&dummy_sess, 0, sizeof(SESSION)); dummy_sess.session_info.state = CKS_RO_USER_FUNCTIONS; if ((rc = object_mgr_find_init(&dummy_sess, tmpl, 3))) { goto done; } /* pulled from SC_FindObjects */ ulObjCount = MIN(1, (dummy_sess.find_count - dummy_sess.find_idx)); memcpy( &hObj, dummy_sess.find_list + dummy_sess.find_idx, ulObjCount * sizeof(CK_OBJECT_HANDLE) ); dummy_sess.find_idx += ulObjCount; if (ulObjCount > 1) { TRACE_INFO("More than one matching key found in the store!\n"); rc = CKR_KEY_NOT_FOUND; goto done; } else if (ulObjCount < 1) { TRACE_INFO("key with ID=\"%s\" not found in the store!\n", key_id); rc = CKR_KEY_NOT_FOUND; goto done; } *handle = hObj; done: object_mgr_find_final(&dummy_sess); free(key_id); return rc; } CK_RV token_get_key_blob(CK_OBJECT_HANDLE ckKey, CK_ULONG *blob_size, CK_BYTE **ret_blob) { CK_RV rc = CKR_OK; CK_BYTE_PTR blob = NULL; CK_ATTRIBUTE tmpl[] = { {CKA_IBM_OPAQUE, NULL_PTR, 0} }; SESSION dummy_sess; /* set up dummy session */ memset(&dummy_sess, 0, sizeof(SESSION)); dummy_sess.session_info.state = CKS_RO_USER_FUNCTIONS; /* find object the first time to return the size of the buffer needed */ if ((rc = object_mgr_get_attribute_values(&dummy_sess, ckKey, tmpl, 1))) { TRACE_DEVEL("object_mgr_get_attribute_values failed:rc=0x%lx\n", rc); goto done; } blob = malloc(tmpl[0].ulValueLen); if (blob == NULL) { TRACE_ERROR("malloc %ld bytes failed.\n", tmpl[0].ulValueLen); rc = CKR_HOST_MEMORY; goto done; } tmpl[0].pValue = blob; /* find object the 2nd time to fill the buffer with data */ if ((rc = object_mgr_get_attribute_values(&dummy_sess, ckKey, tmpl, 1))) { TRACE_DEVEL("object_mgr_get_attribute_values failed:rc=0x%lx\n", rc); goto done; } *ret_blob = blob; *blob_size = tmpl[0].ulValueLen; done: return rc; } CK_RV token_wrap_sw_key(int size_n, unsigned char *n, int size_p, unsigned char *p, TSS_HKEY hParentKey, TSS_FLAG initFlags, TSS_HKEY *phKey) { TSS_RESULT result; TSS_HPOLICY hPolicy; static TSS_BOOL get_srk_pub_key = TRUE; UINT32 key_size; key_size = util_get_keysize_flag(size_n * 8); if (initFlags == 0) { TRACE_ERROR("Invalid key size.\n"); return CKR_FUNCTION_FAILED; } /* create the TSS key object */ result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_RSAKEY, TSS_KEY_MIGRATABLE | initFlags | key_size, phKey); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Context_CreateObject failed: rc=0x%x\n", result); return result; } result = util_set_public_modulus(*phKey, size_n, n); if (result != TSS_SUCCESS) { TRACE_DEVEL("util_set_public_modulus failed:rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); *phKey = NULL_HKEY; return result; } /* set the private key data in the TSS object */ result = Tspi_SetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY, size_p, p); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_SetAttribData failed: rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); *phKey = NULL_HKEY; return result; } /* if the parent wrapping key is the SRK, we need to manually pull * out the SRK's pub key, which is not stored in persistent storage * for privacy reasons */ if (hParentKey == hSRK && get_srk_pub_key == TRUE) { UINT32 pubKeySize; BYTE *pubKey; result = Tspi_Key_GetPubKey(hParentKey, &pubKeySize, &pubKey); if (result != TSS_SUCCESS) { if (result == TPM_E_INVALID_KEYHANDLE) { OCK_SYSLOG(LOG_WARNING, "Warning: Your TPM is not configured to allow " "reading the public SRK by anyone but the owner. Use " "tpm_restrictsrk -a to allow reading the public SRK"); } else { OCK_SYSLOG(LOG_ERR, "Tspi_Key_GetPubKey failed: rc=0x%x", result); } Tspi_Context_CloseObject(tspContext, *phKey); *phKey = NULL_HKEY; return result; } Tspi_Context_FreeMemory(tspContext, pubKey); get_srk_pub_key = FALSE; } result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION, &hPolicy); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Context_CreateObject: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); *phKey = NULL_HKEY; return result; } result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE, 0, NULL); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Policy_SetSecret failed. rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); *phKey = NULL_HKEY; return result; } result = Tspi_Policy_AssignToObject(hPolicy, *phKey); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Policy_AssignToObject: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); *phKey = NULL_HKEY; return result; } if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) { if ((result = Tspi_SetAttribUint32(*phKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15))) { TRACE_ERROR("Tspi_SetAttribUint32 failed. rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); return result; } if ((result = Tspi_SetAttribUint32(*phKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME, TSS_SS_RSASSAPKCS1V15_DER))) { TRACE_ERROR("Tspi_SetAttribUint32 failed. rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); return result; } } result = Tspi_Key_WrapKey(*phKey, hParentKey, NULL_HPCRS); if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Key_WrapKey failed: rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); *phKey = NULL_HKEY; } return result; } /* * Create a TPM key blob for an imported key. This function is only called when * a key is in active use, so any failure should trickle through. */ CK_RV token_wrap_key_object( CK_OBJECT_HANDLE ckObject, TSS_HKEY hParentKey, TSS_HKEY *phKey ) { CK_RV rc = CKR_OK; CK_ATTRIBUTE *attr = NULL, *new_attr, *prime_attr; CK_ULONG class, key_type; CK_BBOOL found; OBJECT *obj; TSS_RESULT result; TSS_FLAG initFlags = 0; BYTE *rgbBlob; UINT32 ulBlobLen; if ((rc = object_mgr_find_in_map1(ckObject, &obj))) { TRACE_DEVEL("object_mgr_find_in_map1 failed. rc=0x%lx\n", rc); return rc; } /* if the object isn't a key, fail */ if ((found = template_attribute_find(obj->template, CKA_KEY_TYPE, &attr)) == FALSE) { TRACE_ERROR("template_attribute_find(CKA_KEY_TYPE) failed.\n"); return CKR_FUNCTION_FAILED; } key_type = *((CK_ULONG *)attr->pValue); if (key_type != CKK_RSA) { TRACE_ERROR("Bad key type!\n"); return CKR_FUNCTION_FAILED; } if ((found = template_attribute_find(obj->template, CKA_CLASS, &attr)) == FALSE) { TRACE_ERROR("template_attribute_find(CKA_CLASS) failed.\n"); return CKR_FUNCTION_FAILED; } class = *((CK_ULONG *)attr->pValue); if (class == CKO_PRIVATE_KEY) { /* In order to create a full TSS key blob using a PKCS#11 private key * object, we need one of the two primes, the modulus and the private * exponent and we need the public exponent to be correct */ /* check the least likely attribute to exist first, the primes */ if ((found = template_attribute_find(obj->template, CKA_PRIME_1, &prime_attr)) == FALSE) { if ((found = template_attribute_find(obj->template, CKA_PRIME_2, &prime_attr)) == FALSE) { TRACE_ERROR("Couldn't find prime1 or prime2 of" " key object to wrap\n"); return CKR_TEMPLATE_INCONSISTENT; } } /* Make sure the public exponent is usable */ if ((util_check_public_exponent(obj->template))) { TRACE_ERROR("Invalid public exponent\n"); return CKR_TEMPLATE_INCONSISTENT; } /* get the modulus */ if ((found = template_attribute_find(obj->template, CKA_MODULUS, &attr)) == FALSE) { TRACE_ERROR("Couldn't find a required attribute of " "key object\n"); return CKR_FUNCTION_FAILED; } /* make sure the key size is usable */ initFlags = util_get_keysize_flag(attr->ulValueLen * 8); if (initFlags == 0) { TRACE_ERROR("Invalid key size.\n"); return CKR_TEMPLATE_INCONSISTENT; } /* generate the software based key */ if ((rc = token_wrap_sw_key((int)attr->ulValueLen, attr->pValue, (int)prime_attr->ulValueLen, prime_attr->pValue, hParentKey, TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION, phKey))) { TRACE_DEVEL("token_wrap_sw_key failed. rc=0x%lu\n", rc); return rc; } } else if (class == CKO_PUBLIC_KEY) { /* Make sure the public exponent is usable */ if ((util_check_public_exponent(obj->template))) { TRACE_DEVEL("Invalid public exponent\n"); return CKR_TEMPLATE_INCONSISTENT; } /* grab the modulus to put into the TSS key object */ if ((found = template_attribute_find(obj->template, CKA_MODULUS, &attr)) == FALSE) { TRACE_ERROR("Couldn't find a required attribute of " "key object\n"); return CKR_TEMPLATE_INCONSISTENT; } /* make sure the key size is usable */ initFlags = util_get_keysize_flag(attr->ulValueLen * 8); if (initFlags == 0) { TRACE_ERROR("Invalid key size.\n"); return CKR_TEMPLATE_INCONSISTENT; } initFlags |= TSS_KEY_TYPE_LEGACY | TSS_KEY_MIGRATABLE | TSS_KEY_NO_AUTHORIZATION; if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) { TRACE_ERROR("Tspi_Context_CreateObject failed. " "rc=0x%x\n", result); return result; } if ((result = util_set_public_modulus(*phKey, attr->ulValueLen, attr->pValue))) { TRACE_DEVEL("util_set_public_modulus failed: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); *phKey = NULL_HKEY; return CKR_FUNCTION_FAILED; } } else { TRACE_ERROR("Bad key class!\n"); return CKR_FUNCTION_FAILED; } /* grab the entire key blob to put into the PKCS#11 object */ if ((result = Tspi_GetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { TRACE_ERROR("Tspi_GetAttribData failed with rc: 0x%x\n",result); return CKR_FUNCTION_FAILED; } /* insert the key blob into the object */ if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, &new_attr))) { TRACE_DEVEL("build_atribute failed\n"); Tspi_Context_FreeMemory(tspContext, rgbBlob); return rc; } template_update_attribute( obj->template, new_attr ); Tspi_Context_FreeMemory(tspContext, rgbBlob); /* if this is a token object, save it with the new attribute so that we * don't have to go down this path again */ if (!object_is_session_object(obj)) { rc = save_token_object(obj); } return rc; } /* * load a key in the TSS hierarchy from its CK_OBJECT_HANDLE */ CK_RV token_load_key(CK_OBJECT_HANDLE ckKey, TSS_HKEY hParentKey, CK_CHAR_PTR passHash, TSS_HKEY *phKey) { TSS_RESULT result; TSS_HPOLICY hPolicy; CK_BYTE *blob = NULL; CK_ULONG ulBlobSize = 0; CK_RV rc; if ((rc = token_get_key_blob(ckKey, &ulBlobSize, &blob))) { if (rc != CKR_ATTRIBUTE_TYPE_INVALID) { TRACE_DEVEL("token_get_key_blob failed. rc=0x%lx\n", rc); return rc; } /* the key blob wasn't found, so check for a modulus * to load */ TRACE_DEVEL("key blob not found, checking for modulus\n"); if ((rc = token_wrap_key_object(ckKey, hParentKey, phKey))) { TRACE_DEVEL("token_wrap_key_object failed. rc=0x%lx\n", rc); return rc; } } if (blob != NULL) { /* load the key inside the TSS */ if ((result = Tspi_Context_LoadKeyByBlob(tspContext, hParentKey, ulBlobSize, blob, phKey))) { TRACE_ERROR("Tspi_Context_LoadKeyByBlob: 0x%x\n", result); goto done; } } #if 0 if ((result = Tspi_GetPolicyObject(*phKey, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_GetPolicyObject: 0x%x\n", result); goto done; } #else if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_Context_CreateObject: 0x%x\n", result); goto done; } #endif if (passHash == NULL) { result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE, 0, NULL); } else { result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, SHA1_HASH_SIZE, passHash); } if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Policy_SetSecret: 0x%x\n", result); goto done; } if ((result = Tspi_Policy_AssignToObject(hPolicy, *phKey))) { TRACE_ERROR("Tspi_Policy_AssignToObject: 0x%x\n", result); goto done; } done: free(blob); return result; } TSS_RESULT token_load_srk() { TSS_HPOLICY hPolicy; TSS_RESULT result; TSS_UUID SRK_UUID = TSS_UUID_SRK; struct srk_info srk; if (hSRK != NULL_HKEY) return TSS_SUCCESS; /* load the SRK */ if ((result = Tspi_Context_LoadKeyByUUID(tspContext, TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSRK))) { TRACE_ERROR("Tspi_Context_LoadKeyByUUID failed. rc=0x%x\n", result); goto done; } #if 0 if ((result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_GetPolicyObject failed. rc=0x%x\n", result); goto done; } #else if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); goto done; } if ((result = Tspi_Policy_AssignToObject(hPolicy, hSRK))) { TRACE_ERROR("Tspi_Policy_AssignToObject failed. rc=0x%x\n", result); goto done; } #endif /* get the srk info */ memset(&srk, 0, sizeof(srk)); if (get_srk_info(&srk)) return -1; if ((result = Tspi_Policy_SetSecret(hPolicy, (TSS_FLAG)srk.mode, srk.len, (BYTE *)srk.secret))) { TRACE_ERROR("Tspi_Policy_SetSecret failed. rc=0x%x\n", result); } if (srk.secret) free(srk.secret); done: return result; } TSS_RESULT token_load_public_root_key() { TSS_RESULT result; BYTE *blob; CK_ULONG blob_size; if (hPublicRootKey != NULL_HKEY) return TSS_SUCCESS; if ((result = token_load_srk())) { TRACE_DEVEL("token_load_srk failed. rc=0x%x\n", result); return result; } if ((result = token_find_key(TPMTOK_PUBLIC_ROOT_KEY, CKO_PRIVATE_KEY, &ckPublicRootKey))) { TRACE_ERROR("token_find_key failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = token_get_key_blob(ckPublicRootKey, &blob_size, &blob))) { TRACE_DEVEL("token_get_key_blob failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* load the Public Root Key */ if ((result = Tspi_Context_LoadKeyByBlob(tspContext, hSRK, blob_size, blob, &hPublicRootKey))) { TRACE_ERROR("Tspi_Context_LoadKeyByBlob failed. rc=0x%x\n", result); free(blob); return CKR_FUNCTION_FAILED; } free(blob); return result; } TSS_RESULT tss_generate_key(TSS_FLAG initFlags, BYTE *passHash, TSS_HKEY hParentKey, TSS_HKEY *phKey) { TSS_RESULT result; TSS_HPOLICY hPolicy, hMigPolicy; if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); return result; } #if 0 if ((result = Tspi_GetPolicyObject(*phKey, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_GetPolicyObject failed. rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); return result; } #else if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_Context_CreateObject: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); return result; } #endif if (passHash == NULL) { result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE, 0, NULL); } else { result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, 20, passHash); } if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Policy_SetSecret failed. rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); return result; } if ((result = Tspi_Policy_AssignToObject(hPolicy, *phKey))) { TRACE_ERROR("Tspi_Policy_AssignToObject: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); return result; } if (TPMTOK_TSS_KEY_MIG_TYPE(initFlags) == TSS_KEY_MIGRATABLE) { if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION, &hMigPolicy))) { TRACE_ERROR("Tspi_Context_CreateObject: 0x%x\n",result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); return result; } if (passHash == NULL) { result = Tspi_Policy_SetSecret(hMigPolicy, TSS_SECRET_MODE_NONE, 0, NULL); } else { result = Tspi_Policy_SetSecret(hMigPolicy, TSS_SECRET_MODE_SHA1, 20, passHash); } if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Policy_SetSecret failed. rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); Tspi_Context_CloseObject(tspContext, hMigPolicy); return result; } if ((result = Tspi_Policy_AssignToObject(hMigPolicy, *phKey))) { TRACE_ERROR("Tspi_Policy_AssignToObject: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); Tspi_Context_CloseObject(tspContext, hMigPolicy); return result; } } if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) { if ((result = Tspi_SetAttribUint32(*phKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15))) { TRACE_ERROR("Tspi_SetAttribUint32 failed. rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); Tspi_Context_CloseObject(tspContext, hMigPolicy); return result; } if ((result = Tspi_SetAttribUint32(*phKey, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME, TSS_SS_RSASSAPKCS1V15_DER))) { TRACE_ERROR("Tspi_SetAttribUint32 failed. rc=0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); Tspi_Context_CloseObject(tspContext, hMigPolicy); return result; } } if ((result = Tspi_Key_CreateKey(*phKey, hParentKey, 0))) { TRACE_ERROR("Tspi_Key_CreateKey failed with rc: 0x%x\n",result); Tspi_Context_CloseObject(tspContext, *phKey); Tspi_Context_CloseObject(tspContext, hPolicy); Tspi_Context_CloseObject(tspContext, hMigPolicy); } return result; } TSS_RESULT tss_change_auth(TSS_HKEY hObjectToChange, TSS_HKEY hParentObject, CK_CHAR *passHash) { TSS_RESULT result; TSS_HPOLICY hPolicy; if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_Context_CreateObject failed: 0x%x\n", result); return result; } if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, SHA1_HASH_SIZE, passHash))) { TRACE_ERROR("Tspi_Policy_SetSecret failed: 0x%x\n", result); return result; } if ((result = Tspi_ChangeAuth(hObjectToChange, hParentObject, hPolicy))) { TRACE_ERROR("Tspi_ChangeAuth failed: 0x%x\n", result); } return result; } CK_RV token_store_priv_key(TSS_HKEY hKey, int key_type, CK_OBJECT_HANDLE *ckKey) { CK_ATTRIBUTE *new_attr = NULL; OBJECT *priv_key_obj = NULL; BYTE *rgbBlob = NULL, *rgbPrivBlob = NULL; UINT32 ulBlobLen = 0, ulPrivBlobLen = 0; CK_BBOOL flag; CK_BYTE *key_id = util_create_id(key_type); CK_RV rc; SESSION dummy_sess; /* set up dummy session */ memset(&dummy_sess, 0, sizeof(SESSION)); dummy_sess.session_info.state = CKS_RW_USER_FUNCTIONS; /* grab the entire key blob to put into the PKCS#11 private key object */ if ((rc = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { TRACE_ERROR("Tspi_GetAttribData failed with rc: 0x%lx\n", rc); free(key_id); return rc; } /* grab the encrypted provate key to put into the object */ if ((rc = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY, &ulPrivBlobLen, &rgbPrivBlob))) { TRACE_ERROR("Tspi_GetAttribData failed with rc: 0x%lx\n", rc); Tspi_Context_FreeMemory(tspContext, rgbBlob); free(key_id); return rc; } /* create skeleton for the private key object */ if ((rc = object_create_skel(NULL, 0, MODE_KEYGEN, CKO_PRIVATE_KEY, CKK_RSA, &priv_key_obj))) { TRACE_DEVEL("objectr_create_skel: 0x%lx\n", rc); Tspi_Context_FreeMemory(tspContext, rgbBlob); Tspi_Context_FreeMemory(tspContext, rgbPrivBlob); free(key_id); return rc; } /* add the ID attribute */ if ((rc = build_attribute(CKA_ID, key_id, strlen((char *)key_id), &new_attr))) { TRACE_DEVEL("build_attribute failed\n"); Tspi_Context_FreeMemory(tspContext, rgbBlob); Tspi_Context_FreeMemory(tspContext, rgbPrivBlob); free(key_id); return rc; } template_update_attribute( priv_key_obj->template, new_attr ); free(key_id); /* add the key blob to the PKCS#11 object template */ if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, &new_attr))) { TRACE_DEVEL("build_attribute failed\n"); Tspi_Context_FreeMemory(tspContext, rgbBlob); Tspi_Context_FreeMemory(tspContext, rgbPrivBlob); return rc; } template_update_attribute( priv_key_obj->template, new_attr ); Tspi_Context_FreeMemory(tspContext, rgbBlob); /* add the private key blob to the PKCS#11 object template */ if ((rc = build_attribute(CKA_MODULUS, rgbPrivBlob, ulPrivBlobLen, &new_attr))) { TRACE_DEVEL("build_attribute failed\n"); Tspi_Context_FreeMemory(tspContext, rgbPrivBlob); return rc; } template_update_attribute( priv_key_obj->template, new_attr ); Tspi_Context_FreeMemory(tspContext, rgbPrivBlob); /* add the HIDDEN attribute */ flag = TRUE; if ((rc = build_attribute(CKA_HIDDEN, &flag, sizeof(CK_BBOOL), &new_attr))) { TRACE_DEVEL("build_attribute failed\n"); free(key_id); return rc; } template_update_attribute( priv_key_obj->template, new_attr ); /* set CKA_ALWAYS_SENSITIVE to true */ if ((rc = build_attribute( CKA_ALWAYS_SENSITIVE, &flag, sizeof(CK_BBOOL), &new_attr ))) { TRACE_DEVEL("build_attribute failed\n"); return rc; } template_update_attribute( priv_key_obj->template, new_attr ); /* set CKA_NEVER_EXTRACTABLE to true */ if ((rc = build_attribute( CKA_NEVER_EXTRACTABLE, &flag, sizeof(CK_BBOOL), &new_attr ))) { TRACE_DEVEL("build_attribute failed\n"); return rc; } template_update_attribute( priv_key_obj->template, new_attr ); /* make the object reside on the token, as if that were possible */ if ((rc = build_attribute( CKA_TOKEN, &flag, sizeof(CK_BBOOL), &new_attr ))) { TRACE_DEVEL("build_attribute failed\n"); return rc; } template_update_attribute( priv_key_obj->template, new_attr ); flag = FALSE; if ((rc = build_attribute( CKA_PRIVATE, &flag, sizeof(CK_BBOOL), &new_attr ))) { TRACE_DEVEL("build_attribute failed\n"); return rc; } template_update_attribute( priv_key_obj->template, new_attr ); if ((rc = object_mgr_create_final(&dummy_sess, priv_key_obj, ckKey))) { TRACE_DEVEL("object_mgr_create_final failed.\n"); } return rc; } CK_RV token_store_pub_key(TSS_HKEY hKey, int key_type, CK_OBJECT_HANDLE *ckKey) { CK_RV rc; TSS_RESULT result; CK_ATTRIBUTE *new_attr = NULL; OBJECT *pub_key_obj; CK_BBOOL flag = TRUE; CK_OBJECT_CLASS pub_class = CKO_PUBLIC_KEY; CK_KEY_TYPE type = CKK_RSA; CK_BYTE *key_id = util_create_id(key_type); CK_BYTE pub_exp[] = { 1, 0, 1 }; // 65537 CK_ATTRIBUTE pub_tmpl[] = { {CKA_CLASS, &pub_class, sizeof(pub_class)}, {CKA_KEY_TYPE, &type, sizeof(type)}, {CKA_ID, key_id, strlen((char *)key_id)}, {CKA_PUBLIC_EXPONENT, pub_exp, sizeof(pub_exp)}, {CKA_MODULUS, NULL_PTR, 0} }; BYTE *rgbPubBlob = NULL; UINT32 ulBlobLen = 0; SESSION dummy_sess; /* set up dummy session */ memset(&dummy_sess, 0, sizeof(SESSION)); dummy_sess.session_info.state = CKS_RW_USER_FUNCTIONS; /* grab the public key to put into the PKCS#11 public key object */ if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &ulBlobLen, &rgbPubBlob))) { TRACE_ERROR("Tspi_GetAttribData failed with rc: 0x%x\n",result); Tspi_Context_CloseObject(tspContext, hKey); free(key_id); return result; } pub_tmpl[4].pValue = rgbPubBlob; pub_tmpl[4].ulValueLen = ulBlobLen; /* create skeleton for the private key object */ if ((rc = object_create_skel(pub_tmpl, 5, MODE_CREATE, CKO_PUBLIC_KEY, CKK_RSA, &pub_key_obj))) { TRACE_DEVEL("object_create_skel: 0x%lx\n", rc); Tspi_Context_CloseObject(tspContext, hKey); free(key_id); return rc; } Tspi_Context_FreeMemory(tspContext, rgbPubBlob); /* make the object reside on the token, as if that were possible */ if ((rc = build_attribute( CKA_TOKEN, &flag, sizeof(CK_BBOOL), &new_attr ))) { TRACE_DEVEL("build attribute failed.\n"); goto done; } template_update_attribute( pub_key_obj->template, new_attr ); /* set the object to be hidden */ if ((rc = build_attribute( CKA_HIDDEN, &flag, sizeof(CK_BBOOL), &new_attr ))) { TRACE_DEVEL("build attribute failed.\n"); goto done; } template_update_attribute( pub_key_obj->template, new_attr ); if ((rc = object_mgr_create_final(&dummy_sess, pub_key_obj, ckKey))) { TRACE_DEVEL("object_mgr_create_final failed\n"); goto done; } done: return rc; } CK_RV token_update_private_key(TSS_HKEY hKey, int key_type) { CK_OBJECT_HANDLE ckHandle; CK_RV rc; SESSION dummy_sess; /* set up dummy session */ memset(&dummy_sess, 0, sizeof(SESSION)); dummy_sess.session_info.state = CKS_RW_USER_FUNCTIONS; /* find the private key portion of the key */ if ((rc = token_find_key(key_type, CKO_PRIVATE_KEY, &ckHandle))) { TRACE_ERROR("token_find_key failed: 0x%lx\n", rc); return rc; } /* destroy the private key and create a new one */ if ((rc = object_mgr_destroy_object(&dummy_sess, ckHandle))) { TRACE_DEVEL("object_mgr_destroy_object failed: 0x%lx\n", rc); return rc; } if ((rc = token_store_priv_key(hKey, key_type, &ckHandle))) { TRACE_DEVEL("token_store_priv_key failed: 0x%lx\n", rc); } return rc; } CK_RV token_store_tss_key(TSS_HKEY hKey, int key_type, CK_OBJECT_HANDLE *ckKey) { CK_RV rc; /* create a PKCS#11 pub key object for the key */ if ((rc = token_store_pub_key(hKey, key_type, ckKey))) { TRACE_DEVEL("token_store_pub_key failed. rc=0x%lx\n", rc); return rc; } /* create a PKCS#11 private key object for the key */ if ((rc = token_store_priv_key(hKey, key_type, ckKey))) { TRACE_DEVEL("token_store_priv_key failed. rc=0x%lx\n", rc); } return rc; } CK_RV token_generate_leaf_key(int key_type, CK_CHAR_PTR passHash, TSS_HKEY *phKey) { CK_RV rc = CKR_FUNCTION_FAILED; TSS_RESULT result; TSS_HKEY hParentKey; CK_OBJECT_HANDLE *ckKey; TSS_FLAG initFlags = TSS_KEY_MIGRATABLE | TSS_KEY_TYPE_BIND | TSS_KEY_SIZE_2048 | TSS_KEY_AUTHORIZATION; switch (key_type) { case TPMTOK_PUBLIC_LEAF_KEY: hParentKey = hPublicRootKey; ckKey = &ckPublicRootKey; break; case TPMTOK_PRIVATE_LEAF_KEY: hParentKey = hPrivateRootKey; ckKey = &ckPrivateRootKey; break; default: TRACE_ERROR("Unknown key type.\n"); goto done; break; } if ((result = tss_generate_key(initFlags, passHash, hParentKey, phKey))) { TRACE_ERROR("tss_generate_key returned 0x%x\n", result); return result; } if ((rc = token_store_tss_key(*phKey, key_type, ckKey))) { TRACE_DEVEL("token_store_tss_key failed. rc=0x%x\n", result); } done: return rc; } CK_RV token_verify_pin(TSS_HKEY hKey) { TSS_HENCDATA hEncData; UINT32 ulUnboundDataLen; BYTE *rgbUnboundData; char *rgbData = "CRAPPENFEST"; TSS_RESULT result; CK_RV rc = CKR_FUNCTION_FAILED; if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); goto done; } if ((result = Tspi_Data_Bind(hEncData, hKey, strlen(rgbData), (BYTE *)rgbData))) { TRACE_ERROR("Tspi_Data_Bind returned 0x%x\n", result); goto done; } /* unbind the junk data to test the key's auth data */ result = Tspi_Data_Unbind(hEncData, hKey, &ulUnboundDataLen, &rgbUnboundData); if (result == TCPA_E_AUTHFAIL) { rc = CKR_PIN_INCORRECT; TRACE_ERROR("Tspi_Data_Unbind returned TCPA_AUTHFAIL\n"); goto done; } else if (result != TSS_SUCCESS) { TRACE_ERROR("Tspi_Data_ Unbind returned 0x%x\n", result); goto done; } rc = memcmp(rgbUnboundData, rgbData, ulUnboundDataLen); Tspi_Context_FreeMemory(tspContext, rgbUnboundData); done: Tspi_Context_CloseObject(tspContext, hEncData); return rc; } CK_RV token_create_private_tree(CK_BYTE *pinHash, CK_BYTE *pPin) { CK_RV rc; TSS_RESULT result; RSA *rsa; unsigned int size_n, size_p; unsigned char n[256], p[256]; /* all sw generated keys are 2048 bits */ if ((rsa = openssl_gen_key()) == NULL) return CKR_HOST_MEMORY; if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) { TRACE_DEVEL("openssl_get_modulus_and_prime failed\n"); return CKR_FUNCTION_FAILED; } /* generate the software based user base key */ if ((rc = token_wrap_sw_key(size_n, n, size_p, p, hSRK, TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE, &hPrivateRootKey))) { TRACE_DEVEL("token_wrap_sw_key failed. rc=0x%lu\n", rc); return rc; } if (openssl_write_key(rsa, TPMTOK_PRIV_ROOT_KEY_FILE, pPin)) { TRACE_DEVEL("openssl_write_key failed.\n"); RSA_free(rsa); return CKR_FUNCTION_FAILED; } RSA_free(rsa); /* store the user base key in a PKCS#11 object internally */ if ((rc = token_store_tss_key(hPrivateRootKey, TPMTOK_PRIVATE_ROOT_KEY, &ckPrivateRootKey))) { TRACE_DEVEL("token_store_tss_key failed. rc=0x%lx\n", rc); return rc; } if ((result = Tspi_Key_LoadKey(hPrivateRootKey, hSRK))) { TRACE_ERROR("Tspi_Key_LoadKey: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, hPrivateRootKey); hPrivateRootKey = NULL_HKEY; return CKR_FUNCTION_FAILED; } /* generate the private leaf key */ if ((rc = token_generate_leaf_key(TPMTOK_PRIVATE_LEAF_KEY, pinHash, &hPrivateLeafKey))) { TRACE_DEVEL("token_generate_leaf_key failed. rc=0x%lx\n", rc); return rc; } if ((result = Tspi_Key_LoadKey(hPrivateLeafKey, hPrivateRootKey))) { TRACE_ERROR("Tspi_Key_LoadKey: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, hPrivateRootKey); hPrivateRootKey = NULL_HKEY; Tspi_Context_CloseObject(tspContext, hPrivateLeafKey); hPrivateRootKey = NULL_HKEY; return CKR_FUNCTION_FAILED; } return rc; } CK_RV token_create_public_tree(CK_BYTE *pinHash, CK_BYTE *pPin) { CK_RV rc; TSS_RESULT result; RSA *rsa; unsigned int size_n, size_p; unsigned char n[256], p[256]; /* all sw generated keys are 2048 bits */ if ((rsa = openssl_gen_key()) == NULL) return CKR_HOST_MEMORY; if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) { TRACE_DEVEL("openssl_get_modulus_and_prime failed\n"); return CKR_FUNCTION_FAILED; } /* create the public root key */ if ((rc = token_wrap_sw_key(size_n, n, size_p, p, hSRK, TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE, &hPublicRootKey))) { TRACE_DEVEL("token_wrap_sw_key failed. rc=0x%lx\n", rc); return rc; } if (openssl_write_key(rsa, TPMTOK_PUB_ROOT_KEY_FILE, pPin)) { TRACE_DEVEL("openssl_write_key\n"); RSA_free(rsa); return CKR_FUNCTION_FAILED; } RSA_free(rsa); if ((result = Tspi_Key_LoadKey(hPublicRootKey, hSRK))) { TRACE_ERROR("Tspi_Key_LoadKey: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, hPublicRootKey); hPublicRootKey = NULL_HKEY; return CKR_FUNCTION_FAILED; } if ((rc = token_store_tss_key(hPublicRootKey, TPMTOK_PUBLIC_ROOT_KEY, &ckPublicRootKey))) { TRACE_DEVEL("token_store_tss_key failed. rc=0x%lx\n", rc); return rc; } /* create the SO's leaf key */ if ((rc = token_generate_leaf_key(TPMTOK_PUBLIC_LEAF_KEY, pinHash, &hPublicLeafKey))) { TRACE_DEVEL("token_generate_leaf_key failed. rc=0x%lx\n", rc); return rc; } if ((result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey))) { TRACE_ERROR("Tspi_Key_LoadKey: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, hPublicRootKey); hPublicRootKey = NULL_HKEY; Tspi_Context_CloseObject(tspContext, hPublicLeafKey); hPublicLeafKey = NULL_HKEY; return CKR_FUNCTION_FAILED; } return rc; } CK_RV token_migrate(int key_type, CK_BYTE *pin) { RSA *rsa; char *backup_loc; unsigned int size_n, size_p; unsigned char n[256], p[256]; TSS_RESULT result; TSS_HKEY *phKey; CK_RV rc; CK_OBJECT_HANDLE *ckHandle; SESSION dummy_sess; /* set up dummy session */ memset(&dummy_sess, 0, sizeof(SESSION)); dummy_sess.session_info.state = CKS_RW_USER_FUNCTIONS; if (key_type == TPMTOK_PUBLIC_ROOT_KEY) { backup_loc = TPMTOK_PUB_ROOT_KEY_FILE; phKey = &hPublicRootKey; ckHandle = &ckPublicRootKey; } else if (key_type == TPMTOK_PRIVATE_ROOT_KEY) { backup_loc = TPMTOK_PRIV_ROOT_KEY_FILE; phKey = &hPrivateRootKey; ckHandle = &ckPrivateRootKey; } else { TRACE_ERROR("Invalid key type.\n"); return CKR_FUNCTION_FAILED; } /* read the backup key with the old pin */ if ((rc = openssl_read_key(backup_loc, pin, &rsa))) { if (rc == CKR_FILE_NOT_FOUND) rc = CKR_FUNCTION_FAILED; TRACE_DEVEL("openssl_read_key failed\n"); return rc; } /* So, reading the backup openssl key off disk succeeded with the SOs PIN. * We will now try to re-wrap that key with the current SRK */ if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) { TRACE_DEVEL("openssl_get_modulus_and_prime failed\n"); return CKR_FUNCTION_FAILED; } if ((rc = token_wrap_sw_key(size_n, n, size_p, p, hSRK, TSS_KEY_TYPE_STORAGE | TSS_KEY_NO_AUTHORIZATION, phKey))) { TRACE_DEVEL("token_wrap_sw_key failed. rc=0x%lx\n", rc); RSA_free(rsa); return rc; } RSA_free(rsa); if ((result = Tspi_Key_LoadKey(*phKey, hSRK))) { TRACE_ERROR("Tspi_Key_LoadKey: 0x%x\n", result); Tspi_Context_CloseObject(tspContext, *phKey); *phKey = NULL_HKEY; return CKR_FUNCTION_FAILED; } /* Loading succeeded, so we need to get rid of the old PKCS#11 objects * and store them anew. */ if ((rc = token_find_key(key_type, CKO_PUBLIC_KEY, ckHandle))) { TRACE_ERROR("token_find_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = object_mgr_destroy_object(&dummy_sess, *ckHandle))) { TRACE_DEVEL("object_mgr_destroy_object failed: 0x%lx\n", rc); return rc; } if ((rc = token_find_key(key_type, CKO_PRIVATE_KEY, ckHandle))) { TRACE_ERROR("token_find_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = object_mgr_destroy_object(&dummy_sess, *ckHandle))) { TRACE_DEVEL("object_mgr_destroy_object failed: 0x%lx\n", rc); return rc; } if ((rc = token_store_tss_key(*phKey, key_type, ckHandle))) { TRACE_DEVEL("token_store_tss_key failed: 0x%lx\n", rc); return rc; } return CKR_OK; } CK_RV save_masterkey_private() { char fname[PATH_MAX]; struct stat file_stat; int err; FILE *fp = NULL; struct passwd *pw = NULL; TSS_RESULT result; TSS_HENCDATA hEncData; BYTE *encrypted_masterkey; UINT32 encrypted_masterkey_size; if ((pw = getpwuid(getuid())) == NULL) { TRACE_ERROR("getpwuid failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } //fp = fopen("/etc/pkcs11/tpm/MK_PRIVATE", "r"); sprintf((char *)fname,"%s/%s/%s", pk_dir, pw->pw_name, TPMTOK_MASTERKEY_PRIVATE); /* if file exists, assume its been written correctly before */ if ((err = stat(fname, &file_stat)) == 0) { return CKR_OK; } else if (errno != ENOENT) { /* some error other than file doesn't exist */ return CKR_FUNCTION_FAILED; } /* encrypt the private masterkey using the private leaf key */ if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_Data_Bind(hEncData, hPrivateLeafKey, MK_SIZE, master_key_private))) { TRACE_ERROR("Tspi_Data_Bind failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, &encrypted_masterkey_size, &encrypted_masterkey))) { TRACE_ERROR("Tspi_GetAttribData failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if (encrypted_masterkey_size > 256) { Tspi_Context_FreeMemory(tspContext, encrypted_masterkey); return CKR_DATA_LEN_RANGE; } /* write the encrypted key to disk */ if ((fp = fopen((char *)fname, "w")) == NULL) { TRACE_ERROR("Error opening %s for write: %s\n", fname, strerror(errno)); Tspi_Context_FreeMemory(tspContext, encrypted_masterkey); return CKR_FUNCTION_FAILED; } if ((err = fwrite(encrypted_masterkey, encrypted_masterkey_size, 1, fp)) == 0) { TRACE_ERROR("Error writing %s: %s\n", fname, strerror(errno)); Tspi_Context_FreeMemory(tspContext, encrypted_masterkey); fclose(fp); return CKR_FUNCTION_FAILED; } Tspi_Context_FreeMemory(tspContext, encrypted_masterkey); fclose(fp); return CKR_OK; } CK_RV load_masterkey_private() { FILE *fp = NULL; int err; struct stat file_stat; CK_BYTE encrypted_masterkey[256]; char fname[PATH_MAX]; CK_RV rc; struct passwd *pw = NULL; TSS_RESULT result; TSS_HENCDATA hEncData; BYTE *masterkey; UINT32 masterkey_size, encrypted_masterkey_size = 256; if ((pw = getpwuid(getuid())) == NULL) { TRACE_ERROR("getpwuid failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } sprintf((char *)fname,"%s/%s/%s", pk_dir, pw->pw_name, TPMTOK_MASTERKEY_PRIVATE); /* if file exists, check its size */ if ((err = stat(fname, &file_stat)) == 0) { if (file_stat.st_size != 256) { TRACE_ERROR("Private master key has been corrupted\n"); return CKR_FUNCTION_FAILED; } } else if (errno == ENOENT) { TRACE_INFO("Private master key doesn't exist, creating it...\n"); /* create the private master key, then save */ if ((rc = token_specific_rng(master_key_private, MK_SIZE))) { TRACE_DEVEL("token_rng failed. rc=0x%lx\n", rc); return rc; } return save_masterkey_private(); } else { /* some error other than file doesn't exist */ TRACE_ERROR("stat of private masterkey failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } //fp = fopen("/etc/pkcs11/tpm/MK_PUBLIC", "r"); if ((fp = fopen((char *)fname, "r")) == NULL) { TRACE_ERROR("Error opening %s: %s\n", fname, strerror(errno)); return CKR_FUNCTION_FAILED; } if (fread(encrypted_masterkey, encrypted_masterkey_size, 1, fp) == 0) { TRACE_ERROR("Error reading %s: %s\n", fname, strerror(errno)); fclose(fp); return CKR_FUNCTION_FAILED; } fclose(fp); /* decrypt the private masterkey using the private leaf key */ if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_SetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, encrypted_masterkey_size, encrypted_masterkey))) { TRACE_ERROR("Tspi_SetAttribData failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_Data_Unbind(hEncData, hPrivateLeafKey, &masterkey_size, &masterkey))) { TRACE_ERROR("Tspi_Data_Unbind failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if (masterkey_size != MK_SIZE) { TRACE_ERROR("decrypted private master key size is %u, " "should be %u\n", masterkey_size, MK_SIZE); Tspi_Context_FreeMemory(tspContext, masterkey); return CKR_FUNCTION_FAILED; } memcpy(master_key_private, masterkey, MK_SIZE); Tspi_Context_FreeMemory(tspContext, masterkey); return CKR_OK; } CK_RV token_specific_login(SESSION *sess, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rc; CK_BYTE hash_sha[SHA1_HASH_SIZE]; TSS_RESULT result; if ((result = token_load_srk())) { TRACE_DEVEL("token_load_srk failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((rc = compute_sha1(pPin, ulPinLen, hash_sha))) { TRACE_ERROR("compute_sha1 failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if (userType == CKU_USER) { /* If the public root key doesn't exist yet, the SO hasn't init'd the token */ if ((result = token_load_public_root_key())) { TRACE_DEVEL("token_load_public_root_key failed. " "rc=0x%x\n", result); return CKR_USER_PIN_NOT_INITIALIZED; } /* find, load the private root key */ if ((rc = token_find_key(TPMTOK_PRIVATE_ROOT_KEY, CKO_PRIVATE_KEY, &ckPrivateRootKey))) { /* user's key chain not found, this must be the initial login */ if (memcmp(hash_sha, default_user_pin_sha, SHA1_HASH_SIZE)) { TRACE_ERROR("token_find_key failed and PIN != default\n"); return CKR_PIN_INCORRECT; } not_initialized = 1; return CKR_OK; } if ((rc = token_load_key(ckPrivateRootKey, hSRK, NULL, &hPrivateRootKey))) { TRACE_DEVEL("token_load_key failed. rc=0x%lx\n", rc); /* Here, we've found the private root key, but its load failed. * This should only happen in a migration path, where we have * the PKCS#11 key store available, but the SRK is now * different. So, we will try to decrypt the PEM backup file * for the private root key using the given password. If that * succeeds, we will assume that we're in a migration path and * re-wrap the private root key to the new SRK. */ if ((token_migrate(TPMTOK_PRIVATE_ROOT_KEY, pPin))) { TRACE_DEVEL("token_migrate. rc=0x%lx\n", rc); return rc; } /* At this point, the public root key has been successfully read * from backup, re-wrapped to the new SRK, loaded and the PKCS#11 * objects have been updated. Proceed with login as normal. */ } /* find, load the user leaf key */ if ((rc = token_find_key(TPMTOK_PRIVATE_LEAF_KEY, CKO_PRIVATE_KEY, &ckPrivateLeafKey))) { TRACE_ERROR("token_find_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = token_load_key(ckPrivateLeafKey, hPrivateRootKey, hash_sha, &hPrivateLeafKey))) { TRACE_DEVEL("token_load_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = token_verify_pin(hPrivateLeafKey))) { TRACE_DEVEL("token_verify_pin failed. failed. rc=0x%lx\n", rc); return rc; } memcpy(current_user_pin_sha, hash_sha, SHA1_HASH_SIZE); /* load private data encryption key here */ if ((rc = load_masterkey_private())) { TRACE_DEVEL("load_masterkey_private failed. rc=0x%lx\n", rc); Tspi_Key_UnloadKey(hPrivateLeafKey); hPrivateLeafKey = NULL_HKEY; return rc; } rc = load_private_token_objects(); XProcLock(); global_shm->priv_loaded = TRUE; XProcUnLock(); } else { /* SO path -- */ /* find, load the root key */ if ((rc = token_find_key(TPMTOK_PUBLIC_ROOT_KEY, CKO_PRIVATE_KEY, &ckPublicRootKey))) { /* The SO hasn't set her PIN yet, compare the login pin with * the hard-coded value */ if (memcmp(default_so_pin_sha, hash_sha, SHA1_HASH_SIZE)) { TRACE_ERROR("token_find_key failed and PIN != default\n"); return CKR_PIN_INCORRECT; } not_initialized = 1; return CKR_OK; } /* The SO's key hierarchy has previously been created, so load the key * hierarchy and verify the pin using the TPM. */ if ((rc = token_load_key(ckPublicRootKey, hSRK, NULL, &hPublicRootKey))) { TRACE_DEVEL("token_load_key failed. rc=0x%lx\n", rc); /* Here, we've found the public root key, but its load failed. * This should only happen in a migration path, where we have * the PKCS#11 key store available, but the SRK is now * different. So, we will try to decrypt the PEM backup file * for the public root key using the given password. If that * succeeds, we will assume that we're in a migration path and * re-wrap the public root key to the new SRK. */ if ((token_migrate(TPMTOK_PUBLIC_ROOT_KEY, pPin))) { TRACE_DEVEL("token_migrate. rc=0x%lx\n", rc); return rc; } /* At this point, the public root key has been successfully read * from backup, re-wrapped to the new SRK, loaded and the PKCS#11 * objects have been updated. Proceed with login as normal. */ } /* find, load the public leaf key */ if ((rc = token_find_key(TPMTOK_PUBLIC_LEAF_KEY, CKO_PRIVATE_KEY, &ckPublicLeafKey))) { TRACE_ERROR("token_find_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = token_load_key(ckPublicLeafKey, hPublicRootKey, hash_sha, &hPublicLeafKey))) { TRACE_DEVEL("token_load_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = token_verify_pin(hPublicLeafKey))) { TRACE_DEVEL("token_verify_pin failed. rc=0x%lx\n", rc); return rc; } memcpy(current_so_pin_sha, hash_sha, SHA1_HASH_SIZE); } return rc; } CK_RV token_specific_logout() { if (hPrivateLeafKey != NULL_HKEY) { Tspi_Key_UnloadKey(hPrivateLeafKey); hPrivateLeafKey = NULL_HKEY; } else if (hPublicLeafKey != NULL_HKEY) { Tspi_Key_UnloadKey(hPublicLeafKey); hPublicLeafKey = NULL_HKEY; } memset(master_key_private, 0, MK_SIZE); memset(current_so_pin_sha, 0, SHA1_HASH_SIZE); memset(current_user_pin_sha, 0, SHA1_HASH_SIZE); return CKR_OK; } CK_RV token_specific_init_pin(SESSION *sess, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { /* Since the SO must log in before calling C_InitPIN, we will * be able to return CKR_OK automatically here. * This is because the USER key structure is created at the * time of her first login, not at C_InitPIN time. */ return CKR_OK; } CK_RV check_pin_properties(CK_USER_TYPE userType, CK_BYTE *pinHash, CK_ULONG ulPinLen) { /* make sure the new PIN is different */ if (userType == CKU_USER) { if (!memcmp(pinHash, default_user_pin_sha, SHA1_HASH_SIZE)) { TRACE_ERROR("new PIN must not be the default\n"); return CKR_PIN_INVALID; } } else { if (!memcmp(pinHash, default_so_pin_sha, SHA1_HASH_SIZE)) { TRACE_ERROR("new PIN must not be the default\n"); return CKR_PIN_INVALID; } } if (ulPinLen > MAX_PIN_LEN || ulPinLen < MIN_PIN_LEN) { TRACE_ERROR("New PIN is out of size range\n"); return CKR_PIN_LEN_RANGE; } return CKR_OK; } /* use this function call from set_pin only, where a not logged in public * session can provide the user pin which must be verified. This function * assumes that the pin has already been set once, so there's no migration * path option or checking of the default user pin. */ CK_RV verify_user_pin(CK_BYTE *hash_sha) { CK_RV rc; /* find, load the private root key */ if ((rc = token_find_key(TPMTOK_PRIVATE_ROOT_KEY, CKO_PRIVATE_KEY, &ckPrivateRootKey))) { TRACE_ERROR("token_find_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = token_load_key(ckPrivateRootKey, hSRK, NULL, &hPrivateRootKey))) { TRACE_DEVEL("token_load_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } /* find, load the user leaf key */ if ((rc = token_find_key(TPMTOK_PRIVATE_LEAF_KEY, CKO_PRIVATE_KEY, &ckPrivateLeafKey))) { TRACE_DEVEL("token_find_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = token_load_key(ckPrivateLeafKey, hPrivateRootKey, hash_sha, &hPrivateLeafKey))) { TRACE_DEVEL("token_load_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = token_verify_pin(hPrivateLeafKey))) { TRACE_DEVEL("token_verify_pin failed. failed. rc=0x%lx\n", rc); return rc; } return CKR_OK; } CK_RV token_specific_set_pin(SESSION *sess, CK_CHAR_PTR pOldPin, CK_ULONG ulOldPinLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewPinLen) { CK_BYTE oldpin_hash[SHA1_HASH_SIZE], newpin_hash[SHA1_HASH_SIZE]; CK_RV rc; RSA *rsa_root; TSS_RESULT result; if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } if ((rc = compute_sha1(pOldPin, ulOldPinLen, oldpin_hash))) { TRACE_ERROR("compute_sha1 failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = compute_sha1(pNewPin, ulNewPinLen, newpin_hash))) { TRACE_ERROR("compute_sha1 failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((result = token_load_srk())) { TRACE_DEVEL("token_load_srk failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of the user that is * currently logged in, or the CKU_USER PIN if the session is not logged in." * A non R/W session fails with CKR_SESSION_READ_ONLY. */ if (sess->session_info.state == CKS_RW_USER_FUNCTIONS || sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (not_initialized) { if (memcmp(oldpin_hash, default_user_pin_sha, SHA1_HASH_SIZE)) { TRACE_ERROR("old PIN != default for an " "uninitialized user\n"); return CKR_PIN_INCORRECT; } if ((rc = check_pin_properties(CKU_USER, newpin_hash, ulNewPinLen))) { return rc; } if ((rc = token_create_private_tree(newpin_hash, pNewPin))) { TRACE_DEVEL("FAILED creating USER tree.\n"); return CKR_FUNCTION_FAILED; } nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); nv_token_data->token_info.flags |= CKF_USER_PIN_INITIALIZED; return save_token_data(sess->session_info.slotID); } if (sess->session_info.state == CKS_RW_USER_FUNCTIONS) { /* if we're already logged in, just verify the hash */ if (memcmp(current_user_pin_sha, oldpin_hash, SHA1_HASH_SIZE)) { TRACE_ERROR("USER pin incorrect\n"); return CKR_PIN_INCORRECT; } } else { if ((rc = verify_user_pin(oldpin_hash))) { return rc; } } if ((rc = check_pin_properties(CKU_USER, newpin_hash, ulNewPinLen))) { return rc; } /* change the auth on the TSS object */ if ((result = tss_change_auth(hPrivateLeafKey, hPrivateRootKey, newpin_hash))) { TRACE_ERROR("tss_change_auth failed\n"); return CKR_FUNCTION_FAILED; } /* destroy the old PKCS#11 priv key object and create a new one */ if ((rc = token_update_private_key(hPrivateLeafKey, TPMTOK_PRIVATE_LEAF_KEY))) { TRACE_DEVEL("token_update_private_key failed.\n"); return rc; } /* read the backup key with the old pin */ if ((rc = openssl_read_key(TPMTOK_PRIV_ROOT_KEY_FILE, pOldPin, &rsa_root))) { if (rc == CKR_FILE_NOT_FOUND) { /* If the user has moved his backup PEM file off site, allow a * change auth to succeed without updating it. */ return CKR_OK; } TRACE_DEVEL("openssl_read_key failed\n"); return rc; } /* write it out using the new pin */ if ((rc = openssl_write_key(rsa_root, TPMTOK_PRIV_ROOT_KEY_FILE, pNewPin))) { RSA_free(rsa_root); TRACE_DEVEL("openssl_write_key failed\n"); return CKR_FUNCTION_FAILED; } RSA_free(rsa_root); } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (not_initialized) { if (memcmp(default_so_pin_sha, oldpin_hash, SHA1_HASH_SIZE)) { TRACE_ERROR("old PIN != default for an " "uninitialized SO\n"); return CKR_PIN_INCORRECT; } if ((rc = check_pin_properties(CKU_SO, newpin_hash, ulNewPinLen))) { return rc; } if ((rc = token_create_public_tree(newpin_hash, pNewPin))) { TRACE_DEVEL("FAILED creating SO tree.\n"); return CKR_FUNCTION_FAILED; } nv_token_data->token_info.flags &= ~(CKF_SO_PIN_TO_BE_CHANGED); return save_token_data(sess->session_info.slotID); } if (memcmp(current_so_pin_sha, oldpin_hash, SHA1_HASH_SIZE)) { TRACE_ERROR("SO PIN incorrect\n"); return CKR_PIN_INCORRECT; } if ((rc = check_pin_properties(CKU_SO, newpin_hash, ulNewPinLen))) { return rc; } /* change auth on the SO's leaf key */ if ((result = tss_change_auth(hPublicLeafKey, hPublicRootKey, newpin_hash))) { TRACE_ERROR("tss_change_auth failed\n"); return CKR_FUNCTION_FAILED; } if ((rc = token_update_private_key(hPublicLeafKey, TPMTOK_PUBLIC_LEAF_KEY))) { TRACE_DEVEL("token_update_private_key failed.\n"); return rc; } /* change auth on the public root key's openssl backup */ if ((rc = openssl_read_key(TPMTOK_PUB_ROOT_KEY_FILE, pOldPin, &rsa_root))) { if (rc == CKR_FILE_NOT_FOUND) { /* If the user has moved his backup PEM file off site, allow a * change auth to succeed without updating it. */ return CKR_OK; } TRACE_DEVEL("openssl_read_key failed\n"); return rc; } /* write it out using the new pin */ if ((rc = openssl_write_key(rsa_root, TPMTOK_PUB_ROOT_KEY_FILE, pNewPin))) { RSA_free(rsa_root); TRACE_DEVEL("openssl_write_key failed\n"); return CKR_FUNCTION_FAILED; } RSA_free(rsa_root); } else { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; } return rc; } static CK_RV delete_tpm_data() { char *cmd = NULL; struct passwd *pw = NULL; if ((pw = getpwuid(getuid())) == NULL) { TRACE_ERROR("getpwuid failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } // delete the TOK_OBJ data files if (asprintf(&cmd, "%s %s/%s/%s/* > /dev/null 2>&1", DEL_CMD, pk_dir, pw->pw_name, PK_LITE_OBJ_DIR) < 0) { return CKR_HOST_MEMORY; } system(cmd); free(cmd); // delete the OpenSSL backup keys if (asprintf(&cmd, "%s %s/%s/%s > /dev/null 2>&1", DEL_CMD, pk_dir, pw->pw_name, TPMTOK_PUB_ROOT_KEY_FILE) < 0) { return CKR_HOST_MEMORY; } system(cmd); free(cmd); if (asprintf(&cmd, "%s %s/%s/%s > /dev/null 2>&1", DEL_CMD, pk_dir, pw->pw_name, TPMTOK_PRIV_ROOT_KEY_FILE) < 0) { return CKR_HOST_MEMORY; } system(cmd); free(cmd); // delete the masterkey if (asprintf(&cmd, "%s %s/%s/%s > /dev/null 2>&1", DEL_CMD, pk_dir, pw->pw_name, TPMTOK_MASTERKEY_PRIVATE) < 0) { return CKR_HOST_MEMORY; } system(cmd); free(cmd); return CKR_OK; } /* only called at token init time */ CK_RV token_specific_init_token(CK_SLOT_ID sid, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) { CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_RV rc; if ((rc = compute_sha1(pPin, ulPinLen, hash_sha))) { TRACE_ERROR("compute_sha1 failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } /* find, load the migratable root key */ if ((rc = token_find_key(TPMTOK_PUBLIC_ROOT_KEY, CKO_PRIVATE_KEY, &ckPublicRootKey))) { /* The SO hasn't set her PIN yet, compare the login pin with * the hard-coded value */ if (memcmp(default_so_pin_sha, hash_sha, SHA1_HASH_SIZE)) { TRACE_ERROR("token_find_key failed and PIN != default\n"); return CKR_PIN_INCORRECT; } goto done; } if ((rc = token_load_srk())) { TRACE_DEVEL("token_load_srk failed. rc = 0x%lx\n", rc); return CKR_FUNCTION_FAILED; } /* we found the root key, so check by loading the chain */ if ((rc = token_load_key(ckPublicRootKey, hSRK, NULL, &hPublicRootKey))) { TRACE_DEVEL("token_load_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } /* find, load the public leaf key */ if ((rc = token_find_key(TPMTOK_PUBLIC_LEAF_KEY, CKO_PRIVATE_KEY, &ckPublicLeafKey))) { TRACE_ERROR("token_find_key failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } if ((rc = token_load_key(ckPublicLeafKey, hPublicRootKey, hash_sha, &hPublicLeafKey))) { TRACE_DEVEL("token_load_key(MigLeafKey) Failed.\n"); return CKR_FUNCTION_FAILED; } if ((rc = token_verify_pin(hPublicLeafKey))) { TRACE_DEVEL("token_verify_pin failed. rc=0x%lx\n", rc); return rc; } done: // Before we reconstruct all the data, we should delete the // token objects from the filesystem. object_mgr_destroy_token_objects(); rc = delete_tpm_data(); if (rc != CKR_OK) return rc; // META This should be fine since the open session checking should occur at // the API not the STDLL init_token_data(sid); init_slotInfo(); memcpy(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE); nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED; memcpy(nv_token_data->token_info.label, pLabel, 32); // New for v2.11 - KEY nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED; rc = save_token_data(sid); if (rc != CKR_OK) { TRACE_DEVEL("save_token_data failed.\n"); return rc; } return CKR_OK; } CK_RV token_specific_final() { TSS_RESULT result; if ((result = Tspi_Context_Close(tspContext))) { TRACE_ERROR("Tspi_Context_Close failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } return CKR_OK; } CK_RV token_specific_des_key_gen(CK_BYTE *des_key, CK_ULONG len, CK_ULONG keysize) { // Nothing different to do for DES or TDES here as this is just // random data... Validation handles the rest // Only check for weak keys when DES. if (len == (3 * DES_KEY_SIZE)) rng_generate(des_key,len); else { do { rng_generate(des_key, len); } while (des_check_weak_key(des_key) == TRUE); } // we really need to validate the key for parity etc... // we should do that here... The caller validates the single des keys // against the known and suspected poor keys.. return CKR_OK; } CK_RV token_specific_des_ecb(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { CK_ULONG rc; CK_ATTRIBUTE *attr = NULL; DES_key_schedule des_key2; const_DES_cblock key_val_SSL, in_key_data; DES_cblock out_key_data; unsigned int i,j; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); return CKR_FUNCTION_FAILED; } // Create the key schedule memcpy(&key_val_SSL, attr->pValue, 8); DES_set_key_unchecked(&key_val_SSL, &des_key2); // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8 ){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } // Both the encrypt and the decrypt are done 8 bytes at a time if (encrypt) { for (i=0; itemplate, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); return CKR_FUNCTION_FAILED; } // Create the key schedule memcpy(&key_val_SSL, attr->pValue, 8); DES_set_key_unchecked(&key_val_SSL, &des_key2); memcpy(&ivec, init_v, 8); // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8 ){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } if ( encrypt){ DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec, DES_ENCRYPT); *out_data_len = in_data_len; rc = CKR_OK; } else { DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec, DES_DECRYPT); *out_data_len = in_data_len; rc = CKR_OK; } return rc; } CK_RV token_specific_tdes_ecb(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_BYTE key_value[3*DES_KEY_SIZE]; unsigned int k, j; DES_key_schedule des_key1; DES_key_schedule des_key2; DES_key_schedule des_key3; const_DES_cblock key_SSL1, key_SSL2, key_SSL3, in_key_data; DES_cblock out_key_data; // get the key type rc = template_attribute_find(key->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("template_attribute_find(CKA_KEY_TYPE) failed.\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); return CKR_FUNCTION_FAILED; } if (keytype == CKK_DES2) { memcpy(key_value, attr->pValue, 2*DES_KEY_SIZE); memcpy(key_value + (2*DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); } else memcpy(key_value, attr->pValue, 3*DES_KEY_SIZE); // The key as passed is a 24 byte long string containing three des keys // pick them apart and create the 3 corresponding key schedules memcpy(&key_SSL1, key_value, 8); memcpy(&key_SSL2, key_value+8, 8); memcpy(&key_SSL3, key_value+16, 8); DES_set_key_unchecked(&key_SSL1, &des_key1); DES_set_key_unchecked(&key_SSL2, &des_key2); DES_set_key_unchecked(&key_SSL3, &des_key3); // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8 ){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } // the encrypt and decrypt are done 8 bytes at a time if (encrypt) { for(k=0;ktemplate, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("template_attribute_find(CKA_KEY_TYPE) failed.\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); return CKR_FUNCTION_FAILED; } if (keytype == CKK_DES2) { memcpy(key_value, attr->pValue, 2*DES_KEY_SIZE); memcpy(key_value + (2*DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); } else memcpy(key_value, attr->pValue, 3*DES_KEY_SIZE); // The key as passed in is a 24 byte string containing 3 keys // pick it apart and create the key schedules memcpy(&key_SSL1, key_value, 8); memcpy(&key_SSL2, key_value+8, 8); memcpy(&key_SSL3, key_value+16, 8); DES_set_key_unchecked(&key_SSL1, &des_key1); DES_set_key_unchecked(&key_SSL2, &des_key2); DES_set_key_unchecked(&key_SSL3, &des_key3); memcpy(ivec, init_v, sizeof(ivec)); // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8 ){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } // Encrypt or decrypt the data if (encrypt){ DES_ede3_cbc_encrypt(in_data, out_data, in_data_len, &des_key1, &des_key2, &des_key3, &ivec, DES_ENCRYPT); *out_data_len = in_data_len; rc = CKR_OK; }else { DES_ede3_cbc_encrypt(in_data, out_data, in_data_len, &des_key1, &des_key2, &des_key3, &ivec, DES_DECRYPT); *out_data_len = in_data_len; rc = CKR_OK; } return rc; } /* wrap the 20 bytes of auth data @authData and store in an attribute of the two * keys. */ CK_RV token_wrap_auth_data(CK_BYTE *authData, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { CK_RV rc; CK_ATTRIBUTE *new_attr; TSS_HKEY hParentKey; TSS_HENCDATA hEncData; BYTE *blob; UINT32 blob_size; if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) { TRACE_ERROR("Shouldn't be wrapping auth data in a " "public path!\n"); return CKR_FUNCTION_FAILED; } else if (hPublicLeafKey != NULL_HKEY) { hParentKey = hPublicLeafKey; } else { hParentKey = hPrivateLeafKey; } /* create the encrypted data object */ if ((rc = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%lx\n", rc); return rc; } if ((rc = Tspi_Data_Bind(hEncData, hParentKey, SHA1_HASH_SIZE, authData))) { TRACE_ERROR("Tspi_Data_Bind failed. rc=0x%lx\n", rc); return rc; } /* pull the encrypted data out of the encrypted data object */ if ((rc = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, &blob_size, &blob))) { TRACE_ERROR("Tspi_SetAttribData failed. rc=0x%lx\n", rc); return rc; } if ((rc = build_attribute( CKA_ENC_AUTHDATA, blob, blob_size, &new_attr ))) { TRACE_DEVEL("build_attribute failed.\n"); return rc; } template_update_attribute( publ_tmpl, new_attr ); if ((rc = build_attribute( CKA_ENC_AUTHDATA, blob, blob_size, &new_attr ))) { TRACE_DEVEL("build_attribute failed.\n"); return rc; } template_update_attribute( priv_tmpl, new_attr ); return rc; } CK_RV token_unwrap_auth_data(CK_BYTE *encAuthData, CK_ULONG encAuthDataLen, TSS_HKEY hKey, BYTE **authData) { TSS_RESULT result; TSS_HENCDATA hEncData; BYTE *buf; UINT32 buf_size; if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_SetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, encAuthDataLen, encAuthData))) { TRACE_ERROR("Tspi_SetAttribData failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* unbind the data, receiving the plaintext back */ if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) { TRACE_ERROR("Tspi_Data_Unbind failed: rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if (buf_size != SHA1_HASH_SIZE) { TRACE_ERROR("auth data decrypt error.\n"); return CKR_FUNCTION_FAILED; } *authData = buf; return CKR_OK; } // convert from the local PKCS11 template representation to // the underlying requirement // returns the pointer to the local key representation CK_BYTE * rsa_convert_public_key(OBJECT *key_obj) { CK_ATTRIBUTE *modulus = NULL; CK_BYTE *ret; CK_RV rc; rc = template_attribute_find( key_obj->template, CKA_MODULUS, &modulus ); if (rc == FALSE) { return NULL; } ret = malloc(modulus->ulValueLen); if (ret == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return NULL; } memcpy(ret, modulus->pValue, modulus->ulValueLen); return ret; } CK_RV token_specific_rsa_generate_keypair( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_ATTRIBUTE *attr = NULL; CK_ULONG mod_bits = 0; CK_BBOOL flag; CK_RV rc; CK_BYTE tpm_pubexp[3] = { 1, 0, 1 }; // 65537 TSS_FLAG initFlags = 0; BYTE authHash[SHA1_HASH_SIZE]; BYTE *authData = NULL; TSS_HKEY hKey = NULL_HKEY; TSS_HKEY hParentKey = NULL_HKEY; TSS_RESULT result; UINT32 ulBlobLen; BYTE *rgbBlob; /* Make sure the public exponent is usable */ if ((util_check_public_exponent(publ_tmpl))) { TRACE_DEVEL("Invalid public exponent\n"); return CKR_TEMPLATE_INCONSISTENT; } flag = template_attribute_find( publ_tmpl, CKA_MODULUS_BITS, &attr ); if (!flag){ TRACE_ERROR("template_attribute_find(CKA_MODULUS_BITS) failed.\n"); return CKR_TEMPLATE_INCOMPLETE; // should never happen } mod_bits = *(CK_ULONG *)attr->pValue; if ((initFlags = util_get_keysize_flag(mod_bits)) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); return CKR_KEY_SIZE_RANGE; } /* If we're not logged in, hPrivateLeafKey and hPublicLeafKey should be NULL */ if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) { /* public session, wrap key with the PRK */ initFlags |= TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION | TSS_KEY_MIGRATABLE; if ((result = token_load_public_root_key())) { TRACE_DEVEL("token_load_public_root_key failed. " "rc=%x\n", result); return CKR_FUNCTION_FAILED; } hParentKey = hPublicRootKey; } else if (hPrivateLeafKey != NULL_HKEY) { /* logged in USER session */ initFlags |= TSS_KEY_TYPE_LEGACY | TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE; /* get a random SHA1 hash for the auth data */ if ((rc = token_specific_rng(authHash, SHA1_HASH_SIZE))) { TRACE_DEVEL("token_rng failed. rc=%lx\n", rc); return CKR_FUNCTION_FAILED; } authData = authHash; hParentKey = hPrivateRootKey; } else { /* logged in SO session */ initFlags |= TSS_KEY_TYPE_LEGACY | TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE; /* get a random SHA1 hash for the auth data */ if ((rc = token_specific_rng(authHash, SHA1_HASH_SIZE))) { TRACE_DEVEL("token_rng failed. rc=0x%lx\n", rc); return CKR_FUNCTION_FAILED; } authData = authHash; hParentKey = hPublicRootKey; } if ((result = tss_generate_key(initFlags, authData, hParentKey, &hKey))) { TRACE_ERROR("tss_generate_key returned 0x%x\n", result); return result; } if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { TRACE_ERROR("Tspi_GetAttribData failed with rc: 0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, &attr))) { TRACE_DEVEL("build_attribute(CKA_IBM_OPAQUE) failed.\n"); Tspi_Context_FreeMemory(tspContext, rgbBlob); return rc; } template_update_attribute( priv_tmpl, attr ); if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, &attr))) { TRACE_DEVEL("build_attribute(CKA_IBM_OPAQUE) failed.\n"); Tspi_Context_FreeMemory(tspContext, rgbBlob); return rc; } template_update_attribute( publ_tmpl, attr ); Tspi_Context_FreeMemory(tspContext, rgbBlob); /* grab the public key to put into the public key object */ if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &ulBlobLen, &rgbBlob))) { TRACE_ERROR("Tspi_GetAttribData failed with rc: 0x%x\n", result); return result; } /* add the public key blob to the object template */ if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) { TRACE_DEVEL("build_attribute(CKA_MODULUS) failed.\n"); Tspi_Context_FreeMemory(tspContext, rgbBlob); return rc; } template_update_attribute( publ_tmpl, attr ); /* add the public key blob to the object template */ if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) { TRACE_DEVEL("build_attribute(CKA_MODULUS) failed.\n"); Tspi_Context_FreeMemory(tspContext, rgbBlob); return rc; } template_update_attribute( priv_tmpl, attr ); Tspi_Context_FreeMemory(tspContext, rgbBlob); /* put the public exponent into the private key object */ if ((rc = build_attribute(CKA_PUBLIC_EXPONENT, tpm_pubexp, sizeof(tpm_pubexp), &attr))) { TRACE_DEVEL("build_attribute(CKA_PUBLIC_EXPONENT) failed.\n"); return rc; } template_update_attribute( priv_tmpl, attr ); /* wrap the authdata and put it into an object */ if (authData != NULL) { if ((rc = token_wrap_auth_data(authData, publ_tmpl, priv_tmpl))) { TRACE_DEVEL("token_wrap_auth_data failed with rc: 0x%lx\n", rc); } } return rc; } CK_RV token_rsa_load_key( OBJECT * key_obj, TSS_HKEY * phKey ) { TSS_RESULT result; TSS_HPOLICY hPolicy = NULL_HPOLICY; TSS_HKEY hParentKey; BYTE *authData = NULL; CK_ATTRIBUTE *attr; CK_RV rc; CK_OBJECT_HANDLE handle; if (hPrivateLeafKey != NULL_HKEY) { hParentKey = hPrivateRootKey; } else { if ((result = token_load_public_root_key())) { TRACE_DEVEL("token_load_public_root_key failed. " "rc=%x\n", result); return CKR_FUNCTION_FAILED; } hParentKey = hPublicRootKey; } if ((rc = template_attribute_find( key_obj->template, CKA_IBM_OPAQUE, &attr )) == FALSE) { /* if the key blob wasn't found, then try to wrap the key */ rc = object_mgr_find_in_map2(key_obj, &handle); if (rc != CKR_OK) return CKR_FUNCTION_FAILED; if ((rc = token_load_key(handle, hParentKey, NULL, phKey))) { TRACE_DEVEL("token_load_key failed. rc=0x%lx\n", rc); return rc; } /* try again to get the CKA_IBM_OPAQUE attr */ if ((rc = template_attribute_find( key_obj->template, CKA_IBM_OPAQUE, &attr )) == FALSE) { TRACE_ERROR("Could not find key blob\n"); return rc; } } if ((result = Tspi_Context_LoadKeyByBlob(tspContext, hParentKey, attr->ulValueLen, attr->pValue, phKey))) { TRACE_ERROR("Tspi_Context_LoadKeyByBlob failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* auth data may be required */ if (template_attribute_find( key_obj->template, CKA_ENC_AUTHDATA, &attr) == TRUE && attr) { if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) { TRACE_ERROR("Shouldn't be in a public session here\n"); return CKR_FUNCTION_FAILED; } else if (hPublicLeafKey != NULL_HKEY) { hParentKey = hPublicLeafKey; } else { hParentKey = hPrivateLeafKey; } if ((result = token_unwrap_auth_data(attr->pValue, attr->ulValueLen, hParentKey, &authData))) { TRACE_DEVEL("token_unwrap_auth_data: 0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_GetPolicyObject(*phKey, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_GetPolicyObject: 0x%x\n", result); return CKR_FUNCTION_FAILED; } /* If the policy handle returned is the same as the context's default policy, then * a new policy must be created and assigned to the key. Otherwise, just set the * secret in the policy */ if (hPolicy == hDefaultPolicy) { if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { TRACE_ERROR("Tspi_Context_CreateObject: 0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, SHA1_HASH_SIZE, authData))) { TRACE_ERROR("Tspi_Policy_SetSecret failed. " "rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_Policy_AssignToObject(hPolicy, *phKey))) { TRACE_ERROR("Tspi_Policy_AssignToObject failed." " rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } } else if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, SHA1_HASH_SIZE, authData))) { TRACE_ERROR("Tspi_Policy_SetSecret failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } Tspi_Context_FreeMemory(tspContext, authData); } return CKR_OK; } CK_RV token_specific_rsa_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj ) { CK_RV rc; TSS_RESULT result; TSS_HKEY hKey; TSS_HENCDATA hEncData = NULL_HENCDATA; UINT32 buf_size = 0; BYTE *buf = NULL; if ((rc = token_rsa_load_key(key_obj, &hKey))) { TRACE_DEVEL("token_rsa_load_key failed. rc=0x%lx\n", rc); return rc; } /* push the data into the encrypted data object */ if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_SetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, in_data_len, in_data))) { TRACE_ERROR("Tspi_SetAttribData failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* unbind the data, receiving the plaintext back */ TRACE_DEVEL("unbinding data with size: %ld\n", in_data_len); if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) { TRACE_ERROR("Tspi_Data_Unbind failed: 0x%x\n", result); return CKR_FUNCTION_FAILED; } if (*out_data_len < buf_size) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); Tspi_Context_FreeMemory(tspContext, buf); return CKR_BUFFER_TOO_SMALL; } memcpy(out_data, buf, buf_size); *out_data_len = buf_size; Tspi_Context_FreeMemory(tspContext, buf); return CKR_OK; } CK_RV token_specific_rsa_verify( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * sig, CK_ULONG sig_len, OBJECT * key_obj ) { TSS_RESULT result; TSS_HHASH hHash; TSS_HKEY hKey; CK_RV rc; if ((rc = token_rsa_load_key(key_obj, &hKey))) { TRACE_DEVEL("token_rsa_load_key failed. rc=0x%lx\n", rc); return rc; } /* Create the hash object we'll use to sign */ if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* Insert the data into the hash object */ if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len, in_data))) { TRACE_ERROR("Tspi_Hash_SetHashValue failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* Verify */ result = Tspi_Hash_VerifySignature(hHash, hKey, sig_len, sig); if (result != TSS_SUCCESS && TPMTOK_TSS_ERROR_CODE(result) != TSS_E_FAIL) { TRACE_ERROR("Tspi_Hash_VerifySignature failed. rc=0x%x\n", result); } if (TPMTOK_TSS_ERROR_CODE(result) == TSS_E_FAIL) { rc = CKR_SIGNATURE_INVALID; } else { rc = CKR_OK; } return rc; } CK_RV token_specific_rsa_sign( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj ) { TSS_RESULT result; TSS_HHASH hHash; BYTE *sig; UINT32 sig_len; TSS_HKEY hKey; CK_RV rc; if ((rc = token_rsa_load_key(key_obj, &hKey))) { TRACE_DEVEL("token_rsa_load_key failed. rc=0x%lx\n", rc); return rc; } /* Create the hash object we'll use to sign */ if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* Insert the data into the hash object */ if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len, in_data))) { TRACE_ERROR("Tspi_Hash_SetHashValue failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } /* Sign */ if ((result = Tspi_Hash_Sign(hHash, hKey, &sig_len, &sig))) { TRACE_ERROR("Tspi_Hash_Sign failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if (sig_len > *out_data_len) { TRACE_ERROR("Buffer too small to hold result.\n"); Tspi_Context_FreeMemory(tspContext, sig); return CKR_BUFFER_TOO_SMALL; } memcpy(out_data, sig, sig_len); *out_data_len = sig_len; Tspi_Context_FreeMemory(tspContext, sig); return CKR_OK; } CK_RV token_specific_rsa_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj ) { TSS_RESULT result; TSS_HENCDATA hEncData; BYTE *dataBlob; UINT32 dataBlobSize; TSS_HKEY hKey; CK_RV rc; if ((rc = token_rsa_load_key(key_obj, &hKey))) { TRACE_DEVEL("token_rsa_load_key failed. rc=0x%lx\n", rc); return rc; } if ((result = Tspi_Context_CreateObject(tspContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { TRACE_ERROR("Tspi_Context_CreateObject failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_Data_Bind(hEncData, hKey, in_data_len, in_data))) { TRACE_ERROR("Tspi_Data_Bind failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if ((result = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, &dataBlobSize, &dataBlob))) { TRACE_ERROR("Tspi_SetAttribData failed. rc=0x%x\n", result); return CKR_FUNCTION_FAILED; } if (dataBlobSize > *out_data_len) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); Tspi_Context_FreeMemory(tspContext, dataBlob); return CKR_DATA_LEN_RANGE; } memcpy(out_data, dataBlob, dataBlobSize); *out_data_len = dataBlobSize; Tspi_Context_FreeMemory(tspContext, dataBlob); return CKR_OK; } CK_RV token_specific_rsa_verify_recover(CK_BYTE *signature, CK_ULONG sig_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; rc = token_specific_rsa_encrypt(signature, sig_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_DEVEL("token specific rsa_encrypt failed.\n"); return rc; } CK_RV token_specific_aes_key_gen(CK_BYTE *key, CK_ULONG len, CK_ULONG keysize) { return token_specific_rng(key, len); } CK_RV token_specific_aes_ecb( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { CK_ATTRIBUTE *attr = NULL; AES_KEY ssl_aes_key; unsigned int i; /* There's a previous check that in_data_len % AES_BLOCK_SIZE == 0, * so this is fine */ CK_ULONG loops = (CK_ULONG)(in_data_len/AES_BLOCK_SIZE); // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); return CKR_FUNCTION_FAILED; } memset( &ssl_aes_key, 0, sizeof(AES_KEY)); // AES_ecb_encrypt encrypts only a single block, so we have to break up the // input data here if (encrypt) { AES_set_encrypt_key((unsigned char *)attr->pValue, (attr->ulValueLen*8), &ssl_aes_key); for( i=0; ipValue, (attr->ulValueLen*8), &ssl_aes_key); for( i=0; itemplate, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("template_attribute_find(CKA_VALUE) failed.\n"); return CKR_FUNCTION_FAILED; } memset( &ssl_aes_key, 0, sizeof(AES_KEY)); // AES_cbc_encrypt chunks the data into AES_BLOCK_SIZE blocks, unlike // AES_ecb_encrypt, so no looping required. if (encrypt) { AES_set_encrypt_key((unsigned char *)attr->pValue, (attr->ulValueLen*8), &ssl_aes_key); AES_cbc_encrypt((unsigned char *)in_data, (unsigned char *)out_data, in_data_len, &ssl_aes_key, init_v, AES_ENCRYPT); } else { AES_set_decrypt_key((unsigned char *)attr->pValue, (attr->ulValueLen*8), &ssl_aes_key); AES_cbc_encrypt((unsigned char *)in_data, (unsigned char *)out_data, in_data_len, &ssl_aes_key, init_v, AES_DECRYPT); } *out_data_len = in_data_len; return CKR_OK; } #ifndef NODH /* Begin code contributed by Corrent corp. */ // This computes DH shared secret, where: // Output: z is computed shared secret // Input: y is other party's public key // x is private key // p is prime // All length's are in number of bytes. All data comes in as Big Endian. CK_RV token_specific_dh_pkcs_derive( CK_BYTE *z, CK_ULONG *z_len, CK_BYTE *y, CK_ULONG y_len, CK_BYTE *x, CK_ULONG x_len, CK_BYTE *p, CK_ULONG p_len) { CK_RV rc ; BIGNUM *bn_z, *bn_y, *bn_x, *bn_p ; BN_CTX *ctx; // Create and Init the BIGNUM structures. bn_y = BN_new() ; bn_x = BN_new() ; bn_p = BN_new() ; bn_z = BN_new() ; if (bn_z == NULL || bn_p == NULL || bn_x == NULL || bn_y == NULL) { if (bn_y) BN_free(bn_y); if (bn_x) BN_free(bn_x); if (bn_p) BN_free(bn_p); if (bn_z) BN_free(bn_z); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } BN_init(bn_y) ; BN_init(bn_x) ; BN_init(bn_p) ; // Initialize context ctx=BN_CTX_new(); if (ctx == NULL) { TRACE_ERROR("BN_CTX_new failed to create a new context\n"); return CKR_FUNCTION_FAILED; } // Add data into these new BN structures BN_bin2bn((char *)y, y_len, bn_y); BN_bin2bn((char *)x, x_len, bn_x); BN_bin2bn((char *)p, p_len, bn_p); rc = BN_mod_exp(bn_z,bn_y,bn_x,bn_p,ctx); if (rc == 0) { BN_free(bn_z); BN_free(bn_y); BN_free(bn_x); BN_free(bn_p); BN_CTX_free(ctx); TRACE_ERROR("BN_mod_exp failed.\n"); return CKR_FUNCTION_FAILED; } *z_len = BN_num_bytes(bn_z); BN_bn2bin(bn_z, z); BN_free(bn_z); BN_free(bn_y); BN_free(bn_x); BN_free(bn_p); BN_CTX_free(ctx); return CKR_OK; } /* end token_specific_dh_pkcs_derive() */ // This computes DH key pair, where: // Output: priv_tmpl is generated private key // pub_tmpl is computed public key // Input: pub_tmpl is public key (prime and generator) // All length's are in number of bytes. All data comes in as Big Endian. CK_RV token_specific_dh_pkcs_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_BBOOL rc; CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *temp_attr = NULL ; CK_ATTRIBUTE *value_bits_attr = NULL; CK_BYTE *temp_byte; CK_ULONG temp_bn_len ; DH *dh ; BIGNUM *bn_p ; BIGNUM *bn_g ; BIGNUM *temp_bn ; rc = template_attribute_find( publ_tmpl, CKA_PRIME, &prime_attr ); if (rc == FALSE) { TRACE_ERROR("template_attribute_find(CKA_PRIME) failed.\n"); return CKR_FUNCTION_FAILED; } rc = template_attribute_find( publ_tmpl, CKA_BASE, &base_attr ); if (rc == FALSE) { TRACE_ERROR("template_attribute_find(CKA_BASE) failed.\n"); return CKR_FUNCTION_FAILED; } if ((prime_attr->ulValueLen > 256) || (prime_attr->ulValueLen < 64)) { TRACE_ERROR("CKA_PRIME is not between 64 and 256 bits.\n"); return CKR_ATTRIBUTE_VALUE_INVALID; } dh = DH_new() ; if (dh == NULL) { TRACE_ERROR("DH_new failed.\n"); return CKR_FUNCTION_FAILED; } // Create and init BIGNUM structs to stick in the DH struct bn_p = BN_new(); bn_g = BN_new(); if (bn_g == NULL || bn_p == NULL) { if (bn_g) BN_free(bn_g); if (bn_p) BN_free(bn_p); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } BN_init(bn_p); BN_init(bn_g); // Convert from strings to BIGNUMs and stick them in the DH struct BN_bin2bn((char *)prime_attr->pValue, prime_attr->ulValueLen, bn_p); dh->p = bn_p; BN_bin2bn((char *)base_attr->pValue, base_attr->ulValueLen, bn_g); dh->g = bn_g; // Generate the DH Key if (!DH_generate_key(dh)) { TRACE_ERROR("DH_generate_key failed.\n"); return CKR_FUNCTION_FAILED; } // Extract the public and private key components from the DH struct, // and insert them in the publ_tmpl and priv_tmpl // // pub_key // //temp_bn = BN_new(); temp_bn = dh->pub_key; temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte); rc = build_attribute( CKA_VALUE, temp_byte, temp_bn_len, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute(CKA_VALUE) failed.\n"); return CKR_FUNCTION_FAILED; } template_update_attribute( publ_tmpl, temp_attr ); free(temp_byte); // // priv_key // //temp_bn = BN_new(); temp_bn = dh->priv_key; temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte); rc = build_attribute( CKA_VALUE, temp_byte, temp_bn_len, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute(CKA_VALUE) failed.\n"); return CKR_FUNCTION_FAILED; } template_update_attribute( priv_tmpl, temp_attr ); free(temp_byte); // Update CKA_VALUE_BITS attribute in the private key value_bits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); value_bits_attr->type = CKA_VALUE_BITS; value_bits_attr->ulValueLen = sizeof(CK_ULONG); value_bits_attr->pValue = (CK_BYTE *)value_bits_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_bits_attr->pValue = 8*temp_bn_len; template_update_attribute( priv_tmpl, value_bits_attr ); // Add prime and base to the private key template rc = build_attribute( CKA_PRIME,(char *)prime_attr->pValue, prime_attr->ulValueLen, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute(CKA_PRIME) failed.\n"); return CKR_FUNCTION_FAILED; } template_update_attribute( priv_tmpl, temp_attr ); rc = build_attribute( CKA_BASE,(char *)base_attr->pValue, base_attr->ulValueLen, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute(CKA_PRIME) failed.\n"); return CKR_FUNCTION_FAILED; } template_update_attribute( priv_tmpl, temp_attr ); // Cleanup DH key DH_free(dh) ; return CKR_OK ; } #endif CK_RV token_specific_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { int rc; /* common/mech_list.c */ rc = ock_generic_get_mechanism_list(pMechanismList, pulCount); return rc; } CK_RV token_specific_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { int rc; /* common/mech_list.c */ rc = ock_generic_get_mechanism_info(type, pInfo); return rc; } int token_specific_creatlock(void) { CK_BYTE lockfile[PATH_MAX]; struct passwd *pw = NULL; struct stat statbuf; mode_t mode = (S_IRUSR|S_IWUSR|S_IXUSR); int lockfd; /* get userid */ if ((pw = getpwuid(getuid())) == NULL) { OCK_SYSLOG(LOG_ERR, "getpwuid(): %s\n",strerror(errno)); return -1; } /* create user-specific directory */ sprintf(lockfile, "%s/%s/%s", LOCKDIR_PATH, SUB_DIR, pw->pw_name); /* see if it exists, otherwise mkdir will fail */ if (stat(lockfile, &statbuf) < 0) { if (mkdir(lockfile, mode) == -1) { OCK_SYSLOG(LOG_ERR, "mkdir(%s): %s\n", lockfile, strerror(errno)); return -1; } /* ensure correct perms on user dir */ if (chmod(lockfile, mode) == -1) { OCK_SYSLOG(LOG_ERR, "chmod(%s): %s\n", lockfile, strerror(errno)); return -1; } } /* create user lock file */ memset(lockfile, 0, PATH_MAX); sprintf(lockfile, "%s/%s/%s/LCK..%s", LOCKDIR_PATH, SUB_DIR, pw->pw_name, SUB_DIR); lockfd = open(lockfile, O_CREAT|O_RDWR, mode); if (lockfd == -1) { OCK_SYSLOG(LOG_ERR, "open(%s): %s\n", lockfile,strerror(errno)); return -1; } else { /* umask may prevent correct mode, so set it. */ if (fchmod(lockfd, mode) == -1) { OCK_SYSLOG(LOG_ERR, "fchmod(%s): %s\n", lockfile, strerror(errno)); goto err; } } return lockfd; err: if (lockfd != -1) close(lockfd); return -1; } CK_RV token_specific_init_token_data(CK_SLOT_ID slot_id) { /* do nothing. */ return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/tpm_stdll/tok_struct.h0000644000175000017500000000712512630407154022341 0ustar xnoxxnox/* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 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 * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ #include "tpm_specific.h" #ifndef TPM_CONFIG_PATH #ifndef CONFIG_PATH #warning CONFIG_PATH not set, using default (/usr/local/var/lib/opencryptoki) #define CONFIG_PATH "/usr/local/var/lib/opencryptoki" #endif // #ifndef CONFIG_PATH #define TPM_CONFIG_PATH CONFIG_PATH "/tpm" #endif // #ifndef TPM_CONFIG_PATH struct token_specific_struct token_specific = { TPM_CONFIG_PATH, "tpm", 0, // Token data info: { TRUE, // Use per guest data store TRUE, // Use master key CKM_AES_CBC, // Data store encryption NULL, // Default initialization vector for pins ")#%&!*)^!()$&!&N", // Default initialization vector for objects }, token_specific_creatlock, NULL, // attach_shm &token_specific_init, &token_specific_init_token_data, NULL, // load_token_data NULL, // save_token_data &token_specific_rng, &token_specific_final, &token_specific_init_token, &token_specific_login, &token_specific_logout, &token_specific_init_pin, &token_specific_set_pin, // DES &token_specific_des_key_gen, &token_specific_des_ecb, &token_specific_des_cbc, // Triple DES &token_specific_tdes_ecb, &token_specific_tdes_cbc, NULL, // tdes_ofb NULL, // tdes_cfb NULL, // tdes_mac // RSA &token_specific_rsa_decrypt, &token_specific_rsa_encrypt, &token_specific_rsa_sign, &token_specific_rsa_verify, &token_specific_rsa_verify_recover, NULL, // rsa_x509_decrypt NULL, // rsa_x509_encrypt NULL, // rsa_x509_sign NULL, // rsa_x509_verify NULL, // rsa_x509_verify_recover NULL, // rsa_oaep_decrypt NULL, // rsa_oaep_encrypt NULL, // rsa_pss_sign NULL, // rsa_pss_verify &token_specific_rsa_generate_keypair, // Elliptic Curve NULL, // ec_sign NULL, // ec_verify NULL, // ec_generate_keypair #ifndef NODH &token_specific_dh_pkcs_derive, &token_specific_dh_pkcs_key_pair_gen, #else NULL, NULL, #endif // SHA NULL, // sha_init NULL, // sha NULL, // sha_update NULL, // sha_final // HMAC NULL, // hmac_sign_init NULL, // hmac_sign NULL, // hmac_sign_update NULL, // hmac_sign_final NULL, // hmac_verify_init NULL, // hmac_verify NULL, // hmac_verify_update NULL, // hmac_verify_final NULL, // generic_secret_key_gen // AES &token_specific_aes_key_gen, &token_specific_aes_ecb, &token_specific_aes_cbc, NULL, // aes_ctr NULL, // aes_gcm_init NULL, // aes_gcm NULL, // aes_gcm_update NULL, // aes_gcm_final NULL, // aes_ofb NULL, // aes_cfb NULL, // aes_mac // DSA NULL, // dsa_generate_keypair NULL, // dsa_sign NULL, // dsa_verify &token_specific_get_mechanism_list, &token_specific_get_mechanism_info, NULL // object_add }; opencryptoki+dfsg/usr/lib/pkcs11/tpm_stdll/Makefile.am0000644000175000017500000000525512630407154022025 0ustar xnoxxnox# Makefile.am for common functions for openCryptoki # Michael A. Halcrow nobase_lib_LTLIBRARIES=opencryptoki/stdll/libpkcs11_tpm.la AUTOMAKE_OPTIONS = gnu #VPATH = ../common # TODO: -DLINUX should be controlled via configure.in # Not all versions of automake observe libname_CFLAGS opencryptoki_stdll_libpkcs11_tpm_la_CFLAGS = -DLINUX -DNOCDMF \ -DNODSA -DNODH \ -I. -I../../../include \ -I../../../include/pkcs11 \ -I../common -DMMAP \ -DSTDLL_NAME=\"tpmtok\" opencryptoki_stdll_libpkcs11_tpm_la_LDFLAGS = -shared -Wl,-Bsymbolic \ -lcrypto -ltspi -lpthread \ -lrt opencryptoki_stdll_libpkcs11_tpm_la_SOURCES = ../common/asn1.c \ ../common/btree.c \ ../common/dig_mgr.c \ ../common/hwf_obj.c \ ../common/trace.c \ ../common/key.c \ ../common/mech_dh.c \ ../common/mech_rng.c \ ../common/new_host.c \ ../common/sign_mgr.c \ ../common/cert.c \ ../common/dp_obj.c \ ../common/mech_aes.c \ ../common/$(MECH_DSA) \ ../common/mech_rsa.c \ ../common/mech_ec.c \ ../common/obj_mgr.c \ ../common/template.c \ ../common/p11util.c \ ../common/data_obj.c \ ../common/encr_mgr.c \ ../common/key_mgr.c \ ../common/mech_md2.c \ ../common/mech_sha.c \ ../common/object.c \ ../common/decr_mgr.c \ ../common/globals.c \ ../common/sw_crypt.c \ ../common/loadsave.c \ ../common/utility.c \ ../common/mech_des.c \ ../common/mech_des3.c \ ../common/mech_md5.c \ ../common/mech_ssl3.c \ ../common/sess_mgr.c \ ../common/verify_mgr.c \ ../common/mech_list.c \ ../common/shared_memory.c \ tpm_specific.c \ tpm_openssl.c \ tpm_util.c noinst_HEADERS = defs.h \ tpm_specific.h install-data-hook: $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/opencryptoki/tpm cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ ln -sf libpkcs11_tpm.so PKCS11_TPM.so $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/opencryptoki/tpm $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/tpm $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/tpm $(MKDIR_P) $(DESTDIR)$(lockdir)/tpm $(CHGRP) pkcs11 $(DESTDIR)$(lockdir)/tpm $(CHMOD) 0770 $(DESTDIR)$(lockdir)/tpm uninstall-hook: if test -d $(DESTDIR)$(libdir)/opencryptoki/stdll; then \ cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ rm -rf PKCS11_TPM.so; fi opencryptoki+dfsg/usr/lib/pkcs11/tpm_stdll/tpm_specific.h0000644000175000017500000000661312630407154022606 0ustar xnoxxnox/* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 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 * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ #ifndef _TPM_SPECIFIC_H_ #define _TPM_SPECIFIC_H_ #include /* TSS key type helper */ #define TPMTOK_TSS_KEY_TYPE_MASK 0x000000F0 #define TPMTOK_TSS_KEY_TYPE(x) (x & TPMTOK_TSS_KEY_TYPE_MASK) #define TPMTOK_TSS_KEY_MIG_TYPE(x) (x & TSS_KEY_MIGRATABLE) #define TPMTOK_TSS_MAX_ERROR 0x00000FFF #define TPMTOK_TSS_ERROR_CODE(x) (x & TPMTOK_TSS_MAX_ERROR) /* key types in the TPM token */ #define TPMTOK_PRIVATE_ROOT_KEY 1 #define TPMTOK_PRIVATE_LEAF_KEY 2 #define TPMTOK_PUBLIC_ROOT_KEY 3 #define TPMTOK_PUBLIC_LEAF_KEY 4 /* key identifiers for the PKCS#11 objects */ #define TPMTOK_PRIVATE_ROOT_KEY_ID "PRIVATE ROOT KEY" #define TPMTOK_PRIVATE_LEAF_KEY_ID "PRIVATE LEAF KEY" #define TPMTOK_PUBLIC_ROOT_KEY_ID "PUBLIC ROOT KEY" #define TPMTOK_PUBLIC_LEAF_KEY_ID "PUBLIC LEAF KEY" #define TPMTOK_PRIVATE_ROOT_KEY_ID_SIZE strlen(TPMTOK_PRIVATE_ROOT_KEY_ID) #define TPMTOK_PRIVATE_LEAF_KEY_ID_SIZE strlen(TPMTOK_PRIVATE_LEAF_KEY_ID) #define TPMTOK_PUBLIC_ROOT_KEY_ID_SIZE strlen(TPMTOK_PUBLIC_ROOT_KEY_ID) #define TPMTOK_PUBLIC_LEAF_KEY_ID_SIZE strlen(TPMTOK_PUBLIC_LEAF_KEY_ID) #define TPMTOK_PUB_ROOT_KEY_FILE "PUBLIC_ROOT_KEY.pem" #define TPMTOK_PRIV_ROOT_KEY_FILE "PRIVATE_ROOT_KEY.pem" /* TPM token specific return codes */ #define CKR_KEY_NOT_FOUND CKR_VENDOR_DEFINED + 0x0f000000 #define CKR_FILE_NOT_FOUND CKR_VENDOR_DEFINED + 0x0f000001 #define TPMTOK_MASTERKEY_PRIVATE "MK_PRIVATE" #ifdef DEBUG #define DEBUG_openssl_print_errors() openssl_print_errors() #else #define DEBUG_openssl_print_errors() #endif /* retry count for generating software RSA keys */ #define KEYGEN_RETRY 5 RSA *openssl_gen_key(); int openssl_write_key(RSA *, char *, CK_BYTE *); CK_RV openssl_read_key(char *, CK_BYTE *, RSA **); int openssl_get_modulus_and_prime(RSA *, unsigned int *, unsigned char *, unsigned int *, unsigned char *); int util_set_file_mode(char *, mode_t); CK_BYTE *util_create_id(int); CK_RV util_set_username(char **); unsigned int util_get_keysize_flag(CK_ULONG); CK_ULONG util_check_public_exponent(TEMPLATE *); #define NULL_HKEY 0 #define NULL_HENCDATA 0 #define NULL_HPOLICY 0 #define NULL_HCONTEXT 0 #define NULL_HPCRS 0 /* CKA_ENC_AUTHDATA will be used to store the encrypted SHA-1 hashes of auth data * passed in for TPM keys. The authdata will be encrypted using either the public * leaf key or the private leaf key */ #define CKA_ENC_AUTHDATA CKA_VENDOR_DEFINED + 0x01000001 #define MK_SIZE (AES_KEY_SIZE_256) struct srk_info { char *secret; int mode; int len; }; int get_srk_info(struct srk_info *srk); #endif opencryptoki+dfsg/usr/lib/pkcs11/tpm_stdll/tpm_openssl.c0000644000175000017500000001116512630407154022475 0ustar xnoxxnox /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 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 * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11/pkcs11types.h" #include "pkcs11/stdll.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_specific.h" #include "tok_spec_struct.h" #include "trace.h" #include "tpm_specific.h" #ifdef DEBUG void openssl_print_errors() { ERR_load_ERR_strings(); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); } #endif RSA * openssl_gen_key() { RSA *rsa; int rc, counter = 0; char buf[32]; token_specific_rng((CK_BYTE *)buf, 32); RAND_seed(buf, 32); regen_rsa_key: rsa = RSA_generate_key(2048, 65537, NULL, NULL); if (rsa == NULL) { fprintf(stderr, "Error generating user's RSA key\n"); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); return NULL; } rc = RSA_check_key(rsa); switch (rc) { case 0: /* rsa is not a valid RSA key */ RSA_free(rsa); counter++; if (counter == KEYGEN_RETRY) { TRACE_DEVEL("Tried %d times to generate a " "valid RSA key, failed.\n", KEYGEN_RETRY); return NULL; } goto regen_rsa_key; break; case 1: /* success case, rsa is a valid key */ break; case -1: /* fall through */ default: DEBUG_openssl_print_errors(); break; } return rsa; } int openssl_write_key(RSA *rsa, char *filename, CK_BYTE *pPin) { BIO *b = NULL; char loc[PATH_MAX]; struct passwd *pw = NULL; errno = 0; if ((pw = getpwuid(getuid())) == NULL) { TRACE_ERROR("Error getting username: %s\n", strerror(errno)); return -1; } sprintf(loc, "%s/%s/%s", pk_dir, pw->pw_name, filename); b = BIO_new_file(loc, "w"); if (!b) { TRACE_ERROR("Error opening file for write: %s\n", loc); return -1; } if (!PEM_write_bio_RSAPrivateKey(b, rsa, EVP_aes_256_cbc(), NULL, 0, 0, pPin)) { BIO_free(b); TRACE_ERROR("Writing key %s to disk failed.\n", loc); DEBUG_openssl_print_errors(); return -1; } BIO_free(b); if (util_set_file_mode(loc, (S_IRUSR|S_IWUSR))) { TRACE_ERROR("Setting file mode of %s failed\n", loc); } return 0; } CK_RV openssl_read_key(char *filename, CK_BYTE *pPin, RSA **ret) { BIO *b = NULL; RSA *rsa = NULL; char loc[PATH_MAX]; struct passwd *pw = NULL; CK_RV rc = CKR_FUNCTION_FAILED; errno = 0; if ((pw = getpwuid(getuid())) == NULL) { TRACE_ERROR("Error getting username: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } sprintf(loc, "%s/%s/%s", pk_dir, pw->pw_name, filename); /* we can't allow a pin of NULL here, since openssl will try to prompt * for a password in PEM_read_bio_RSAPrivateKey */ if (pPin == NULL) return CKR_PIN_INCORRECT; b = BIO_new_file(loc, "r+"); if (b == NULL) { TRACE_ERROR("Error opening file for read: %s\n", loc); return CKR_FILE_NOT_FOUND; } if ((rsa = PEM_read_bio_RSAPrivateKey(b, NULL, 0, pPin)) == NULL) { TRACE_ERROR("Reading key %s from disk failed.\n", loc); DEBUG_openssl_print_errors(); if (ERR_GET_REASON(ERR_get_error()) == PEM_R_BAD_DECRYPT) { rc = CKR_PIN_INCORRECT; } BIO_free(b); return rc; } BIO_free(b); *ret = rsa; return CKR_OK; } int openssl_get_modulus_and_prime(RSA *rsa, unsigned int *size_n, unsigned char *n, unsigned int *size_p, unsigned char *p) { /* get the modulus from the RSA object */ if ((*size_n = BN_bn2bin(rsa->n, n)) <= 0) { DEBUG_openssl_print_errors(); return -1; } /* get one of the primes from the RSA object */ if ((*size_p = BN_bn2bin(rsa->p, p)) <= 0) { DEBUG_openssl_print_errors(); return -1; } return 0; } opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/0000755000175000017500000000000012630407154020106 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/icsf_specific.c0000644000175000017500000036225012630407154023053 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * openCryptoki ICSF token * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2006, 2012 * * Author: Marcelo Cerri (mhcerri@br.ibm.com) * * Based on CCC token. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "pbkdf.h" #include "h_extern.h" #include "tok_specific.h" #include "tok_struct.h" #include "icsf_config.h" #include "pbkdf.h" #include "list.h" #include "attributes.h" #include "../api/apiproto.h" #include "trace.h" #include "shared_memory.h" /* Default token attributes */ CK_CHAR manuf[] = "IBM Corp."; CK_CHAR model[] = "IBM ICSFTok "; CK_CHAR descr[] = "IBM PKCS#11 ICSF token"; CK_CHAR label[] = "IBM OS PKCS#11 "; /* mechanisms provided by this token */ MECH_LIST_ELEMENT mech_list[] = { {CKM_DES_KEY_GEN, {8, 8, CKF_HW|CKF_GENERATE}}, {CKM_DES_ECB, {0, 0, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {CKM_DES_CBC, {0, 0, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {CKM_DES_CBC_PAD, {0, 0, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_DES3_ECB, {0, 0, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {CKM_DES3_CBC, {0, 0, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {CKM_DES3_CBC_PAD, {0, 0, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_DES3_KEY_GEN, {24, 24, CKF_HW|CKF_GENERATE}}, {CKM_DES2_KEY_GEN, {24, 24, CKF_HW|CKF_GENERATE}}, {CKM_RSA_PKCS_KEY_PAIR_GEN, {512, 4096, CKF_HW|CKF_GENERATE_KEY_PAIR}}, {CKM_RSA_PKCS, {512, 4096, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP|CKF_SIGN|CKF_VERIFY|CKF_SIGN_RECOVER| CKF_VERIFY_RECOVER}}, {CKM_RSA_X_509, {512, 4096, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_SIGN| CKF_VERIFY|CKF_SIGN_RECOVER|CKF_VERIFY_RECOVER}}, {CKM_MD5_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA1_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA256_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA384_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA512_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA_1, {0, 0, CKF_HW|CKF_DIGEST}}, {CKM_SHA_1_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA256_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA384_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_SHA512_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_MD5, {0, 0, CKF_DIGEST}}, {CKM_MD5_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_AES_KEY_GEN, {16, 32, CKF_HW|CKF_GENERATE}}, {CKM_AES_ECB, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {CKM_AES_CBC, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {CKM_AES_CBC_PAD, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {CKM_DH_PKCS_KEY_PAIR_GEN, {512, 2048, CKF_GENERATE_KEY_PAIR}}, {CKM_DH_PKCS_DERIVE, {512, 2048, CKF_DERIVE}}, {CKM_DSA_KEY_PAIR_GEN, {512, 2048, CKF_HW|CKF_GENERATE_KEY_PAIR}}, {CKM_DSA_SHA1, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_DSA, {512, 2048, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {CKM_ECDSA_SHA1, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY|CKF_EC_F_P| CKF_EC_NAMEDCURVE|CKF_EC_UNCOMPRESS}}, {CKM_ECDSA, {160, 521, CKF_HW|CKF_SIGN|CKF_VERIFY|CKF_EC_F_P| CKF_EC_NAMEDCURVE|CKF_EC_UNCOMPRESS}}, {CKM_EC_KEY_PAIR_GEN, {160, 521, CKF_HW|CKF_GENERATE_KEY_PAIR| CKF_EC_F_P|CKF_EC_NAMEDCURVE|CKF_EC_UNCOMPRESS}}, {CKM_SSL3_PRE_MASTER_KEY_GEN, {48, 48, CKF_HW|CKF_GENERATE}}, {CKM_SSL3_MD5_MAC, {384, 384, CKF_SIGN|CKF_VERIFY}}, {CKM_SSL3_SHA1_MAC, {384, 384, CKF_SIGN|CKF_VERIFY}}, {CKM_SSL3_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}}, {CKM_SSL3_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}}, {CKM_TLS_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}}, {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW|CKF_GENERATE}}, }; CK_ULONG mech_list_len = (sizeof(mech_list) / sizeof(MECH_LIST_ELEMENT)); /* * This list contains one element to each session and it's used to keep * session specific data. Any insertion or deletion in this list should * be protected by sess_list_mutex. * * This lock is intended to protect the linked list, not the content of each * element. Since PKCS#11 applications should not use the same session for * different threads, the only concurrency that we have to deal is when adding * or removing a session to or from the list. */ list_t sessions = LIST_INIT(); extern pthread_mutex_t sess_list_mutex; /* Each element of the list sessions should have this type: */ struct session_state { CK_SESSION_HANDLE session_id; LDAP *ld; /* List element */ list_entry_t sessions; }; /* * This binary tree keeps the mapping between ICSF object handles and PKCS#11 * object handles. The tree index is used as the PKCS#11 handle. * * Any insertion or deletion in this tree should be protected by * obj_list_rw_mutex. */ struct btree objects; extern pthread_rwlock_t obj_list_rw_mutex; /* Each element of the btree objects should have this type: */ struct icsf_object_mapping { CK_SESSION_HANDLE session_id; struct icsf_object_record icsf_object; }; /* * Structure used to keep track of data used in multi-part operations. */ struct icsf_multi_part_context { int initiated; char chain_data[ICSF_CHAINING_DATA_LEN]; char *data; size_t data_len; size_t used_data_len; }; /* * Get the session specific structure. */ static struct session_state *get_session_state(CK_SESSION_HANDLE session_id) { struct session_state *found = NULL; struct session_state *s; /* Lock sessions list */ if (pthread_mutex_lock(&sess_list_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return NULL; } for_each_list_entry(&sessions, struct session_state, s, sessions) { if (s->session_id == session_id) { found = s; goto done; } } done: /* Unlock */ if (pthread_mutex_unlock(&sess_list_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); return NULL; } return found; } /* * Remove all mapped objects. */ static CK_RV purge_object_mapping() { if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } bt_destroy(&objects, free); if (pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); return CKR_FUNCTION_FAILED; } return CKR_OK; } /* Store ICSF specific data for each slot*/ struct slot_data { int initialized; char conf_name[PATH_MAX + 1]; char uri[PATH_MAX + 1]; char dn[NAME_MAX + 1]; char ca_file[PATH_MAX + 1]; char cert_file[PATH_MAX + 1]; char key_file[PATH_MAX + 1]; int mech; }; struct slot_data *slot_data[MAX_SLOT_ID + 1]; /* * Converts an ICSF reason code to an ock error code */ int icsf_to_ock_err(int icsf_return_code, int icsf_reason_code) { switch(icsf_return_code) { case 0: return CKR_OK; case 4: switch(icsf_reason_code) { case 8000: case 11000: return CKR_SIGNATURE_INVALID; } break; case 8: switch(icsf_reason_code) { case 2154: return CKR_KEY_TYPE_INCONSISTENT; case 3003: return CKR_BUFFER_TOO_SMALL; case 3019: return CKR_SESSION_HANDLE_INVALID; case 3027: return CKR_SESSION_HANDLE_INVALID; case 3029: return CKR_ATTRIBUTE_TYPE_INVALID; case 3030: return CKR_ATTRIBUTE_VALUE_INVALID; case 3033: return CKR_TEMPLATE_INCOMPLETE; case 3034: case 3035: return CKR_ATTRIBUTE_READ_ONLY; case 3038: return CKR_KEY_FUNCTION_NOT_PERMITTED; case 3039: return CKR_KEY_TYPE_INCONSISTENT; case 3041: return CKR_KEY_NOT_WRAPPABLE; case 3043: return CKR_BUFFER_TOO_SMALL; case 3045: return CKR_KEY_UNEXTRACTABLE; case 3046: return CKR_BUFFER_TOO_SMALL; case 11000: return CKR_DATA_LEN_RANGE; } break; } return CKR_FUNCTION_FAILED; } /* * Called during C_Initialize. */ CK_RV icsftok_init(CK_SLOT_ID slot_id, char *conf_name) { CK_RV rc = CKR_OK; struct slot_data *data; /* Check Slot ID */ if (slot_id < 0 || slot_id > MAX_SLOT_ID) { TRACE_ERROR("Invalid slot ID: %lu\n", slot_id); return CKR_FUNCTION_FAILED; } XProcLock(); if (slot_data[slot_id] == NULL) { TRACE_ERROR("ICSF slot data not initialized.\n"); rc = CKR_FUNCTION_FAILED; goto done; } data = slot_data[slot_id]; strncpy(data->conf_name, conf_name, sizeof(data->conf_name) - 1); data->conf_name[sizeof(data->conf_name) - 1] = '\0'; done: XProcUnLock(); return rc; } CK_RV token_specific_init_token_data(CK_SLOT_ID slot_id) { CK_RV rc = CKR_OK; const char *conf_name = NULL; struct icsf_config config; /* Check Slot ID */ if (slot_id < 0 || slot_id > MAX_SLOT_ID) { TRACE_ERROR("Invalid slot ID: %lu\n", slot_id); return CKR_FUNCTION_FAILED; } XProcLock(); if (slot_data[slot_id] == NULL) { TRACE_ERROR("ICSF slot data not initialized.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if data needs to be retrieved for this slot */ if (slot_data[slot_id]->initialized) { TRACE_DEVEL("Slot data already initialized for slot %lu. " "Skipping it\n", slot_id); goto done; } /* Check config file */ conf_name = slot_data[slot_id]->conf_name; if (!conf_name || !conf_name[0]) { TRACE_ERROR("Missing config for slot %lu.\n", slot_id); return CKR_FUNCTION_FAILED; } TRACE_DEVEL("DEBUG: conf_name=\"%s\".\n", conf_name); if (parse_config_file(conf_name, slot_id, &config)) { TRACE_ERROR("Failed to parse file \"%s\" for slot %lu.\n", conf_name, slot_id); rc = CKR_FUNCTION_FAILED; goto done; } /* Copy general info */ strcpy(nv_token_data->token_info.label, config.name); strcpy(nv_token_data->token_info.manufacturerID, config.manuf); strcpy(nv_token_data->token_info.model, config.model); strcpy(nv_token_data->token_info.serialNumber, config.serial); /* Copy ICSF specific info */ strcpy(slot_data[slot_id]->uri, config.uri); strcpy(slot_data[slot_id]->dn, config.dn); strcpy(slot_data[slot_id]->ca_file, config.ca_file); strcpy(slot_data[slot_id]->cert_file, config.cert_file); strcpy(slot_data[slot_id]->key_file, config.key_file); slot_data[slot_id]->initialized = 1; slot_data[slot_id]->mech = config.mech; done: XProcUnLock(); return rc; } CK_RV token_specific_load_token_data(CK_SLOT_ID slot_id, FILE *fh) { CK_RV rc = CKR_OK; struct slot_data data; /* Check Slot ID */ if (slot_id < 0 || slot_id > MAX_SLOT_ID) { TRACE_ERROR("Invalid slot ID: %lu\n", slot_id); return CKR_FUNCTION_FAILED; } if (!fread(&data, sizeof(data), 1, fh)) { TRACE_ERROR("Failed to read ICSF slot data.\n"); return CKR_FUNCTION_FAILED; } XProcLock(); if (slot_data[slot_id] == NULL) { TRACE_ERROR("ICSF slot data not initialized.\n"); rc = CKR_FUNCTION_FAILED; goto done; } memcpy(slot_data[slot_id], &data, sizeof(data)); done: XProcUnLock(); return rc; } CK_RV token_specific_save_token_data(CK_SLOT_ID slot_id, FILE *fh) { CK_RV rc = CKR_OK; /* Check Slot ID */ if (slot_id < 0 || slot_id > MAX_SLOT_ID) { TRACE_ERROR("Invalid slot ID: %lu\n", slot_id); return CKR_FUNCTION_FAILED; } XProcLock(); if (slot_data[slot_id] == NULL) { TRACE_ERROR("ICSF slot data not initialized.\n"); rc = CKR_FUNCTION_FAILED; goto done; } if (!fwrite(slot_data[slot_id], sizeof(**slot_data), 1, fh)) { TRACE_ERROR("Failed to write ICSF slot data.\n"); rc = CKR_FUNCTION_FAILED; goto done; } done: XProcUnLock(); return rc; } /* * Initialize the shared memory region. ICSF has to use a custom method for * this because it uses additional data in the shared memory and in the future * multiple slots should be supported for ICSF. */ CK_RV token_specific_attach_shm(CK_SLOT_ID slot_id, LW_SHM_TYPE **shm) { CK_RV rc = CKR_OK; int ret; void *ptr; size_t len = sizeof(**shm) + sizeof(**slot_data); char *shm_id = NULL; if (slot_id < 0 || slot_id > MAX_SLOT_ID) { TRACE_ERROR("Invalid slot ID: %lu\n", slot_id); return CKR_FUNCTION_FAILED; } if (asprintf(&shm_id, "/icsf-%lu", slot_id) < 0) { TRACE_ERROR("Failed to allocate shared memory id " "for slot %lu.\n", slot_id); return CKR_HOST_MEMORY; } TRACE_DEVEL("Attaching to shared memory \"%s\".\n", shm_id); XProcLock(); /* * Attach to an existing shared memory region or create it if it doesn't * exists. When the it's created (ret=0) the region is initialized with * zeroes. */ ret = sm_open(shm_id, 0666, (void**) &ptr, len, 1); if (ret < 0) { TRACE_ERROR("Failed to open shared memory \"%s\".\n", shm_id); rc = CKR_FUNCTION_FAILED; goto done; } *shm = ptr; slot_data[slot_id] = ptr + sizeof(**shm); done: XProcUnLock(); if (shm_id) free(shm_id); return rc; } CK_RV login(LDAP **ld, CK_SLOT_ID slot_id, CK_BYTE *pin, CK_ULONG pin_len, const char *pass_file_type) { CK_RV rc = CKR_OK; struct slot_data data; LDAP *ldapd = NULL; char *fname = NULL; int ret; /* Check Slot ID */ if (slot_id < 0 || slot_id > MAX_SLOT_ID) { TRACE_ERROR("Invalid slot ID: %lu\n", slot_id); return CKR_FUNCTION_FAILED; } XProcLock(); /* Check slot data */ if (slot_data[slot_id] == NULL || !slot_data[slot_id]->initialized) { TRACE_ERROR("ICSF slot data not initialized.\n"); rc = CKR_FUNCTION_FAILED; goto done; } memcpy(&data, slot_data[slot_id], sizeof(data)); XProcUnLock(); if (data.mech == ICSF_CFG_MECH_SIMPLE) { CK_BYTE mk[MAX_KEY_SIZE]; CK_BYTE racf_pass[PIN_SIZE]; int mk_len = sizeof(mk); int racf_pass_len = sizeof(racf_pass); CK_BYTE pk_dir_buf[PATH_MAX], fname[PATH_MAX]; /* Load master key */ sprintf(fname, "%s/MK_SO", get_pk_dir(pk_dir_buf)); if (get_masterkey(pin, pin_len, fname, mk, &mk_len)) { TRACE_DEVEL("Failed to get masterkey \"%s\".\n", fname); return CKR_FUNCTION_FAILED; } /* Load RACF password */ if (get_racf(mk, mk_len, racf_pass, &racf_pass_len)) { TRACE_DEVEL("Failed to get RACF password.\n"); return CKR_FUNCTION_FAILED; } /* Simple bind */ ret = icsf_login(&ldapd, data.uri, data.dn, racf_pass); } else { /* SASL bind */ ret = icsf_sasl_login(&ldapd, data.uri, data.cert_file, data.key_file, data.ca_file, NULL); } if (ret) { TRACE_DEVEL("Failed to bind to %s\n", data.uri); rc = CKR_FUNCTION_FAILED; goto done; } if (icsf_check_pkcs_extension(ldapd)) { TRACE_ERROR("ICSF LDAP externsion not supported.\n"); rc = CKR_FUNCTION_FAILED; goto done; } done: if (rc == CKR_OK && ld) *ld = ldapd; if (fname) free(fname); return rc; } CK_RV reset_token_data(CK_SLOT_ID slot_id, CK_CHAR_PTR pin, CK_ULONG pin_len) { CK_BYTE mk[MAX_KEY_SIZE]; CK_BYTE racf_pass[PIN_SIZE]; int mk_len = sizeof(mk); int racf_pass_len = sizeof(racf_pass); CK_BYTE pk_dir_buf[PATH_MAX], fname[PATH_MAX]; /* Remove user's masterkey */ if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { sprintf(fname, "%s/MK_USER", get_pk_dir(pk_dir_buf)); if (unlink(fname) && errno == ENOENT) TRACE_WARNING("Failed to remove \"%s\".\n", fname); /* Load master key */ sprintf(fname, "%s/MK_SO", get_pk_dir(pk_dir_buf)); if (get_masterkey(pin, pin_len, fname, mk, &mk_len)) { TRACE_DEVEL("Failed to load masterkey \"%s\".\n", fname); return CKR_FUNCTION_FAILED; } /* Load RACF password */ if (get_racf(mk, mk_len, racf_pass, &racf_pass_len)) { TRACE_DEVEL("Failed to get RACF password.\n"); return CKR_FUNCTION_FAILED; } /* Generate new key */ if (get_randombytes(mk, mk_len)) { TRACE_DEVEL("Failed to generate new master key.\n"); return CKR_FUNCTION_FAILED; } /* Save racf password using the new master key */ if (secure_racf(racf_pass, racf_pass_len, mk, mk_len)) { TRACE_DEVEL("Failed to save racf password.\n"); return CKR_FUNCTION_FAILED; } } /* Reset token data and keep token name */ slot_data[slot_id]->initialized = 0; init_token_data(slot_id); init_slotInfo(); nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED; /* Reset SO pin to default and user pin to invalid */ pin_len = strlen((pin = "87654321")); if (compute_sha1(pin, pin_len, nv_token_data->so_pin_sha)) { TRACE_ERROR("Failed to reset so pin.\n"); return CKR_FUNCTION_FAILED; } memset(nv_token_data->user_pin_sha, '0', sizeof(nv_token_data->user_pin_sha)); if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { /* Save master key */ if (secure_masterkey(mk, mk_len, pin, pin_len, fname)) { TRACE_DEVEL("Failed to save the new master key.\n"); return CKR_FUNCTION_FAILED; } } if (save_token_data(slot_id)) { TRACE_DEVEL("Failed to save token data.\n"); return CKR_FUNCTION_FAILED; } return CKR_OK; } CK_RV destroy_objects(CK_SLOT_ID slot_id, CK_CHAR_PTR token_name, CK_CHAR_PTR pin, CK_ULONG pin_len) { CK_RV rc = CKR_OK; LDAP *ld = NULL; struct icsf_object_record records[16]; struct icsf_object_record *previous = NULL; size_t i, records_len; int reason = 0; if (login(&ld, slot_id, pin, pin_len, RACFFILE)) return CKR_FUNCTION_FAILED; TRACE_DEVEL("Destroying objects in slot %lu.\n", slot_id); do { records_len = sizeof(records)/sizeof(records[0]); rc = icsf_list_objects(ld, NULL, token_name, 0, NULL, previous, records, &records_len, 0); if (ICSF_RC_IS_ERROR(rc)) { TRACE_DEVEL("Failed to list objects for slot %lu.\n", slot_id); rc = CKR_FUNCTION_FAILED; goto done; } for (i = 0; i < records_len; i++) { if ((rc = icsf_destroy_object(ld, &reason, &records[i]))) { TRACE_DEVEL("Failed to destroy object " "%s/%lu/%c in slot %lu.\n", records[i].token_name, records[i].sequence, records[i].id, slot_id); rc = icsf_to_ock_err(rc, reason); goto done; } } if (records_len) previous = &records[records_len - 1]; } while (records_len); done: if (icsf_logout(ld) && rc == CKR_OK) rc = CKR_FUNCTION_FAILED; return rc; } /* * Initialize token. */ CK_RV icsftok_init_token(CK_SLOT_ID slot_id, CK_CHAR_PTR pin, CK_ULONG pin_len, CK_CHAR_PTR label) { CK_RV rc = CKR_OK; CK_BYTE hash_sha[SHA1_HASH_SIZE]; /* Check pin */ rc = compute_sha1(pin, pin_len, hash_sha); if (memcmp(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } if ((rc = reset_token_data(slot_id, pin, pin_len))) goto done; if ((rc = destroy_objects(slot_id, nv_token_data->token_info.label, pin, pin_len))) goto done; /* purge the object btree */ if (purge_object_mapping()) { TRACE_DEVEL("Failed to purge objects.\n"); rc = CKR_FUNCTION_FAILED; } done: return rc; } CK_RV icsftok_init_pin(SESSION *sess, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rc = CKR_OK; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_SLOT_ID sid; CK_BYTE fname[PATH_MAX]; char pk_dir_buf[PATH_MAX]; /* get slot id */ sid = sess->session_info.slotID; /* compute the SHA of the user pin */ rc = compute_sha1(pPin, ulPinLen, hash_sha); if (rc != CKR_OK) { TRACE_ERROR("Hash Computation Failed.\n"); return rc; } /* encrypt the masterkey and store in MK_USER if using SIMPLE AUTH * to authenticate to ldao server. The masterkey protects the * racf passwd. */ if (slot_data[sid]->mech == ICSF_CFG_MECH_SIMPLE) { sprintf(fname, "%s/MK_USER", get_pk_dir(pk_dir_buf)); rc = secure_masterkey(master_key, AES_KEY_SIZE_256, pPin, ulPinLen, fname); if (rc != CKR_OK) { TRACE_DEVEL("Could not create MK_USER.\n"); return rc; } } rc = XProcLock(); if (rc != CKR_OK) { TRACE_ERROR("Process Lock Failed.\n"); return rc; } memcpy(nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE); nv_token_data->token_info.flags |= CKF_USER_PIN_INITIALIZED; nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); nv_token_data->token_info.flags &= ~(CKF_USER_PIN_LOCKED); XProcUnLock(); return rc; } CK_RV icsftok_set_pin(SESSION *sess, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { CK_RV rc = CKR_OK; CK_BYTE new_hash_sha[SHA1_HASH_SIZE]; CK_BYTE old_hash_sha[SHA1_HASH_SIZE]; CK_BYTE fname[PATH_MAX]; CK_SLOT_ID sid; char pk_dir_buf[PATH_MAX]; /* get slot id */ sid = sess->session_info.slotID; rc = compute_sha1(pNewPin, ulNewLen, new_hash_sha ); rc |= compute_sha1( pOldPin, ulOldLen, old_hash_sha ); if (rc != CKR_OK) { TRACE_ERROR("Hash Computation Failed.\n"); return rc; } /* check that the old pin and new pin are not the same. */ if (memcmp(old_hash_sha, new_hash_sha, SHA1_HASH_SIZE) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID)); return CKR_PIN_INVALID; } /* check the length requirements */ if ((ulNewLen < MIN_PIN_LEN) || (ulNewLen > MAX_PIN_LEN)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LEN_RANGE)); return CKR_PIN_LEN_RANGE; } if ((sess->session_info.state == CKS_RW_USER_FUNCTIONS) || (sess->session_info.state == CKS_RW_PUBLIC_SESSION)) { /* check that old pin matches what is in NVTOK.DAT */ if (memcmp(nv_token_data->user_pin_sha, old_hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); return CKR_PIN_INCORRECT; } /* if using simple auth, encrypt masterkey with new pin */ if (slot_data[sid]->mech == ICSF_CFG_MECH_SIMPLE) { sprintf (fname, "%s/MK_USER", get_pk_dir(pk_dir_buf)); rc = secure_masterkey(master_key, AES_KEY_SIZE_256, pNewPin, ulNewLen, fname); if (rc != CKR_OK) { TRACE_ERROR("Save Master Key Failed.\n"); return rc; } } /* grab lock and change shared memory */ rc = XProcLock(); if (rc != CKR_OK) { TRACE_ERROR("Process Lock Failed.\n"); return rc; } memcpy(nv_token_data->user_pin_sha, new_hash_sha, SHA1_HASH_SIZE); nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); XProcUnLock(); } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { /* check that old pin matches what is in NVTOK.DAT */ if (memcmp(nv_token_data->so_pin_sha, old_hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); return CKR_PIN_INCORRECT; } /* check that new pin is not the default */ if (memcmp(new_hash_sha, default_so_pin_sha, SHA1_HASH_SIZE) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID)); return CKR_PIN_INVALID; } if (slot_data[sid]->mech == ICSF_CFG_MECH_SIMPLE) { /* * if using simle auth, encrypt masterkey with new pin */ sprintf (fname, "%s/MK_SO", get_pk_dir(pk_dir_buf)); rc = secure_masterkey(master_key, AES_KEY_SIZE_256, pNewPin, ulNewLen, fname); if (rc != CKR_OK) { TRACE_ERROR("Save Master Key Failed.\n"); return rc; } } /* grab lock and change shared memory */ rc = XProcLock(); if (rc != CKR_OK) { TRACE_ERROR("Process Lock Failed.\n"); return rc; } memcpy(nv_token_data->so_pin_sha, new_hash_sha, SHA1_HASH_SIZE); nv_token_data->token_info.flags &= ~(CKF_SO_PIN_TO_BE_CHANGED); XProcUnLock(); } else { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); return CKR_SESSION_READ_ONLY; } rc = save_token_data(sid); if (rc != CKR_OK) { TRACE_ERROR("Save Token Failed.\n"); return rc; } return rc; } LDAP *getLDAPhandle(CK_SLOT_ID slot_id) { CK_BYTE racfpwd[PIN_SIZE]; int racflen; char *ca_dir = NULL; LDAP *new_ld = NULL; CK_RV rc = CKR_OK; if (slot_data[slot_id] == NULL) { TRACE_ERROR("ICSF slot data not initialized.\n"); return NULL; } /* Check if using sasl or simple auth */ if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { TRACE_INFO("Using SIMPLE auth with slot ID: %lu\n", slot_id); /* get racf passwd */ rc = get_racf(master_key, AES_KEY_SIZE_256, racfpwd, &racflen); if (rc != CKR_OK) { TRACE_DEVEL("Failed to get racf passwd.\n"); return NULL; } /* ok got the passwd, perform simple ldap bind call */ rc = icsf_login(&new_ld, slot_data[slot_id]->uri, slot_data[slot_id]->dn, racfpwd); if (rc != CKR_OK) { TRACE_DEVEL("Failed to bind to ldap server.\n"); return NULL; } } else { TRACE_INFO("Using SASL auth with slot ID: %lu\n", slot_id); rc = icsf_sasl_login(&new_ld, slot_data[slot_id]->uri, slot_data[slot_id]->cert_file, slot_data[slot_id]->key_file, slot_data[slot_id]->ca_file, ca_dir); if (rc != CKR_OK) { TRACE_DEVEL("Failed to bind to ldap server.\n"); return NULL; } } return new_ld; } CK_RV icsf_get_handles(CK_SLOT_ID slot_id) { struct session_state *s; /* Any prior sessions without an ldap descriptor, can now get one. */ /* Lock sessions list */ if (pthread_mutex_lock(&sess_list_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } for_each_list_entry(&sessions, struct session_state, s, sessions) { if (s->ld == NULL) s->ld = getLDAPhandle(slot_id); } if (pthread_mutex_unlock(&sess_list_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); return CKR_FUNCTION_FAILED; } return CKR_OK; } CK_RV icsftok_open_session(SESSION *sess) { CK_RV rc = CKR_OK; LDAP *ld; struct session_state *session_state; /* Add session to list */ session_state = malloc(sizeof(struct session_state)); if (!session_state) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_FUNCTION_FAILED; } session_state->session_id = sess->handle; session_state->ld = NULL; if (pthread_mutex_lock(&sess_list_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); free(session_state); return CKR_FUNCTION_FAILED; } /* see if user has logged in to acquire ldap handle for session. * pkcs#11v2.2 states that all sessions within a process have * same login state. */ if (global_login_state == CKS_RW_USER_FUNCTIONS || global_login_state == CKS_RO_USER_FUNCTIONS) { ld = getLDAPhandle(sess->session_info.slotID); if (ld == NULL) { TRACE_DEVEL("Failed to get LDAP handle for session.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* put the new ldap handle into the session state. */ session_state->ld = ld; } /* put new session_state into the list */ list_insert_head(&sessions, &session_state->sessions); done: /* Unlock */ if (pthread_mutex_unlock(&sess_list_mutex)) { TRACE_ERROR("Mutex Unlock Failed.\n"); rc = CKR_FUNCTION_FAILED; } if (rc != CKR_OK) free(session_state); return rc;; } /* * Close a session. * * Must be called with sess_list_mutex locked. */ static CK_RV close_session(struct session_state *session_state) { CK_RV rc = CKR_OK; unsigned long i; int reason = 0; if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } /* Remove each session object */ for (i = 1; i <= objects.size; i++) { struct icsf_object_mapping *mapping; /* Skip missing ids */ if(!(mapping = bt_get_node_value(&objects, i))) continue; /* Skip object from other sessions */ if (mapping->session_id != session_state->session_id) continue; /* Skip token objects */ if (mapping->icsf_object.id != ICSF_SESSION_OBJECT) continue; if ((rc = icsf_destroy_object(session_state->ld, &reason, &mapping->icsf_object))) { /* Log error */ TRACE_DEBUG("Failed to remove icsf object: %s/%lu/%c", mapping->icsf_object.token_name, mapping->icsf_object.sequence, mapping->icsf_object.id); rc = icsf_to_ock_err(rc, reason); break; } /* Remove object from object list */ bt_node_free(&objects, i, &free); } if (pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock Failed.\n"); return CKR_FUNCTION_FAILED; } if (rc) return rc; /* Log off from LDAP server */ if (session_state->ld) { if (icsf_logout(session_state->ld)) { TRACE_DEVEL("Failed to disconnect from LDAP server.\n"); return CKR_FUNCTION_FAILED; } session_state->ld = NULL; } /* Remove session */ list_remove(&session_state->sessions); if (list_is_empty(&sessions)) { if (purge_object_mapping()) { TRACE_DEVEL("Failed to purge objects.\n"); rc = CKR_FUNCTION_FAILED; } } free(session_state); return rc; } /* * Called during C_CloseSession. */ CK_RV icsftok_close_session(SESSION *session) { CK_RV rc; struct session_state *session_state; /* Get the related session_state */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } /* Remove session_state from the list and free it */ if (pthread_mutex_lock(&sess_list_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } if ((rc = close_session(session_state))) TRACE_ERROR("close_session failed\n"); if (pthread_mutex_unlock(&sess_list_mutex)) { TRACE_ERROR("Mutex Unlock Failed.\n"); rc = CKR_FUNCTION_FAILED; } return rc; } /* * Called during C_Finalize and C_CloseAllSessions */ CK_RV icsftok_close_all_sessions(void) { CK_RV rc = CKR_OK; struct session_state *session_state; list_entry_t *e; /* Lock to add a new session in the list */ if (pthread_mutex_lock(&sess_list_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } for_each_list_entry_safe(&sessions, struct session_state, session_state, sessions, e) { if ((rc = close_session(session_state))) break; } /* Unlock */ if (pthread_mutex_unlock(&sess_list_mutex)) { TRACE_ERROR("Mutex Unlock Failed.\n"); return CKR_FUNCTION_FAILED; } return rc; } CK_RV icsftok_login(SESSION *sess, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rc = CKR_OK; char fname[PATH_MAX]; CK_BYTE hash_sha[SHA1_HASH_SIZE]; int mklen; char pk_dir_buf[PATH_MAX]; CK_SLOT_ID slot_id = sess->session_info.slotID; /* Check Slot ID */ if (slot_id < 0 || slot_id > MAX_SLOT_ID) { TRACE_ERROR("Invalid slot ID: %lu\n", slot_id); return CKR_FUNCTION_FAILED; } /* compute the sha of the pin. */ rc = compute_sha1(pPin, ulPinLen, hash_sha); if (rc != CKR_OK) { TRACE_ERROR("Hash Computation Failed.\n"); return rc; } XProcLock(); if (userType == CKU_USER) { /* check if pin initialized */ if (memcmp(nv_token_data->user_pin_sha, "00000000000000000000", SHA1_HASH_SIZE) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED)); rc = CKR_USER_PIN_NOT_INITIALIZED; goto done; } /* check that pin is the same as the one in NVTOK.DAT */ if (memcmp(nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* now load the master key */ if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { sprintf(fname, "%s/MK_USER", get_pk_dir(pk_dir_buf)); rc = get_masterkey(pPin, ulPinLen, fname, master_key, &mklen); if (rc != CKR_OK) { TRACE_DEVEL("Failed to load master key.\n"); goto done; } } } else { /* if SO ... */ /* check that pin is the same as the one in NVTOK.DAT */ if (memcmp(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } if (slot_data[slot_id]->mech == ICSF_CFG_MECH_SIMPLE) { /* now load the master key */ sprintf(fname, "%s/MK_SO", get_pk_dir(pk_dir_buf)); rc = get_masterkey(pPin, ulPinLen, fname, master_key, &mklen); if (rc != CKR_OK) { TRACE_DEVEL("Failed to load master key.\n"); goto done; } } } /* Now that user is authenticated, can get racf passwd and * establish ldap handle for session. This will get done * when we call icsf_get_handles() in SC_Login(). */ done: XProcUnLock(); return rc; } static CK_RV check_session_permissions(SESSION *sess, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len) { CK_RV rc = CKR_OK; /* PKCS#11 default value for CKA_TOKEN is FALSE */ CK_BBOOL is_token_obj = FALSE; /* ICSF default value for CKA_PRIVATE is TRUE */ CK_BBOOL is_priv_obj = TRUE; /* Get attributes values */ find_bbool_attribute(attrs, attrs_len, CKA_TOKEN, &is_token_obj); find_bbool_attribute(attrs, attrs_len, CKA_PRIVATE, &is_priv_obj); /* * Check whether session has permissions to create the object, etc * * Object R/O R/W R/O R/W R/W * Type Public Public User User SO * ------------------------------------------------------------- * Public session R/W R/W R/W R/W R/W * Private session R/W R/W * Public token R/O R/W R/O R/W R/W * Private token R/O R/W */ if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (is_priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } if (is_token_obj) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (is_token_obj) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (is_priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (is_priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } } done: return rc; } /* * Copy an existing object. */ CK_RV icsftok_copy_object(SESSION * session, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE src, CK_OBJECT_HANDLE_PTR dst) { CK_RV rc = CKR_OK; struct session_state *session_state; struct icsf_object_mapping *mapping_dst = NULL; struct icsf_object_mapping *mapping_src = NULL; CK_ULONG node_number; int is_obj_locked = 0; int reason = 0; CK_BBOOL is_priv; CK_BBOOL is_token; CK_RV rc_permission = CKR_OK; CK_ATTRIBUTE priv_attrs[] = { {CKA_PRIVATE, &is_priv, sizeof(is_priv)}, {CKA_TOKEN, &is_token, sizeof(is_token)}, }; CK_ATTRIBUTE_PTR temp_attrs; /* Get session state */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Allocate structure for new object */ if (!(mapping_dst = malloc(sizeof(*mapping_dst)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } pthread_rwlock_rdlock(&obj_list_rw_mutex); mapping_src = bt_get_node_value(&objects, src); pthread_rwlock_unlock(&obj_list_rw_mutex); if (!mapping_src) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_OBJECT_HANDLE_INVALID; goto done; } rc = icsf_get_attribute(session_state->ld, &reason, &mapping_src->icsf_object, priv_attrs, 2); if (rc != CKR_OK) { TRACE_ERROR("icsf_get_attribute failed\n"); goto done; } if (attrs_len != 0) { /* looking for CKA_PRIVATE */ temp_attrs = get_attribute_by_type(attrs, attrs_len, CKA_PRIVATE); if (temp_attrs != NULL) { priv_attrs[0].pValue = temp_attrs->pValue; priv_attrs[0].ulValueLen = temp_attrs->ulValueLen; } /* looking for CKA_TOKEN */ temp_attrs = get_attribute_by_type(attrs, attrs_len, CKA_TOKEN); if (temp_attrs != NULL) { priv_attrs[1].pValue = temp_attrs->pValue; priv_attrs[1].ulValueLen = attrs->ulValueLen; } } /* Check permissions based on attributes and session */ rc = check_session_permissions(session, priv_attrs, 2); if (rc_permission != CKR_OK) { TRACE_DEVEL("check_session_permissions failed\n"); goto done; } /* Call ICSF service */ rc = icsf_copy_object(session_state->ld, &reason, attrs, attrs_len, &mapping_src->icsf_object, &mapping_dst->icsf_object); if (rc != 0) { TRACE_DEVEL("Failed to Copy object.\n"); rc = icsf_to_ock_err(rc, reason); goto done; } /* Lock the object list */ if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); rc = CKR_FUNCTION_FAILED; goto done; } is_obj_locked = 1; /* Add info about object into session */ if (!(node_number = bt_node_add(&objects, mapping_dst))) { TRACE_ERROR("Failed to add object to binary tree.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Use node number as handle */ *dst = node_number; done: if (is_obj_locked && pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock Failed.\n"); rc = CKR_FUNCTION_FAILED; } /* If allocated, object must be freed in case of failure */ if (rc && mapping_dst) free(mapping_dst); return rc; } /* * Create a new object. */ CK_RV icsftok_create_object(SESSION *session, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle) { CK_RV rc = CKR_OK; struct session_state *session_state; struct icsf_object_mapping *mapping; CK_ULONG node_number; char token_name[sizeof(nv_token_data->token_info.label)]; int is_obj_locked = 0; int reason = 0; /* Check permissions based on attributes and session */ rc = check_session_permissions(session, attrs, attrs_len); if (rc != CKR_OK) return rc; /* Copy token name from shared memory */ XProcLock(); memcpy(token_name, nv_token_data->token_info.label, sizeof(token_name)); XProcUnLock(); /* Allocate structure to keep ICSF object information */ if (!(mapping = malloc(sizeof(*mapping)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(mapping, 0, sizeof(struct icsf_object_mapping)); mapping->session_id = session->handle; /* Get session state */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Call ICSF service */ if ((rc = icsf_create_object(session_state->ld, &reason, token_name, attrs, attrs_len, &mapping->icsf_object))) { TRACE_DEVEL("icsf_create_object failed\n"); rc = icsf_to_ock_err(rc, reason); goto done; } /* Lock the object list */ if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); rc = CKR_FUNCTION_FAILED; goto done; } is_obj_locked = 1; /* Add info about object into session */ if(!(node_number = bt_node_add(&objects, mapping))) { TRACE_ERROR("Failed to add object to binary tree.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Use node number as handle */ *handle = node_number; done: if (is_obj_locked && pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); rc = CKR_FUNCTION_FAILED; } /* If allocated, object must be freed in case of failure */ if (rc && mapping) free(mapping); return rc; } /* * Check if attribute values are valid and add default values for missing ones. * * It returns a new allocated array that must be freed with * free_attribute_array(). */ static CK_RV check_key_attributes(CK_ULONG class, CK_ULONG key_type, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_ATTRIBUTE_PTR *p_attrs, CK_ULONG *p_attrs_len) { CK_RV rc; CK_ULONG i; CK_ULONG check_types[] = { CKA_CLASS, CKA_KEY_TYPE }; CK_ULONG *check_values[] = { &class, &key_type }; if ((rc = dup_attribute_array(attrs, attrs_len, p_attrs, p_attrs_len))) return rc; for (i = 0; i < sizeof(check_types)/sizeof(*check_types); i++) { /* Search for the attribute */ CK_ATTRIBUTE_PTR attr = get_attribute_by_type(*p_attrs, *p_attrs_len, check_types[i]); if (attr) { /* Check the expected value */ if (*((CK_ULONG *) attr->pValue) != *check_values[i]) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); rc = CKR_ATTRIBUTE_VALUE_INVALID; goto cleanup; } } else { /* Add default value */ rc = add_to_attribute_array(p_attrs, p_attrs_len, check_types[i], (CK_BYTE *) check_values[i], sizeof(*check_values[i])); if (rc) goto cleanup; } } rc = CKR_OK; cleanup: if (rc) { free_attribute_array(*p_attrs, *p_attrs_len); *p_attrs = NULL; *p_attrs_len = 0; } return rc; } /* * Get the type of the key that must be generated based on given mechanism. * * This functions is used by both symmetric and asymmetric key generation * functions. */ static CK_ULONG get_generate_key_type(CK_MECHANISM_PTR mech) { switch (mech->mechanism) { /* Symmetric keys */ case CKM_AES_KEY_GEN: return CKK_AES; case CKM_DES_KEY_GEN: return CKK_DES; case CKM_DES2_KEY_GEN: return CKK_DES2; case CKM_DES3_KEY_GEN: return CKK_DES3; case CKM_SSL3_PRE_MASTER_KEY_GEN: return CKK_GENERIC_SECRET; /* Asymmetric keys */ case CKM_RSA_PKCS_KEY_PAIR_GEN: return CKK_RSA; case CKM_DSA_KEY_PAIR_GEN: return CKK_DSA; case CKM_DH_PKCS_KEY_PAIR_GEN: case CKM_DH_PKCS_DERIVE: return CKK_DH; case CKM_EC_KEY_PAIR_GEN: return CKK_EC; case CKM_SSL3_MASTER_KEY_DERIVE: case CKM_SSL3_KEY_AND_MAC_DERIVE: case CKM_TLS_KEY_AND_MAC_DERIVE: case CKM_GENERIC_SECRET_KEY_GEN: return CKK_GENERIC_SECRET; } return -1; } /* * Generate a key pair. */ CK_RV icsftok_generate_key_pair(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR pub_attrs, CK_ULONG pub_attrs_len, CK_ATTRIBUTE_PTR priv_attrs, CK_ULONG priv_attrs_len, CK_OBJECT_HANDLE_PTR p_pub_key, CK_OBJECT_HANDLE_PTR p_priv_key) { CK_RV rc; char token_name[sizeof(nv_token_data->token_info.label)]; struct session_state *session_state; struct icsf_object_mapping *pub_key_mapping = NULL; struct icsf_object_mapping *priv_key_mapping = NULL; int reason = 0; int is_obj_locked = 0; int pub_node_number, priv_node_number; CK_ATTRIBUTE_PTR new_pub_attrs = NULL; CK_ULONG new_pub_attrs_len = 0; CK_ATTRIBUTE_PTR new_priv_attrs = NULL; CK_ULONG new_priv_attrs_len = 0; CK_ULONG key_type; /* Check and set default attributes based on mech */ if ((key_type = get_generate_key_type(mech)) == -1) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; goto done; } rc = check_key_attributes(CKO_PUBLIC_KEY, key_type, pub_attrs, pub_attrs_len, &new_pub_attrs, &new_pub_attrs_len); if (rc != CKR_OK) goto done; rc = check_key_attributes(CKO_PRIVATE_KEY, key_type, priv_attrs, priv_attrs_len, &new_priv_attrs, &new_priv_attrs_len); if (rc != CKR_OK) goto done; /* Check permissions based on attributes and session */ rc = check_session_permissions(session, new_pub_attrs, new_pub_attrs_len); if (rc != CKR_OK) goto done; rc = check_session_permissions(session, new_priv_attrs, new_priv_attrs_len); if (rc != CKR_OK) goto done; /* Get session state */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Copy token name from shared memory */ XProcLock(); memcpy(token_name, nv_token_data->token_info.label, sizeof(token_name)); XProcUnLock(); /* Allocate structure to keep ICSF objects information */ if (!(pub_key_mapping = malloc(sizeof(*pub_key_mapping))) || !(priv_key_mapping = malloc(sizeof(*priv_key_mapping)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } /* Call ICSF service */ if ((rc = icsf_generate_key_pair(session_state->ld, &reason, token_name, new_pub_attrs, new_pub_attrs_len, new_priv_attrs, new_priv_attrs_len, &pub_key_mapping->icsf_object, &priv_key_mapping->icsf_object))) { TRACE_DEVEL("icsf_generate_key_pair failed\n"); rc = icsf_to_ock_err(rc, reason); goto done; } /* Lock the object list */ if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); rc = CKR_FUNCTION_FAILED; goto done; } is_obj_locked = 1; /* Add info about objects into session */ if(!(pub_node_number = bt_node_add(&objects, pub_key_mapping)) || !(priv_node_number = bt_node_add(&objects, priv_key_mapping))) { TRACE_ERROR("Failed to add object to binary tree.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Use node numbers as handles */ *p_pub_key = pub_node_number; *p_priv_key = priv_node_number; done: if (is_obj_locked && pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to unlock mutex.\n"); rc = CKR_FUNCTION_FAILED; } free_attribute_array(new_pub_attrs, new_pub_attrs_len); free_attribute_array(new_priv_attrs, new_priv_attrs_len); /* Object mappings must be freed in case of failure */ if (rc && pub_key_mapping) free(pub_key_mapping); if (rc && priv_key_mapping) free(priv_key_mapping); return rc; } /* * Generate a symmetric key. */ CK_RV icsftok_generate_key(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle) { CK_RV rc = CKR_OK; struct session_state *session_state; struct icsf_object_mapping *mapping = NULL; CK_ULONG node_number; char token_name[sizeof(nv_token_data->token_info.label)]; int is_obj_locked = 0; CK_ATTRIBUTE_PTR new_attrs = NULL; CK_ULONG new_attrs_len = 0; CK_ULONG class = CKO_SECRET_KEY; CK_ULONG key_type = 0; int reason = 0; /* Check attributes */ if ((key_type = get_generate_key_type(mech)) == -1) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; goto done; } rc = check_key_attributes(class, key_type, attrs, attrs_len, &new_attrs, &new_attrs_len); if (rc != CKR_OK) goto done; /* Check permissions based on attributes and session */ rc = check_session_permissions(session, new_attrs, new_attrs_len); if (rc != CKR_OK) goto done; /* Copy token name from shared memory */ XProcLock(); memcpy(token_name, nv_token_data->token_info.label, sizeof(token_name)); XProcUnLock(); /* Allocate structure to keep ICSF object information */ if (!(mapping = malloc(sizeof(*mapping)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto done; } memset(mapping, 0, sizeof(struct icsf_object_mapping)); mapping->session_id = session->handle; /* Get session state */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Call ICSF service */ if ((rc = icsf_generate_secret_key(session_state->ld, &reason, token_name, mech, new_attrs, new_attrs_len, &mapping->icsf_object))) { TRACE_DEVEL("icsf_generate_secret_key failed\n"); rc = icsf_to_ock_err(rc, reason); goto done; } /* Lock the object list */ if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); rc = CKR_FUNCTION_FAILED; goto done; } is_obj_locked = 1; /* Add info about object into session */ if(!(node_number = bt_node_add(&objects, mapping))) { TRACE_ERROR("Failed to add object to binary tree.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Use node number as handle */ *handle = node_number; done: if (is_obj_locked && pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); rc = CKR_FUNCTION_FAILED; } if (new_attrs) free_attribute_array(new_attrs, new_attrs_len); /* If allocated, object must be freed in case of failure */ if (rc && mapping) free(mapping); return rc; } /* * Free all data pointed by an encryption context and set everything to zero. */ static void free_encr_ctx(ENCR_DECR_CONTEXT *encr_ctx) { struct icsf_multi_part_context *multi_part_ctx; if (!encr_ctx) return; /* Initialize encryption context */ multi_part_ctx = (struct icsf_multi_part_context *) encr_ctx->context; if (multi_part_ctx) { if (multi_part_ctx->data) free(multi_part_ctx->data); free(multi_part_ctx); } if (encr_ctx->mech.pParameter) free(encr_ctx->mech.pParameter); memset(encr_ctx, 0, sizeof(*encr_ctx)); } /* * Return if the algorithm used by a mechanism is asymmetric or symmetric. */ static CK_RV get_crypt_type(CK_MECHANISM_PTR mech, int *p_symmetric) { switch (mech->mechanism) { case CKM_AES_ECB: case CKM_AES_CBC: case CKM_AES_CBC_PAD: case CKM_DES_ECB: case CKM_DES_CBC: case CKM_DES_CBC_PAD: case CKM_DES3_ECB: case CKM_DES3_CBC: case CKM_DES3_CBC_PAD: *p_symmetric = 1; break; case CKM_RSA_PKCS: case CKM_RSA_X_509: *p_symmetric = 0; break; default: return CKR_MECHANISM_INVALID; } return CKR_OK; } /* * Initialize an encryption operation. */ CK_RV icsftok_encrypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key) { CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *encr_ctx = &session->encr_ctx; struct icsf_multi_part_context *multi_part_ctx = NULL; size_t block_size = 0; int symmetric = 0; /* Check session */ if (!get_session_state(session->handle)) { rc = CKR_SESSION_HANDLE_INVALID; TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); goto done; } /* Get algorithm type */ if ((rc = get_crypt_type(mech, &symmetric))) goto done; /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!bt_get_node_value(&objects, key)) { rc = CKR_KEY_HANDLE_INVALID; TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* Initialize encryption context */ free_encr_ctx(encr_ctx); encr_ctx->key = key; encr_ctx->active = TRUE; /* Copy mechanism */ if (mech->pParameter == NULL || mech->ulParameterLen == 0) { encr_ctx->mech.ulParameterLen = 0; encr_ctx->mech.pParameter = NULL; } else { encr_ctx->mech.pParameter = malloc(mech->ulParameterLen); if (!encr_ctx->mech.pParameter) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } encr_ctx->mech.ulParameterLen = mech->ulParameterLen; memcpy(encr_ctx->mech.pParameter, mech->pParameter, mech->ulParameterLen); } encr_ctx->mech.mechanism = mech->mechanism; /* * Asymmetric algorithms don't support multi-part and then there's no * need to allocate context. */ if (!symmetric) goto done; /* Allocate context for multi-part operations */ if (!(multi_part_ctx = malloc(sizeof(*multi_part_ctx)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } encr_ctx->context = (void *) multi_part_ctx; /* Chained data has always a fixed length */ memset(multi_part_ctx, 0, sizeof(*multi_part_ctx)); /* Check mechanism and get block size */ rc = icsf_block_size(mech->mechanism, &block_size); if (rc != CKR_OK) goto done; /* * data is used to retain data until at least the block size is reached. */ multi_part_ctx->data_len = block_size; multi_part_ctx->data = malloc(multi_part_ctx->data_len); if (!multi_part_ctx->data) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } done: if (rc != CKR_OK) free_encr_ctx(encr_ctx); return rc; } /* * Encrypt data and finalize an encryption operation. */ CK_RV icsftok_encrypt(SESSION *session, CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len) { CK_RV rc = CKR_OK; CK_BBOOL is_length_only = (output_data == NULL); ENCR_DECR_CONTEXT *encr_ctx = &session->encr_ctx; struct session_state *session_state; struct icsf_object_mapping *mapping; char chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); int reason = 0; int symmetric = 0; /* Get algorithm type */ if ((rc = get_crypt_type(&encr_ctx->mech, &symmetric))) goto done; /* Check if there's a multi-part encryption in progress */ if (encr_ctx->multi) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, encr_ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* Encrypt data using remote token. */ if (symmetric) { rc = icsf_secret_key_encrypt(session_state->ld, &reason, &mapping->icsf_object, &encr_ctx->mech, ICSF_CHAINING_ONLY, input_data, input_data_len, output_data, p_output_data_len, chain_data, &chain_data_len); } else { rc = icsf_public_key_verify(session_state->ld, &reason, TRUE, &mapping->icsf_object, &encr_ctx->mech, input_data, input_data_len, output_data, p_output_data_len); } if (rc) { if (reason == ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) { if (is_length_only) { /* * Parameter too short is not a problem when * querying the expect output size. */ rc = CKR_OK; } else { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; } } else { TRACE_ERROR("Failed to encrypt data. reason = %d\n", reason); rc = icsf_to_ock_err(rc, reason); } goto done; } done: if (rc != CKR_BUFFER_TOO_SMALL && !(rc == CKR_OK && is_length_only)) free_encr_ctx(encr_ctx); return rc; } /* * Multi-part encryption. */ CK_RV icsftok_encrypt_update(SESSION *session, CK_BYTE_PTR input_part, CK_ULONG input_part_len, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { CK_RV rc = CKR_OK; CK_BBOOL is_length_only = (output_part == NULL); ENCR_DECR_CONTEXT *encr_ctx = &session->encr_ctx; struct icsf_multi_part_context *multi_part_ctx; struct session_state *session_state; struct icsf_object_mapping *mapping; char chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); CK_ULONG total, remaining; char *buffer = NULL; int chaining; int reason = 0; int symmetric = 0; /* Multi-part is not supported for asymmetric algorithms. */ if ((rc = get_crypt_type(&encr_ctx->mech, &symmetric))) goto done; if (!symmetric) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, encr_ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; multi_part_ctx = (struct icsf_multi_part_context *) encr_ctx->context; /* Define the type of the call */ switch (encr_ctx->mech.mechanism) { case CKM_DES_ECB: case CKM_DES3_ECB: case CKM_AES_ECB: /* ICSF just support the chaining mode ONLY for ECB. */ chaining = ICSF_CHAINING_ONLY; break; default: if (multi_part_ctx->initiated) { chaining = ICSF_CHAINING_CONTINUE; memcpy(chain_data, multi_part_ctx->chain_data, chain_data_len); } else { chaining = ICSF_CHAINING_INITIAL; } } /* * Data needs to be sent to ICSF in chucks with size that is multiple of * block size. Any remaining data is kept in the multi-part context and * can be sent in a further call of the update function or when the * finalize function is called. */ total = multi_part_ctx->used_data_len + input_part_len; remaining = total % multi_part_ctx->data_len; /* * If there's no enough data to make a call, skip it. */ if (total < multi_part_ctx->data_len) { *p_output_part_len = 0; goto keep_remaining_data; } /* * The data to be encrypted should have length that is multiple of the * block size. It is composed by data kept in the multi-part context * concatenated with part of the data given. */ if (!(buffer = malloc(total - remaining))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(buffer, multi_part_ctx->data, multi_part_ctx->used_data_len); memcpy(buffer + multi_part_ctx->used_data_len, input_part, input_part_len - remaining); /* Encrypt data using remote token. */ rc = icsf_secret_key_encrypt(session_state->ld, &reason, &mapping->icsf_object, &encr_ctx->mech, chaining, buffer, total - remaining, output_part, p_output_part_len, chain_data, &chain_data_len); if (rc) { if (reason == ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) { if (is_length_only) { /* * Parameter too short is not a problem when * querying the expect output size. */ rc = CKR_OK; } else { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; } } else { TRACE_DEVEL("Failed to encrypt data. reason = %d\n", reason); rc = icsf_to_ock_err(rc, reason); } goto done; } /* * When blocks are sent it's necessary to keep the chain data returned * to be used in a subsequent call. */ if (!is_length_only) { /* Copy chain data into context */ memcpy(multi_part_ctx->chain_data, chain_data, chain_data_len); /* Mark multi-part operation as initiated */ multi_part_ctx->initiated = TRUE; /* Data stored in cache was used */ multi_part_ctx->used_data_len = 0; } keep_remaining_data: /* Keep the remaining data to a next call */ if (!is_length_only) { /* Copy remaining part of input_part into context */ if (total < multi_part_ctx->data_len) { memcpy(multi_part_ctx->data + multi_part_ctx->used_data_len, input_part, input_part_len); } else { memcpy(multi_part_ctx->data, input_part + input_part_len - remaining, remaining); } multi_part_ctx->used_data_len = remaining; } done: /* Free resources */ if (buffer) free(buffer); if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) free_encr_ctx(encr_ctx); return rc; } /* * Finalize a multi-part encryption. */ CK_RV icsftok_encrypt_final(SESSION *session, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { CK_RV rc = CKR_OK; CK_BBOOL is_length_only = (output_part == NULL); ENCR_DECR_CONTEXT *encr_ctx = &session->encr_ctx; struct icsf_multi_part_context *multi_part_ctx; struct session_state *session_state; struct icsf_object_mapping *mapping; char chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); int chaining; int reason = 0; int symmetric = 0; /* Multi-part is not supported for asymmetric algorithms. */ if ((rc = get_crypt_type(&encr_ctx->mech, &symmetric))) goto done; if (!symmetric) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, encr_ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* Define the type of the call */ multi_part_ctx = (struct icsf_multi_part_context *) encr_ctx->context; switch (encr_ctx->mech.mechanism) { case CKM_DES_ECB: case CKM_DES3_ECB: case CKM_AES_ECB: /* * When not using a chained algorithm and there's no remaining * data, don't call ICSF. */ *p_output_part_len = 0; if (!multi_part_ctx->used_data_len) goto done; /* ICSF just support the chaining mode ONLY for ECB. */ chaining = ICSF_CHAINING_ONLY; break; default: if (multi_part_ctx->initiated) { chaining = ICSF_CHAINING_FINAL; memcpy(chain_data, multi_part_ctx->chain_data, chain_data_len); } else { chaining = ICSF_CHAINING_ONLY; } } /* * Encrypt data using remote token. * * All the data in multi-part context should be sent. */ rc = icsf_secret_key_encrypt(session_state->ld, &reason, &mapping->icsf_object, &encr_ctx->mech, chaining, multi_part_ctx->data, multi_part_ctx->used_data_len, output_part, p_output_part_len, chain_data, &chain_data_len); if (rc) { if (reason == ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) { if (is_length_only) { /* * Parameter too short is not a problem when * querying the expect output size. */ rc = CKR_OK; } else { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; } } else { TRACE_DEVEL("Failed to encrypt data. reason = %d\n", reason); rc = icsf_to_ock_err(rc, reason); } goto done; } done: if ((is_length_only && rc != CKR_OK) || (!is_length_only && rc != CKR_BUFFER_TOO_SMALL)) free_encr_ctx(encr_ctx); return rc; } /* * Initialize a decryption operation. */ CK_RV icsftok_decrypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key) { CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *decr_ctx = &session->decr_ctx; struct icsf_multi_part_context *multi_part_ctx = NULL; size_t block_size = 0; int symmetric = 0; /* Check session */ if (!get_session_state(session->handle)) { rc = CKR_SESSION_HANDLE_INVALID; TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); goto done; } /* Get algorithm type */ if ((rc = get_crypt_type(mech, &symmetric))) goto done; /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!bt_get_node_value(&objects, key)) { rc = CKR_KEY_HANDLE_INVALID; TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* Initialize decryption context */ free_encr_ctx(decr_ctx); decr_ctx->key = key; decr_ctx->active = TRUE; /* Copy mechanism */ if (mech->pParameter == NULL || mech->ulParameterLen == 0) { decr_ctx->mech.ulParameterLen = 0; decr_ctx->mech.pParameter = NULL; } else { decr_ctx->mech.pParameter = malloc(mech->ulParameterLen); if (!decr_ctx->mech.pParameter) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } decr_ctx->mech.ulParameterLen = mech->ulParameterLen; memcpy(decr_ctx->mech.pParameter, mech->pParameter, mech->ulParameterLen); } decr_ctx->mech.mechanism = mech->mechanism; /* * Asymmetric algorithms don't support multi-part and then there's no * need to allocate context. */ if (!symmetric) goto done; /* Allocate context for multi-part operations */ if (!(multi_part_ctx = malloc(sizeof(*multi_part_ctx)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } decr_ctx->context = (void *) multi_part_ctx; /* Chained data has always a fixed length */ memset(multi_part_ctx, 0, sizeof(*multi_part_ctx)); /* Check mechanism and get block size */ rc = icsf_block_size(mech->mechanism, &block_size); if (rc != CKR_OK) goto done; /* * data is used to retain data until at least the block size is reached. */ multi_part_ctx->data_len = block_size; multi_part_ctx->data = malloc(multi_part_ctx->data_len); if (!multi_part_ctx->data) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } done: if (rc != CKR_OK) free_encr_ctx(decr_ctx); return rc; } /* * Decrypt data and finalize a decryption operation. */ CK_RV icsftok_decrypt(SESSION *session, CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len) { CK_RV rc = CKR_OK; CK_BBOOL is_length_only = (output_data == NULL); ENCR_DECR_CONTEXT *decr_ctx = &session->decr_ctx; struct session_state *session_state; struct icsf_object_mapping *mapping; char chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); int reason = 0; int symmetric = 0; /* Get algorithm type */ if ((rc = get_crypt_type(&decr_ctx->mech, &symmetric))) goto done; /* Check if there's a multi-part decryption in progress */ if (decr_ctx->multi) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, decr_ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* Decrypt data using remote token. */ if (symmetric) { rc = icsf_secret_key_decrypt(session_state->ld, &reason, &mapping->icsf_object, &decr_ctx->mech, ICSF_CHAINING_ONLY, input_data, input_data_len, output_data, p_output_data_len, chain_data, &chain_data_len); } else { rc = icsf_private_key_sign(session_state->ld, &reason, TRUE, &mapping->icsf_object, &decr_ctx->mech, input_data, input_data_len, output_data, p_output_data_len); } if (rc) { if (reason == ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) { if (is_length_only) { /* * Parameter too short is not a problem when * querying the expect output size. */ rc = CKR_OK; } else { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; } } else { TRACE_DEVEL("Failed to decrypt data. reason = %d\n", reason); rc = icsf_to_ock_err(rc, reason); } goto done; } done: if (rc != CKR_BUFFER_TOO_SMALL && !(rc == CKR_OK && is_length_only)) free_encr_ctx(decr_ctx); return rc; } /* * Multi-part decryption. */ CK_RV icsftok_decrypt_update(SESSION *session, CK_BYTE_PTR input_part, CK_ULONG input_part_len, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { CK_RV rc = CKR_OK; CK_BBOOL is_length_only = (output_part == NULL); ENCR_DECR_CONTEXT *decr_ctx = &session->decr_ctx; struct icsf_multi_part_context *multi_part_ctx; struct session_state *session_state; struct icsf_object_mapping *mapping; char chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); CK_ULONG total, remaining; char *buffer = NULL; int chaining; int reason = 0; int padding = 0; int symmetric = 0; /* Multi-part is not supported for asymmetric algorithms. */ if ((rc = get_crypt_type(&decr_ctx->mech, &symmetric))) goto done; if (!symmetric) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, decr_ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; multi_part_ctx = (struct icsf_multi_part_context *) decr_ctx->context; /* Define the type of the call */ switch (decr_ctx->mech.mechanism) { case CKM_AES_ECB: case CKM_DES_ECB: case CKM_DES3_ECB: /* ICSF just support the chaining mode ONLY for ECB. */ chaining = ICSF_CHAINING_ONLY; break; case CKM_AES_CBC_PAD: case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: padding = 1; default: if (multi_part_ctx->initiated) { chaining = ICSF_CHAINING_CONTINUE; memcpy(chain_data, multi_part_ctx->chain_data, chain_data_len); } else { chaining = ICSF_CHAINING_INITIAL; } } /* * Data needs to be sent to ICSF in chucks with size that is multiple of * block size. Any remaining data is kept in the multi-part context and * can be sent in a further call of the update function or when the * finalize function is called. * * When padding is used, there's no way to know if the current block of * data is the one that contains the padding, So a block is kept in * multi-part context when the data available is exactly multiple of the * block size. */ total = multi_part_ctx->used_data_len + input_part_len; if (!padding) { remaining = total % multi_part_ctx->data_len; } else { remaining = MIN(((total - 1) % multi_part_ctx->data_len) + 1, total); } /* * If there's no enough data to make a call, skip it. */ if (total < multi_part_ctx->data_len || (padding && total == multi_part_ctx->data_len)) { *p_output_part_len = 0; goto keep_remaining_data; } /* * The data to be decrypted should have length that is multiple of the * block size. It is composed by data kept in the multi-part context * concatenated with part of the data given. */ if (!(buffer = malloc(total - remaining))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(buffer, multi_part_ctx->data, multi_part_ctx->used_data_len); memcpy(buffer + multi_part_ctx->used_data_len, input_part, input_part_len - remaining); /* Decrypt data using remote token. */ rc = icsf_secret_key_decrypt(session_state->ld, &reason, &mapping->icsf_object, &decr_ctx->mech, chaining, buffer, total - remaining, output_part, p_output_part_len, chain_data, &chain_data_len); if (rc) { if (reason == ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) { if (is_length_only) { /* * Parameter too short is not a problem when * querying the expect output size. */ rc = CKR_OK; } else { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; } } else { TRACE_DEVEL("Failed to decrypt data. reason = %d\n", reason); rc = icsf_to_ock_err(rc, reason); } goto done; } /* * When blocks are sent it's necessary to keep the chain data returned * to be used in a subsequent call. */ if (!is_length_only) { /* Copy chain data into context */ memcpy(multi_part_ctx->chain_data, chain_data, chain_data_len); /* Mark multi-part operation as initiated */ multi_part_ctx->initiated = TRUE; /* Data stored in cache was used */ multi_part_ctx->used_data_len = 0; } keep_remaining_data: /* Keep the remaining data to a next call */ if (!is_length_only) { /* Copy remaining part of input_part into context */ if (total < multi_part_ctx->data_len || (padding && total == multi_part_ctx->data_len)) { memcpy(multi_part_ctx->data + multi_part_ctx->used_data_len, input_part, input_part_len); } else { memcpy(multi_part_ctx->data, input_part + input_part_len - remaining, remaining); } multi_part_ctx->used_data_len = remaining; } done: /* Free resources */ if (buffer) free(buffer); if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) free_encr_ctx(decr_ctx); return rc; } /* * Finalize a multi-part decryption. */ CK_RV icsftok_decrypt_final(SESSION *session, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { CK_RV rc = CKR_OK; CK_BBOOL is_length_only = (output_part == NULL); ENCR_DECR_CONTEXT *decr_ctx = &session->decr_ctx; struct icsf_multi_part_context *multi_part_ctx; struct session_state *session_state; struct icsf_object_mapping *mapping; char chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); int chaining; int reason = 0; int symmetric = 0; /* Multi-part is not supported for asymmetric algorithms. */ if ((rc = get_crypt_type(&decr_ctx->mech, &symmetric))) goto done; if (!symmetric) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, decr_ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* Define the type of the call */ multi_part_ctx = (struct icsf_multi_part_context *) decr_ctx->context; switch (decr_ctx->mech.mechanism) { case CKM_AES_ECB: case CKM_DES_ECB: case CKM_DES3_ECB: /* * When not using a chained algorithm and there's no remaining * data, don't call ICSF. */ *p_output_part_len = 0; if (!multi_part_ctx->used_data_len) goto done; /* ICSF just support the chaining mode ONLY for ECB. */ chaining = ICSF_CHAINING_ONLY; break; default: if (multi_part_ctx->initiated) { chaining = ICSF_CHAINING_FINAL; memcpy(chain_data, multi_part_ctx->chain_data, chain_data_len); } else { chaining = ICSF_CHAINING_ONLY; } } /* * Decrypt data using remote token. * * All the data in multi-part context should be sent. */ rc = icsf_secret_key_decrypt(session_state->ld, &reason, &mapping->icsf_object, &decr_ctx->mech, chaining, multi_part_ctx->data, multi_part_ctx->used_data_len, output_part, p_output_part_len, chain_data, &chain_data_len); if (rc) { if (reason == ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) { if (is_length_only) { /* * Parameter too short is not a problem when * querying the expect output size. */ rc = CKR_OK; } else { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; } } else { TRACE_DEVEL("Failed to decrypt data. reason = %d\n", reason); rc = icsf_to_ock_err(rc, reason); } goto done; } done: if ((is_length_only && rc != CKR_OK) || (!is_length_only && rc != CKR_BUFFER_TOO_SMALL)) free_encr_ctx(decr_ctx); return rc; } /* * Get the attribute values for a list of attributes. */ CK_RV icsftok_get_attribute_value(SESSION *sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) { CK_RV rc = CKR_OK; CK_BBOOL priv_obj; struct session_state *session_state; struct icsf_object_mapping *mapping = NULL; int reason = 0; CK_ATTRIBUTE priv_attr[] = { {CKA_PRIVATE, &priv_obj, sizeof(priv_obj)}, }; /* Get session state */ if (!(session_state = get_session_state(sess->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); return CKR_FUNCTION_FAILED; } /* get the object handle */ /* get a read lock */ if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } mapping = bt_get_node_value(&objects, handle); if (!mapping) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); rc = CKR_OBJECT_HANDLE_INVALID; goto done; } /* get the private attribute so we can check the permissions */ rc = icsf_get_attribute(session_state->ld, &reason, &mapping->icsf_object, priv_attr, 1); if (rc != CKR_OK) { TRACE_DEVEL("icsf_get_attribute failed\n"); rc = icsf_to_ock_err(rc, reason); goto done; } if (priv_obj == TRUE) { if (sess->session_info.state == CKS_RO_PUBLIC_SESSION || sess->session_info.state == CKS_RW_PUBLIC_SESSION) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } } /* Now call icsf to get the attribute values */ rc = icsf_get_attribute(session_state->ld, &reason, &mapping->icsf_object, pTemplate, ulCount); if (rc != CKR_OK) { TRACE_DEVEL("icsf_get_attribute failed\n"); rc = icsf_to_ock_err(rc, reason); } done: if (pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); rc = CKR_FUNCTION_FAILED; } return rc; } /* * Set attribute values for a list of attributes. */ CK_RV icsftok_set_attribute_value(SESSION *sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) { struct session_state *session_state; struct icsf_object_mapping *mapping = NULL; CK_BBOOL is_priv; CK_BBOOL is_token; CK_RV rc = CKR_OK; int reason = 0; CK_ATTRIBUTE priv_attrs[] = { {CKA_PRIVATE, &is_priv, sizeof(is_priv)}, {CKA_TOKEN, &is_token, sizeof(is_token)}, }; /* Get session state */ if (!(session_state = get_session_state(sess->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); return CKR_FUNCTION_FAILED; } /* get the object handle */ /* get a read lock */ if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } mapping = bt_get_node_value(&objects, handle); if (!mapping) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); rc = CKR_OBJECT_HANDLE_INVALID; goto done; } /* check permissions : * first get CKA_PRIVATE since we need to check againse session * icsf will check if the attributes are modifiable */ rc = icsf_get_attribute(session_state->ld, &reason, &mapping->icsf_object, priv_attrs, 2); if (rc != CKR_OK) { TRACE_DEVEL("icsf_get_attribute failed\n"); rc = icsf_to_ock_err(rc, reason); goto done; } /* Check permissions based on attributes and session */ rc = check_session_permissions(sess, priv_attrs, 2); if (rc != CKR_OK) { TRACE_DEVEL("check_session_permissions failed\n"); goto done; } /* Now call into icsf to set the attribute values */ rc = icsf_set_attribute(session_state->ld, &reason, &mapping->icsf_object, pTemplate, ulCount); if (rc != CKR_OK) { TRACE_ERROR("icsf_set_attribute failed\n"); rc = icsf_to_ock_err(rc, reason); goto done; } done: /* Unlock */ if (pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); rc = CKR_FUNCTION_FAILED; } return rc; } /* * Initialize a search for token and session objects that match a template. */ CK_RV icsftok_find_objects_init(SESSION *sess, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) { char token_name[sizeof(nv_token_data->token_info.label)]; struct session_state *session_state; struct icsf_object_record records[MAX_RECORDS]; struct icsf_object_record *previous = NULL; size_t records_len; int i, j, node_number; int reason = 0; CK_RV rc = CKR_OK; /* Whether we retrieve public or private objects is determined by * the caller's SAF authority on the token, something ock doesn't * control. * Since an app MUST have authenticated to ICSF token to use it, * we can always assume it is an authenticated session and anything else * is an error. */ if (sess->session_info.state == CKS_RO_PUBLIC_SESSION || sess->session_info.state == CKS_RW_PUBLIC_SESSION || sess->session_info.state == CKS_RW_SO_FUNCTIONS) { TRACE_ERROR("You must authenticate to access ICSF token.\n"); return CKR_FUNCTION_FAILED; } /* Initialize the found object list. In keeping with other tokens, * if the list does not exist, allocate list big enough for MAX_RECORD * handles. reallocate later if more needed. */ if (sess->find_list == NULL) { sess->find_list = (CK_OBJECT_HANDLE *) malloc( 10 * sizeof(CK_OBJECT_HANDLE)); if (!sess->find_list) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } sess->find_len = 10; } memset(sess->find_list, 0x0, sess->find_len*sizeof(CK_OBJECT_HANDLE)); sess->find_count = 0; sess->find_idx = 0; /* Prepare to query ICSF for list objects * Copy token name from shared memory */ XProcLock(); memcpy(token_name, nv_token_data->token_info.label, sizeof(token_name)); XProcUnLock(); /* Get session state */ if (!(session_state = get_session_state(sess->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); return CKR_FUNCTION_FAILED; } /* clear out records */ memset(records, 0, MAX_RECORDS*(sizeof(struct icsf_object_record))); if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } do { records_len = sizeof(records)/sizeof(struct icsf_object_record); rc = icsf_list_objects(session_state->ld, &reason, token_name, ulCount, pTemplate, previous, records, &records_len, 0); if (ICSF_RC_IS_ERROR(rc)) { TRACE_DEVEL("Failed to list objects.\n"); rc = icsf_to_ock_err(rc, reason); goto done; } /* Now step thru the object btree so we can find the node * value for any matching objects we retrieved from ICSF. * If we cannot find a matching object in the btree, * then add it so we can get a node value. * And also because ICSF object database is authoritative. */ for (i = 0; i < records_len; i++) { /* mark not found */ node_number = 0; for (j=1; j <= objects.size; j++) { struct icsf_object_mapping *mapping = NULL; /* skip missing ids */ mapping = bt_get_node_value(&objects, j); if (mapping) { if (memcmp(&records[i], &mapping->icsf_object, sizeof(struct icsf_object_record)) == 0) { node_number = j; break; } } else continue; } /* if could not find in our object tree, then add it * since ICSF object database is authoritative. */ if (!node_number) { struct icsf_object_mapping *new_mapping; if (!(new_mapping = malloc(sizeof(*new_mapping)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } new_mapping->session_id = sess->handle; new_mapping->icsf_object = records[i]; if(!(node_number = bt_node_add(&objects, new_mapping))) { TRACE_ERROR("Failed to add object to " "binary tree.\n"); rc = CKR_FUNCTION_FAILED; goto done; } } /* Add to our findobject list */ if (node_number) { sess->find_list[sess->find_count] = node_number; sess->find_count++; if (sess->find_count >= sess->find_len) { void *find_list; size_t find_len = sess->find_len + MAX_RECORDS; find_list = realloc(sess->find_list, find_len * sizeof(CK_OBJECT_HANDLE)); if (!find_list) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } sess->find_list = find_list; sess->find_len = find_len; } } } if (records_len) previous = &records[records_len - 1]; } while (records_len); sess->find_active = TRUE; done: if (pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); return CKR_FUNCTION_FAILED; } return rc; } /* * Destroy an object. */ CK_RV icsftok_destroy_object(SESSION *sess, CK_OBJECT_HANDLE handle) { struct session_state *session_state; struct icsf_object_mapping *mapping = NULL; int reason; CK_RV rc = CKR_OK; /* Get session state */ if (!(session_state = get_session_state(sess->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID;; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); return CKR_FUNCTION_FAILED; } /* Lock the object list */ if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); return CKR_FUNCTION_FAILED; } /* get the object handle */ mapping = bt_get_node_value(&objects, handle); if (!mapping) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); rc = CKR_OBJECT_HANDLE_INVALID; goto done; } /* Now remove the object from ICSF */ rc = icsf_destroy_object(session_state->ld, &reason, &mapping->icsf_object); if (rc != 0) { TRACE_DEVEL("icsf_destroy_object failed\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Now remove the object from the object btree */ bt_node_free(&objects, handle, free); done: if (pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); return CKR_FUNCTION_FAILED; } return rc; } /* * Free all data pointed by SIGN_VERIFY_CONTEXT and set everything to zero. */ static void free_sv_ctx(SIGN_VERIFY_CONTEXT *ctx) { struct icsf_multi_part_context *multi_part_ctx; if (!ctx) return; /* Initialize encryption context */ multi_part_ctx = (struct icsf_multi_part_context *) ctx->context; if (multi_part_ctx) { if (multi_part_ctx->data) free(multi_part_ctx->data); free(multi_part_ctx); } if (ctx->mech.pParameter) free(ctx->mech.pParameter); memset(ctx, 0, sizeof(*ctx)); } /* * get the hash size for hmacs. */ int get_signverify_len(CK_MECHANISM mech) { switch(mech.mechanism) { case CKM_MD5_HMAC: case CKM_SSL3_MD5_MAC: return MD5_HASH_SIZE; case CKM_SHA_1_HMAC: case CKM_SSL3_SHA1_MAC: return SHA1_HASH_SIZE; case CKM_SHA256_HMAC: return SHA2_HASH_SIZE; case CKM_SHA384_HMAC: return SHA3_HASH_SIZE; case CKM_SHA512_HMAC: return SHA5_HASH_SIZE; } return -1; } CK_RV icsftok_sign_init(SESSION *session, CK_MECHANISM *mech, CK_OBJECT_HANDLE key) { struct session_state *session_state; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; struct icsf_multi_part_context *multi_part_ctx = NULL; struct icsf_object_mapping *mapping = NULL; CK_RV rc = CKR_OK; CK_BBOOL multi = FALSE; CK_BBOOL datacaching = FALSE; CK_MAC_GENERAL_PARAMS *param; /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) return rc; /* Check the mechanism info */ switch (mech->mechanism) { case CKM_RSA_X_509: case CKM_RSA_PKCS: case CKM_DSA: case CKM_ECDSA: /* these do not do multipart and do not require * a mechanism parameter. */ if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } multi = FALSE; break; case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: /* hmacs can do mulitpart and do not require a * mechanism parameter. */ if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } multi = TRUE; break; case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: /* can do mulitpart and take a mech parameter */ param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if (((mech->mechanism == CKM_SSL3_MD5_MAC) && (*param != 16)) || ((mech->mechanism == CKM_SSL3_SHA1_MAC) && (*param != 20))){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } multi = TRUE; break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_DSA_SHA1: case CKM_ECDSA_SHA1: /* these can do mulitpart and require data caching * and do not require a mechanism parameter. */ if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } multi = TRUE; datacaching = TRUE; break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } /* Initialize sign context */ free_sv_ctx(ctx); /* Copy mechanism */ if (mech->pParameter == NULL || mech->ulParameterLen == 0) { ctx->mech.ulParameterLen = 0; ctx->mech.pParameter = NULL; } else { ctx->mech.pParameter = malloc(mech->ulParameterLen); if (!ctx->mech.pParameter) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } ctx->mech.ulParameterLen = mech->ulParameterLen; memcpy(ctx->mech.pParameter, mech->pParameter, mech->ulParameterLen); } ctx->mech.mechanism = mech->mechanism; /* If the mechanism supports multipart, prepare ctx */ if (multi) { /* Allocate context for multi-part operations */ if (!(multi_part_ctx = malloc(sizeof(*multi_part_ctx)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } ctx->context_len = sizeof(*multi_part_ctx); ctx->context = (void *) multi_part_ctx; memset(multi_part_ctx, 0, sizeof(*multi_part_ctx)); /* keep a cache to ensure multiple of blocksize * is sent to ICSF. */ if (datacaching) { size_t blocksize; rc = icsf_block_size(mech->mechanism, &blocksize); if (rc != CKR_OK) goto done; multi_part_ctx->data_len = blocksize; multi_part_ctx->data = malloc(multi_part_ctx->data_len); if (!multi_part_ctx->data) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(multi_part_ctx->data, 0, blocksize); } } else { ctx->context_len = 0; ctx->context = NULL; } ctx->key = key; ctx->multi = FALSE; ctx->active = TRUE; done: if (rc != CKR_OK) free_sv_ctx(ctx); return rc; } CK_RV icsftok_sign(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG *sig_len) { struct session_state *session_state; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; struct icsf_object_mapping *mapping = NULL; CK_BYTE chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); CK_RV rc = CKR_OK; int hlen, reason; CK_BBOOL length_only = (signature == NULL); if (ctx->multi == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; switch (ctx->mech.mechanism) { case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: if (length_only) { hlen = get_signverify_len(ctx->mech); if (hlen < 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; goto done; } *sig_len = hlen; rc = CKR_OK; goto done; } rc = icsf_hmac_sign(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, "ONLY", in_data, in_data_len, signature, sig_len, chain_data, &chain_data_len); if (rc != 0) rc = icsf_to_ock_err(rc, reason); break; case CKM_RSA_X_509: case CKM_RSA_PKCS: case CKM_DSA: case CKM_ECDSA: rc = icsf_private_key_sign(session_state->ld, &reason, FALSE, &mapping->icsf_object, &ctx->mech, in_data, in_data_len, signature, sig_len); if (rc != 0) { if (reason == ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT && length_only) { rc = CKR_OK; } else { TRACE_DEVEL("icsf_private_key_sign failed\n"); rc = icsf_to_ock_err(rc, reason); } } break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_DSA_SHA1: case CKM_ECDSA_SHA1: rc = icsf_hash_signverify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, "ONLY", in_data, in_data_len, signature, sig_len, chain_data, &chain_data_len, 0); if (rc != 0) { if (reason == ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT && length_only) { rc = CKR_OK; } else { TRACE_DEVEL("icsf_hash_signverify failed\n"); rc = icsf_to_ock_err(rc, reason); } } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } done: if (rc != CKR_BUFFER_TOO_SMALL && !(rc == CKR_OK && length_only)) free_sv_ctx(ctx); return rc; } CK_RV icsftok_sign_update(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len) { struct session_state *session_state; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; struct icsf_object_mapping *mapping = NULL; struct icsf_multi_part_context *multi_part_ctx = NULL; CK_BYTE chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); CK_RV rc = CKR_OK; int reason; size_t siglen = 0; CK_ULONG total, remain, out_len = 0; char *buffer = NULL; /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* indicate this is multipart operation and get chain info from ctx. * if any mechanisms that cannot do multipart sign come here, they * will not have had ctx->context allocated and will * get an error in switch below. */ ctx->multi = TRUE; if (ctx->context) { multi_part_ctx = (struct icsf_multi_part_context *)ctx->context; if (multi_part_ctx->initiated) memcpy(chain_data, multi_part_ctx->chain_data, chain_data_len); } switch (ctx->mech.mechanism) { case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: rc = icsf_hmac_sign(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, (multi_part_ctx->initiated) ? "MIDDLE":"FIRST", in_data, in_data_len, NULL, &siglen, chain_data, &chain_data_len); if (rc != 0) { TRACE_DEVEL("icsf_hmac_sign failed\n"); rc = icsf_to_ock_err(rc, reason); } else { multi_part_ctx->initiated = TRUE; memcpy(multi_part_ctx->chain_data, chain_data, chain_data_len); } break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_DSA_SHA1: case CKM_ECDSA_SHA1: /* caching data since ICSF wants in multiple of blocksize */ if (multi_part_ctx && multi_part_ctx->data) { total = multi_part_ctx->used_data_len + in_data_len; remain = total % multi_part_ctx->data_len;; /* if not enough to meet blocksize, cache and exit. */ if (total < multi_part_ctx->data_len) { memcpy(multi_part_ctx->data + multi_part_ctx->used_data_len, in_data, in_data_len ); multi_part_ctx->used_data_len += in_data_len; rc = CKR_OK; goto done; } else { /* there is at least 1 block */ out_len = total - remain; /* prepare a buffer to send data in */ if (!(buffer = malloc(out_len))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(buffer, multi_part_ctx->data, multi_part_ctx->used_data_len); memcpy(buffer + multi_part_ctx->used_data_len, in_data, out_len - multi_part_ctx->used_data_len); /* copy remainder of data to ctx * for next time. caching. */ if (remain != 0) memcpy(multi_part_ctx->data, in_data + (in_data_len - remain), remain); multi_part_ctx->used_data_len = remain; } } rc = icsf_hash_signverify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, (multi_part_ctx->initiated) ? "MIDDLE":"FIRST", buffer, out_len, NULL, NULL, chain_data, &chain_data_len, 0); if (rc != 0) { TRACE_DEVEL("icsf_hash_signverify failed\n"); rc = icsf_to_ock_err(rc, reason); } else { multi_part_ctx->initiated = TRUE; memcpy(multi_part_ctx->chain_data, chain_data, chain_data_len); } if (buffer) free(buffer); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } done: if (rc != CKR_OK) free_sv_ctx(ctx); return rc; } CK_RV icsftok_sign_final(SESSION *session, CK_BYTE *signature, CK_ULONG *sig_len) { struct session_state *session_state; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; struct icsf_object_mapping *mapping = NULL; struct icsf_multi_part_context *multi_part_ctx = NULL; CK_BYTE chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); char *buffer = NULL; CK_RV rc = CKR_OK; int hlen, reason; CK_BBOOL length_only = (signature == NULL); /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* get the chain data from ctx */ if (ctx->context) { multi_part_ctx = (struct icsf_multi_part_context *)ctx->context; memcpy(chain_data, multi_part_ctx->chain_data, chain_data_len); } switch (ctx->mech.mechanism) { case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: if (length_only) { hlen = get_signverify_len(ctx->mech); if (hlen < 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } *sig_len = hlen; return CKR_OK; } rc = icsf_hmac_sign(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, multi_part_ctx->initiated ? "LAST":"ONLY", "", 0, signature, sig_len, chain_data, &chain_data_len); if (rc != 0) rc = icsf_to_ock_err(rc, reason); break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_DSA_SHA1: case CKM_ECDSA_SHA1: /* see if any data left in the cache */ if (multi_part_ctx && multi_part_ctx->used_data_len) { if (!(buffer = malloc(multi_part_ctx->used_data_len))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(buffer, multi_part_ctx->data, multi_part_ctx->used_data_len); } rc = icsf_hash_signverify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, multi_part_ctx->initiated ? "LAST":"ONLY", (buffer) ? buffer : NULL, multi_part_ctx->used_data_len, signature, sig_len, chain_data, &chain_data_len, 0); if (rc != 0) { if (length_only && reason == 3003) rc = CKR_OK; else { TRACE_DEVEL("icsf_hash_signverify failed\n"); rc = icsf_to_ock_err(rc, reason); } } if (buffer) free(buffer); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } done: if (rc != CKR_BUFFER_TOO_SMALL && !(rc == CKR_OK && length_only)) free_sv_ctx(ctx); return rc; } CK_RV icsftok_verify_init(SESSION *session, CK_MECHANISM *mech, CK_OBJECT_HANDLE key) { struct session_state *session_state; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; struct icsf_multi_part_context *multi_part_ctx = NULL; struct icsf_object_mapping *mapping = NULL; CK_RV rc = CKR_OK; CK_BBOOL multi = FALSE; CK_BBOOL datacaching = FALSE; CK_MAC_GENERAL_PARAMS *param; /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) return rc; /* Check the mechanism info */ switch (mech->mechanism) { case CKM_RSA_X_509: case CKM_RSA_PKCS: case CKM_DSA: case CKM_ECDSA: /* these do not do multipart and do not require * a mechanism parameter. */ if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } multi = FALSE; break; case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: /* hmacs can do mulitpart and do not require a * mechanism parameter. */ if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } multi = TRUE; break; case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: /* can do mulitpart and take a mech parameter */ param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if (((mech->mechanism == CKM_SSL3_MD5_MAC) && (*param != 16)) || ((mech->mechanism == CKM_SSL3_SHA1_MAC) && (*param != 20))){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } multi = TRUE; break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_DSA_SHA1: case CKM_ECDSA_SHA1: /* these can do mulitpart and require data caching * but do not require a mechanism parameter */ if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } multi = TRUE; datacaching = TRUE; break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } /* Initialize ctx */ free_sv_ctx(ctx); /* Copy mechanism */ if (mech->pParameter == NULL || mech->ulParameterLen == 0) { ctx->mech.ulParameterLen = 0; ctx->mech.pParameter = NULL; } else { ctx->mech.pParameter = malloc(mech->ulParameterLen); if (!ctx->mech.pParameter) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } ctx->mech.ulParameterLen = mech->ulParameterLen; memcpy(ctx->mech.pParameter, mech->pParameter, mech->ulParameterLen); } ctx->mech.mechanism = mech->mechanism; /* If the mechanism supports multipart, prepare ctx */ if (multi) { /* Allocate context for multi-part operations */ if (!(multi_part_ctx = malloc(sizeof(*multi_part_ctx)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } ctx->context_len = sizeof(*multi_part_ctx); ctx->context = (void *) multi_part_ctx; memset(multi_part_ctx, 0, sizeof(*multi_part_ctx)); /* keep a cache to ensure multiple of blocksize * is sent to ICSF. */ if (datacaching) { size_t blocksize; rc = icsf_block_size(mech->mechanism, &blocksize); if (rc != CKR_OK) goto done; multi_part_ctx->data_len = blocksize; multi_part_ctx->data = malloc(multi_part_ctx->data_len); if (!multi_part_ctx->data) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(multi_part_ctx->data, 0, blocksize); } } else { ctx->context_len = 0; ctx->context = NULL; } ctx->key = key; ctx->multi = FALSE; ctx->active = TRUE; done: if (rc != CKR_OK) free_sv_ctx(ctx); return rc; } CK_RV icsftok_verify(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { struct session_state *session_state; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; struct icsf_object_mapping *mapping = NULL; CK_BYTE chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); CK_RV rc = CKR_OK; int reason; if (ctx->multi == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; switch (ctx->mech.mechanism) { case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: rc = icsf_hmac_verify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, "ONLY", in_data, in_data_len, signature, sig_len, chain_data, &chain_data_len); if (rc != 0) rc = icsf_to_ock_err(rc, reason); break; case CKM_RSA_X_509: case CKM_RSA_PKCS: case CKM_DSA: case CKM_ECDSA: rc = icsf_public_key_verify(session_state->ld, &reason, FALSE, &mapping->icsf_object, &ctx->mech, in_data, in_data_len, signature, &sig_len); if (rc != 0) rc = icsf_to_ock_err(rc, reason); break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_DSA_SHA1: case CKM_ECDSA_SHA1: rc = icsf_hash_signverify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, "ONLY", in_data, in_data_len, signature, &sig_len, chain_data, &chain_data_len, 1); if (rc != 0) rc = icsf_to_ock_err(rc, reason); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } done: free_sv_ctx(ctx); return rc; } CK_RV icsftok_verify_update(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len) { struct session_state *session_state; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; struct icsf_object_mapping *mapping = NULL; struct icsf_multi_part_context *multi_part_ctx = NULL; CK_BYTE chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); CK_RV rc = CKR_OK; int reason; CK_ULONG total, remain, out_len = 0; char *buffer = NULL; /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* indicate this is multipart operation and get chain info from ctx. * if any mechanisms that cannot do multipart verify come here, they * will get an error in switch below. */ ctx->multi = TRUE; if (ctx->context) { multi_part_ctx = (struct icsf_multi_part_context *)ctx->context; if (multi_part_ctx->initiated) memcpy(chain_data, multi_part_ctx->chain_data, chain_data_len); } switch (ctx->mech.mechanism) { case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: rc = icsf_hmac_verify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, (multi_part_ctx->initiated) ? "MIDDLE":"FIRST", in_data, in_data_len, "", 0, chain_data, &chain_data_len); if (rc != 0) { TRACE_DEVEL("icsf_hmac_verify failed\n"); rc = icsf_to_ock_err(rc, reason); } else { multi_part_ctx->initiated = TRUE; memcpy(multi_part_ctx->chain_data, chain_data, chain_data_len); } break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_DSA_SHA1: case CKM_ECDSA_SHA1: /* caching data since ICSF wants in multiple of blocksize */ if (multi_part_ctx && multi_part_ctx->data) { total = multi_part_ctx->used_data_len + in_data_len; remain = total % multi_part_ctx->data_len;; /* if not enough to meet blocksize, cache and exit. */ if (total < multi_part_ctx->data_len) { memcpy(multi_part_ctx->data + multi_part_ctx->used_data_len, in_data, in_data_len ); multi_part_ctx->used_data_len += in_data_len; rc = CKR_OK; goto done; } else { /* there is at least 1 block */ out_len = total - remain; /* prepare a buffer to send data in */ if (!(buffer = malloc(out_len))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(buffer, multi_part_ctx->data, multi_part_ctx->used_data_len); memcpy(buffer + multi_part_ctx->used_data_len, in_data, out_len - multi_part_ctx->used_data_len); /* copy remainder of data to ctx * for next time. caching. */ if (remain != 0) memcpy(multi_part_ctx->data, in_data + (in_data_len - remain), remain); multi_part_ctx->used_data_len = remain; } } rc = icsf_hash_signverify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, (multi_part_ctx->initiated) ? "MIDDLE":"FIRST", buffer, out_len, NULL, NULL, chain_data, &chain_data_len, 1); if (rc != 0) { TRACE_DEVEL("icsf_hash_signverify failed\n"); rc = icsf_to_ock_err(rc, reason); } else { multi_part_ctx->initiated = TRUE; memcpy(multi_part_ctx->chain_data, chain_data, chain_data_len); } if (buffer) free(buffer); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } done: if (rc != CKR_OK) free_sv_ctx(ctx); return rc; } CK_RV icsftok_verify_final(SESSION *session, CK_BYTE *signature, CK_ULONG sig_len) { struct session_state *session_state; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; struct icsf_object_mapping *mapping = NULL; struct icsf_multi_part_context *multi_part_ctx = NULL; CK_BYTE chain_data[ICSF_CHAINING_DATA_LEN] = { 0, }; size_t chain_data_len = sizeof(chain_data); CK_RV rc = CKR_OK; int reason; char *buffer = NULL; if (!sig_len) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); if(!(mapping = bt_get_node_value(&objects, ctx->key))) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); if (rc != CKR_OK) goto done; /* get the chain data from ctx */ if (ctx->context) { multi_part_ctx = (struct icsf_multi_part_context *)ctx->context; memcpy(chain_data, multi_part_ctx->chain_data, chain_data_len); } switch (ctx->mech.mechanism) { case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: /* get the chain data */ rc = icsf_hmac_verify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, multi_part_ctx->initiated ? "LAST":"ONLY", "", 0, signature, sig_len, chain_data, &chain_data_len); if (rc != 0) rc = icsf_to_ock_err(rc, reason); break; case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: case CKM_DSA_SHA1: case CKM_ECDSA_SHA1: /* see if any data left in the cache */ if (multi_part_ctx && multi_part_ctx->used_data_len) { if (!(buffer = malloc(multi_part_ctx->used_data_len))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(buffer, multi_part_ctx->data, multi_part_ctx->used_data_len); } rc = icsf_hash_signverify(session_state->ld, &reason, &mapping->icsf_object, &ctx->mech, multi_part_ctx->initiated ? "LAST":"ONLY", (buffer) ? buffer : NULL, multi_part_ctx->used_data_len, signature, &sig_len, chain_data, &chain_data_len, 1); if (rc != 0) rc = icsf_to_ock_err(rc, reason); if (buffer) free(buffer); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } done: free_sv_ctx(ctx); return rc; } /* * Wrap a key and return it as binary data. */ CK_RV icsftok_wrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR p_wrapped_key_len) { int rc; int reason = 0; struct session_state *session_state; struct icsf_object_mapping *wrapping_key_mapping = NULL; struct icsf_object_mapping *key_mapping = NULL; /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); return CKR_FUNCTION_FAILED; } /* Check if keys exist */ pthread_rwlock_rdlock(&obj_list_rw_mutex); wrapping_key_mapping = bt_get_node_value(&objects, wrapping_key); key_mapping = bt_get_node_value(&objects, key); pthread_rwlock_unlock(&obj_list_rw_mutex); if (!wrapping_key_mapping || !key_mapping) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); return CKR_KEY_HANDLE_INVALID; } /* Call ICSF service */ rc = icsf_wrap_key(session_state->ld, &reason, mech, &wrapping_key_mapping->icsf_object, &key_mapping->icsf_object, wrapped_key, p_wrapped_key_len); if (rc) { TRACE_DEVEL("icsf_wrap_key failed\n"); return icsf_to_ock_err(rc, reason); } return CKR_OK; } /* * Unwrap a key from binary data and create a new key object. */ CK_RV icsftok_unwrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE_PTR p_key) { int rc; int reason = 0; struct session_state *session_state; struct icsf_object_mapping *wrapping_key_mapping = NULL; struct icsf_object_mapping *key_mapping = NULL; int is_obj_locked = 0; CK_ULONG node_number; /* Check session */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); return CKR_SESSION_HANDLE_INVALID; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); return CKR_FUNCTION_FAILED; } /* Check if key exists */ pthread_rwlock_rdlock(&obj_list_rw_mutex); wrapping_key_mapping = bt_get_node_value(&objects, wrapping_key); pthread_rwlock_unlock(&obj_list_rw_mutex); if (!wrapping_key_mapping) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); return CKR_KEY_HANDLE_INVALID; } /* Allocate structure to keep ICSF object information */ if (!(key_mapping = malloc(sizeof(*key_mapping)))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(key_mapping, 0, sizeof(*key_mapping)); key_mapping->session_id = session->handle; /* Call ICSF service */ rc = icsf_unwrap_key(session_state->ld, &reason, mech, &wrapping_key_mapping->icsf_object, wrapped_key, wrapped_key_len, attrs, attrs_len, &key_mapping->icsf_object); if (rc) { TRACE_DEVEL("icsf_unwrap_key failed\n"); rc = icsf_to_ock_err(rc, reason); goto done; } /* Lock the object list */ if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Failed to lock mutex.\n"); rc = CKR_FUNCTION_FAILED; goto done; } is_obj_locked = 1; /* Add info about object into session */ if(!(node_number = bt_node_add(&objects, key_mapping))) { TRACE_ERROR("Failed to add object to binary tree.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Use node number as handle */ *p_key = node_number; done: if (is_obj_locked && pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); rc = CKR_FUNCTION_FAILED; } /* If allocated, object must be freed in case of failure */ if (rc && key_mapping) free(key_mapping); return rc; } /* * Derive a key from a base key, creating a new key object. */ CK_RV icsftok_derive_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE hBaseKey, CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len) { CK_RV rc = CKR_OK; struct session_state *session_state; struct icsf_object_mapping *base_key_mapping; CK_ULONG node_number; char token_name[sizeof(nv_token_data->token_info.label)]; CK_SSL3_KEY_MAT_PARAMS *params = {0}; int is_obj_locked = 0; int reason = 0; int i; /* Variable for multiple keys derivation */ int multiple = 0; struct icsf_object_mapping *mappings[4] = { NULL, }; CK_OBJECT_HANDLE *keys[4] = { NULL, }; /* Check type of derivation */ if (mech->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE || mech->mechanism == CKM_TLS_KEY_AND_MAC_DERIVE) { multiple = 1; params = (CK_SSL3_KEY_MAT_PARAMS *) mech->pParameter; keys[0] = ¶ms->pReturnedKeyMaterial->hClientMacSecret; keys[1] = ¶ms->pReturnedKeyMaterial->hServerMacSecret; keys[2] = ¶ms->pReturnedKeyMaterial->hClientKey; keys[3] = ¶ms->pReturnedKeyMaterial->hServerKey; } else { keys[0] = handle; } /* Check permissions based on attributes and session */ rc = check_session_permissions(session, attrs, attrs_len); if (rc != CKR_OK) return rc; /* Copy token name from shared memory */ XProcLock(); memcpy(token_name, nv_token_data->token_info.label, sizeof(token_name)); XProcUnLock(); /* Allocate structure to keep ICSF object information */ for (i = 0; i < sizeof(mappings)/sizeof(*mappings); i++) { if (!(mappings[i] = malloc(sizeof(*mappings[i])))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset(mappings[i], 0, sizeof(*mappings[i])); mappings[i]->session_id = session->handle; /* If not deriving multiple keys, just one key is needed */ if (!multiple) break; } /* Get session state */ if (!(session_state = get_session_state(session->handle))) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* check ldap handle */ if (session_state->ld == NULL) { TRACE_ERROR("No LDAP handle.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Convert the OCK_CK_OBJECT_HANDLE_PTR to ICSF */ pthread_rwlock_rdlock(&obj_list_rw_mutex); base_key_mapping = bt_get_node_value(&objects, hBaseKey); pthread_rwlock_unlock(&obj_list_rw_mutex); if(!base_key_mapping) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; goto done; } /* Call ICSF service */ if (!multiple) rc = icsf_derive_key(session_state->ld, &reason, mech, &base_key_mapping->icsf_object, &mappings[0]->icsf_object, attrs, attrs_len); else rc = icsf_derive_multiple_keys(session_state->ld, &reason, mech, &base_key_mapping->icsf_object, attrs, attrs_len, &mappings[0]->icsf_object, &mappings[1]->icsf_object, &mappings[2]->icsf_object, &mappings[3]->icsf_object, params->pReturnedKeyMaterial->pIVClient, params->pReturnedKeyMaterial->pIVServer); if (rc) { rc = icsf_to_ock_err(rc, reason); goto done; } /* Lock the object list */ if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); rc = CKR_FUNCTION_FAILED; goto done; } is_obj_locked = 1; for (i = 0; i < sizeof(mappings)/sizeof(*mappings); i++) { /* Add info about object into session */ if(!(node_number = bt_node_add(&objects, mappings[i]))) { TRACE_ERROR("Failed to add object to binary tree.\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* Use node number as handle */ *keys[i] = node_number; /* If not deriving multiple keys, just one key is returned */ if (!multiple) break; } done: if (is_obj_locked && pthread_rwlock_unlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Unlock failed.\n"); rc = CKR_FUNCTION_FAILED; } /* If allocated, object must be freed in case of failure */ if (rc) { for (i = 0; i < sizeof(mappings)/sizeof(*mappings); i++) if (mappings[i]) free(mappings[i]); } return rc; } opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/icsf_config_lexer.l0000644000175000017500000003711412630407154023741 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2013 */ %{ #include #include "icsf_config_parse.h" %} %option noyywrap %% [\t\n ]+ { /* Ignore spaces */ } #.*\n { /* Comment */ } slot { /* Identify a definition */ return SLOT; } [0-9]+ { /* Number */ yylval.num = strtoul(yytext, NULL, 10); return INTEGER; } \{ { /* Open definition */ return BEGIN_DEF; } \} { /* Close definition */ return END_DEF; } = { /* Assignment */ return EQUAL; } [^\"= \t\n]+ { /* String */ yylval.str = strdup(yytext); return STRING; } \"[^\"\n]*\" { /* Quoted string */ yylval.str = strdup(yytext + 1); if (yylval.str && yylval.str[0]) yylval.str[strlen(yylval.str) - 1] = '\0'; return STRING; } . { /* Default */ yyerror(yytext); } %% opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/icsf.h0000644000175000017500000002015712630407154021210 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token - LDAP functions * * (C) COPYRIGHT International Business Machines Corp. 2012 * * Author: Marcelo Cerri (mhcerri@br.ibm.com) * */ #ifndef ICSF_H #define ICSF_H #include #include #include "pkcs11types.h" /* OIDs used for PKCS extension */ #define ICSF_REQ_OID "1.3.18.0.2.12.83" #define ICSF_RES_OID "1.3.18.0.2.12.84" /* * Tag numbers for each ICSF call. * * ICSF message is composed by some fields that are common to all services and * a service-specific field. The tag number of this field identifies the * service that is called. */ #define ICSF_TAG_CSFPDMK 1 // Derive Multiple Keys #define ICSF_TAG_CSFPDVK 2 // Derive Key #define ICSF_TAG_CSFPGAV 3 #define ICSF_TAG_CSFPGKP 4 #define ICSF_TAG_CSFPGSK 5 #define ICSF_TAG_CSFPHMG 6 #define ICSF_TAG_CSFPHMV 7 #define ICSF_TAG_CSFPOWH 8 #define ICSF_TAG_CSFPPKS 9 #define ICSF_TAG_CSFPPKV 10 #define ICSF_TAG_CSFPSAV 11 #define ICSF_TAG_CSFPSKD 12 #define ICSF_TAG_CSFPSKE 13 #define ICSF_TAG_CSFPTRC 14 #define ICSF_TAG_CSFPTRD 15 #define ICSF_TAG_CSFPTRL 16 #define ICSF_TAG_CSFPUWK 17 #define ICSF_TAG_CSFPWPK 18 /* Return codes */ #define ICSF_RC_SUCCESS 0 #define ICSF_RC_PARTIAL_SUCCESS 4 #define ICSF_RC_ERROR 8 #define ICSF_RC_FATAL 12 #define ICSF_RC_IS_ERROR(rc) \ ((rc) > ICSF_RC_PARTIAL_SUCCESS || (rc) < 0) /* Reason codes */ #define ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT 3003 /* Default lengths */ #define ICSF_HANDLE_LEN 44 #define ICSF_TOKEN_RECORD_LEN 116 #define ICSF_TOKEN_NAME_LEN 32 #define ICSF_SEQUENCE_LEN 8 #define ICSF_MANUFACTURER_LEN 32 #define ICSF_MODEL_LEN 16 #define ICSF_SERIAL_LEN 16 #define ICSF_DATE_LEN 8 #define ICSF_TIME_LEN 8 #define ICSF_FLAGS_LEN 4 #define ICSF_RULE_ITEM_LEN 8 #define MAX_RECORDS 10 /* Object types */ #define ICSF_SESSION_OBJECT 'S' #define ICSF_TOKEN_OBJECT 'T' #define ICSF_IS_VALID_OBJECT_TYPE(_type) \ (_type == ICSF_SESSION_OBJECT || \ _type == ICSF_TOKEN_OBJECT) /* Chaining types */ #define ICSF_CHAINING_INITIAL 1 #define ICSF_CHAINING_CONTINUE 2 #define ICSF_CHAINING_FINAL 3 #define ICSF_CHAINING_ONLY 4 #define ICSF_CHAINING_IS_VALID(_type) \ (((_type) == ICSF_CHAINING_INITIAL) || \ ((_type) == ICSF_CHAINING_CONTINUE) || \ ((_type) == ICSF_CHAINING_FINAL) || \ ((_type) == ICSF_CHAINING_ONLY)) #define ICSF_CHAINING(_type) \ (((_type) == ICSF_CHAINING_INITIAL) ? "INITIAL" : \ ((_type) == ICSF_CHAINING_CONTINUE) ? "CONTINUE" : \ ((_type) == ICSF_CHAINING_FINAL) ? "FINAL" : \ ((_type) == ICSF_CHAINING_ONLY) ? "ONLY" : \ NULL) #define ICSF_CHAINING_DATA_LEN (128) /* Macros for testing flags. */ #define ICSF_IS_TOKEN_READ_ONLY(_flags) \ (_flags[0] & (1 << 7)) struct icsf_token_record { char name[ICSF_TOKEN_NAME_LEN + 1]; char manufacturer[ICSF_MANUFACTURER_LEN + 1]; char model[ICSF_MODEL_LEN + 1]; char serial[ICSF_SERIAL_LEN + 1]; char date[ICSF_DATE_LEN + 1]; char time[ICSF_TIME_LEN + 1]; char flags[ICSF_FLAGS_LEN]; }; struct icsf_object_record { char token_name[ICSF_TOKEN_NAME_LEN + 1]; unsigned long sequence; char id; }; int icsf_login(LDAP **ld, const char *uri, const char *dn, const char *password); int icsf_sasl_login(LDAP **ld, const char *uri, const char *cert, const char *key, const char *ca, const char *ca_dir); int icsf_logout(LDAP *ld); int icsf_check_pkcs_extension(LDAP *ld); int icsf_create_token(LDAP *ld, int *reason, const char *token_name, const char *manufacturer_id, const char *model, const char *serial_number); int icsf_destroy_token(LDAP *ld, int *reason, char *token_name); int icsf_list_tokens(LDAP *ld, int *reason, struct icsf_token_record *first, struct icsf_token_record *records, size_t *records_len); int icsf_copy_object(LDAP * ld, int *reason, CK_ATTRIBUTE * attrs, CK_ULONG attrs_len, struct icsf_object_record *src, struct icsf_object_record *dst); int icsf_create_object(LDAP *ld, int *reason, const char *token_name, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, struct icsf_object_record *object); int icsf_list_objects(LDAP *ld, int *reason, const char *token_name, CK_ULONG attrs_len, CK_ATTRIBUTE *attrs, struct icsf_object_record *previous, struct icsf_object_record *records, size_t *records_len, int all); int icsf_destroy_object(LDAP *ld, int *reason, struct icsf_object_record *obj); int icsf_generate_secret_key(LDAP *ld, int *reason, const char *token_name, CK_MECHANISM_PTR mech, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, struct icsf_object_record *object); int icsf_derive_key(LDAP *ld, int *reason, CK_MECHANISM_PTR mech, struct icsf_object_record *baseKey, struct icsf_object_record *object, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len); int icsf_generate_key_pair(LDAP *ld, int *reason, const char *token_name, CK_ATTRIBUTE *pub_attrs, CK_ULONG pub_attrs_len, CK_ATTRIBUTE *priv_attrs, CK_ULONG priv_attrs_len, struct icsf_object_record *pub_key_object, struct icsf_object_record *priv_key_object); CK_RV icsf_block_size(CK_MECHANISM_TYPE mech_type, CK_ULONG_PTR p_block_size); int icsf_get_attribute(LDAP *ld, int *reason, struct icsf_object_record *object, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len); int icsf_set_attribute(LDAP *ld, int *reason, struct icsf_object_record *object, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len); int icsf_secret_key_encrypt(LDAP *ld, int *reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, int chaining, const char *clear_text, size_t clear_text_len, char *cipher_text, size_t *p_cipher_text_len, char *chaining_data, size_t *p_chaining_data_len); int icsf_secret_key_decrypt(LDAP *ld, int *reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, int chaining, const char *cipher_text, size_t cipher_text_len, char *clear_text, size_t *p_clear_text_len, char *chaining_data, size_t *p_chaining_data_len); int icsf_private_key_sign(LDAP *ld, int *p_reason, int decrypt, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *cipher_text, size_t cipher_text_len, char *clear_text, size_t *p_clear_text_len); int icsf_public_key_verify(LDAP *ld, int *p_reason, int encrypt, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *clear_text, size_t clear_text_len, char *cipher_text, size_t *p_cipher_text_len); int icsf_hmac_sign(LDAP *ld, int *reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *chain_rule, const char *clear_text, size_t clear_text_len, char *hmac, size_t *hmac_len, char *chain_data, size_t *chain_data_len); int icsf_hmac_verify(LDAP *ld, int *reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *chain_rule, const char *clear_text, size_t clear_text_len, char *hmac, size_t hmac_len, char *chain_data, size_t *chain_data_len); int icsf_wrap_key(LDAP *ld, int *p_reason, CK_MECHANISM_PTR mech, struct icsf_object_record *wrapping_key, struct icsf_object_record *key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR p_wrapped_key_len); int icsf_unwrap_key(LDAP *ld, int *p_reason, CK_MECHANISM_PTR mech, struct icsf_object_record *unwrapping_key, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, struct icsf_object_record *key); int icsf_hash_signverify(LDAP *ld, int *reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *chain_rule, const char *clear_text, unsigned long clear_text_len, char *sig, unsigned long *sig_len, char *chain_data, size_t *chain_data_len, int verify); int icsf_derive_multiple_keys(LDAP *ld, int *p_reason, CK_MECHANISM_PTR mech, struct icsf_object_record *key, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, struct icsf_object_record *client_mac_handle, struct icsf_object_record *server_mac_handle, struct icsf_object_record *client_key_handle, struct icsf_object_record *server_key_handle, unsigned char *client_iv, unsigned char *server_iv); #endif opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/pbkdf.c0000644000175000017500000006443612630407154021355 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2013 */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "pbkdf.h" #include "trace.h" CK_RV get_randombytes(char *output, int bytes) { int ranfd; int rlen; unsigned int totallen = 0; ranfd = open("/dev/urandom",O_RDONLY); if (ranfd >= 0 ) { do { rlen = read(ranfd, output+totallen, bytes-totallen); if (rlen == -1) { close(ranfd); TRACE_ERROR("read failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } totallen += rlen; } while( totallen < bytes); close(ranfd); return CKR_OK; } else return CKR_FUNCTION_FAILED; } CK_RV set_perms(int file) { struct group *grp; if (fchmod(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) { TRACE_ERROR("fchmod failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } grp = getgrnam("pkcs11"); if (grp) { if (fchown(file, -1, grp->gr_gid) != 0) { TRACE_ERROR("fchown failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } } else { TRACE_ERROR("getgrnam failed:%s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } return CKR_OK; } CK_RV encrypt_aes(CK_BYTE *inbuf, int inbuflen, CK_BYTE *dkey, CK_BYTE *iv, CK_BYTE *outbuf, int *outbuflen) { CK_ULONG_32 tmplen; EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher = EVP_aes_256_cbc(); EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit_ex(&ctx, cipher, NULL, dkey, iv); if (!EVP_EncryptUpdate(&ctx, outbuf, outbuflen, inbuf, inbuflen)) { TRACE_ERROR("EVP_EncryptUpdate failed.\n"); return CKR_FUNCTION_FAILED; } if (!EVP_EncryptFinal_ex(&ctx, outbuf+(*outbuflen), &tmplen)) { TRACE_ERROR("EVP_EncryptFinal failed.\n"); return CKR_FUNCTION_FAILED; } *outbuflen = (*outbuflen) + tmplen; EVP_CIPHER_CTX_cleanup(&ctx); return CKR_OK; } CK_RV decrypt_aes(CK_BYTE *inbuf, int inbuflen, CK_BYTE *dkey, CK_BYTE *iv, CK_BYTE *outbuf, int *outbuflen) { int size; EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher = EVP_aes_256_cbc(); EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit_ex(&ctx, cipher, NULL, dkey, iv); if (!EVP_DecryptUpdate(&ctx, outbuf, outbuflen, inbuf, inbuflen)) { TRACE_ERROR("EVP_DecryptUpdate failed.\n"); return CKR_FUNCTION_FAILED; } if (!EVP_DecryptFinal_ex(&ctx, outbuf+(*outbuflen), &size)) { TRACE_ERROR("EVP_DecryptFinal failed.\n"); return CKR_FUNCTION_FAILED; } /* total length of the decrypted data */ *outbuflen = (*outbuflen) + size; /* EVP_DecryptFinal removes any padding. The final length * is the length of the decrypted data without padding. */ EVP_CIPHER_CTX_cleanup(&ctx); return CKR_OK; } CK_RV get_masterkey(CK_BYTE *pin, CK_ULONG pinlen, CK_BYTE *fname, CK_BYTE *masterkey, int *len) { struct stat statbuf; FILE *fp; CK_ULONG_32 totallen, datasize, readsize; int dkeysize; CK_BYTE salt[SALTSIZE]; CK_BYTE dkey[AES_KEY_SIZE_256]; CK_BYTE outbuf[ENCRYPT_SIZE]; CK_RV rc = CKR_OK; size_t ret; /* see if the file exists */ if ((stat(fname, &statbuf) < 0) && (errno = ENOENT)) { TRACE_ERROR("stat() failed: File does not exist.\n"); return CKR_FUNCTION_FAILED; } /* open the file */ fp = fopen(fname, "r"); if (fp == NULL) { TRACE_ERROR("fopen failed\n"); return CKR_FUNCTION_FAILED; } ret = fread(&totallen, sizeof(CK_ULONG_32), 1, fp); if (ret != 1) { fclose(fp); TRACE_ERROR("fread failed.\n"); return CKR_FUNCTION_FAILED; } ret = fread(salt, SALTSIZE, 1, fp); if (ret != 1) { fclose(fp); TRACE_ERROR("fread failed.\n"); return CKR_FUNCTION_FAILED; } /* get length of encryted data */ datasize = totallen - SALTSIZE; readsize = fread(outbuf, datasize, 1, fp); if (readsize != 1) { TRACE_ERROR("Could not get encrypted data in %s.\n", fname); fclose(fp); return CKR_FUNCTION_FAILED; } fclose(fp); /* now derive the key using the salt and PIN */ dkeysize = AES_KEY_SIZE_256; rc = pbkdf(pin, pinlen, salt, dkey, dkeysize); if (rc != CKR_OK) { TRACE_DEBUG("pbkdf(): Failed to derive a key.\n"); return CKR_FUNCTION_FAILED; } /* decrypt the masterkey */ /* re-use salt for iv */ rc = decrypt_aes(outbuf, datasize, dkey, salt, masterkey, len); if (rc != CKR_OK) { TRACE_DEBUG("Failed to decrypt the racf pwd.\n"); return CKR_FUNCTION_FAILED; } /* make sure len is equal to our masterkey size. */ if (*len != AES_KEY_SIZE_256) { TRACE_ERROR("Decrypted key is invalid.\n"); return CKR_FUNCTION_FAILED; } return rc; } CK_RV get_racf(CK_BYTE *masterkey, CK_ULONG mklen, CK_BYTE *racfpwd, int *racflen) { struct stat statbuf; CK_BYTE outbuf[ENCRYPT_SIZE]; CK_BYTE iv[AES_INIT_VECTOR_SIZE]; int len, datasize, readsize; FILE *fp; CK_RV rc; /* see if the file exists ... */ if ((stat(RACFFILE, &statbuf) < 0) && (errno = ENOENT)) { TRACE_ERROR("File does not exist.\n"); return CKR_FUNCTION_FAILED; } /* if file exists, open it */ fp = fopen(RACFFILE, "r"); if (fp == NULL) { TRACE_ERROR("fopen failed\n"); return CKR_FUNCTION_FAILED; } fread(&len, sizeof(CK_ULONG_32), 1, fp); fread(iv, AES_INIT_VECTOR_SIZE, 1, fp); /* get length of encryted data */ datasize = len - AES_INIT_VECTOR_SIZE; readsize = fread(outbuf, datasize, 1, fp); if (readsize != 1) { TRACE_ERROR("Could not get encrypted data in %s.\n",RACFFILE); fclose(fp); return CKR_FUNCTION_FAILED; } fclose(fp); /* decrypt the data using the masterkey */ rc = decrypt_aes(outbuf, datasize, masterkey, iv, racfpwd, racflen); /* terminate the decrypted string. */ memset(racfpwd + (*racflen),0 , 1); if (rc != CKR_OK) { TRACE_DEBUG("Failed to decrypt the racf pwd.\n"); return CKR_FUNCTION_FAILED; } return CKR_OK; } CK_RV pbkdf(CK_BYTE *password, CK_ULONG len, CK_BYTE *salt, CK_BYTE *dkey, CK_ULONG klen) { unsigned char hash[SHA2_HASH_SIZE]; unsigned char hash_block[SHA2_HASH_SIZE]; unsigned char *result; unsigned int r, num_of_blocks; unsigned int count, hashlen; CK_ULONG rc = CKR_OK; int i, j, k; /* check inputs */ if (!password || !salt) { TRACE_ERROR("Invalid function argument(s).\n"); return CKR_FUNCTION_FAILED; } /* check length of key.. for now only 32 byte keys*/ if (klen != DKEYLEN) { TRACE_ERROR("Only support 32 byte keys.\n"); return CKR_FUNCTION_FAILED; } /* SP 800-132 recommends a minimum iteration count of 1000. * so lets try that for now... */ count = 1000; hashlen = SHA2_HASH_SIZE; /* Calculate amount of blocks in klen. * SP 800-132: len = [kLen / hLen] (rounded up). * r = kLen - (len - 1) * hLen; */ if (klen < SHA2_HASH_SIZE) { num_of_blocks = 1; r = klen; } else { num_of_blocks = klen/SHA2_HASH_SIZE; /* round up by adding another block if there is a modulus */ if ((klen % SHA2_HASH_SIZE) != 0) num_of_blocks++; r = klen - (num_of_blocks - 1) * SHA2_HASH_SIZE; } /* SP 800-132: For i = 1 to len */ for (i = 1; i <= num_of_blocks; i++) { /* SP 800-132: Ti = 0; */ memset(hash_block, 0, SHA2_HASH_SIZE); /* SP 800-132: U0 = S || Int(i); */ memset(hash, 0, SHA2_HASH_SIZE); memcpy(hash, salt, SALTSIZE); hash[SALTSIZE] = i; hashlen = SALTSIZE+1; /* SP 800-132: For j = 1 to C */ for (j = 1; j <= count; j++) { /* SP 800-132: Uj = HMAC(P, U(j-1)); */ result = HMAC(EVP_sha256(), password, len, hash, hashlen, NULL, NULL); if (result == NULL) { TRACE_ERROR("Failed to compute the hmac.\n"); rc = CKR_FUNCTION_FAILED; goto out; } /* SP 800-132: Ti = Ti Exclusive_OR Uj; */ for (k = 0; k < SHA2_HASH_SIZE; k++) hash_block[k] ^= hash[k]; /* prep U(j-1) for next iteration */ memcpy(hash, result, SHA2_HASH_SIZE); hashlen = SHA2_HASH_SIZE; } /* SP 800-132: derived_key = * hash_block(1)||hash_block(2)||hash_block(num_of_blocks)<0...r-1> * This means num_of_blocks are needed to concatencate * together to make the derived key. * However, if the derived key length is not a multiple of the * HASH_SIZE, then we only need some of the data in the last hash_block. * So, if there is an r, then only copy r bytes from last hash_block * to the derived_key. */ if ((i == num_of_blocks) && (r != 0)) memcpy(dkey, hash_block, r); else memcpy(dkey, hash_block, SHA2_HASH_SIZE); } out: return rc; } CK_RV secure_racf(CK_BYTE *racf, CK_ULONG racflen, CK_BYTE *key, CK_ULONG keylen) { CK_RV rc = CKR_OK; CK_BYTE iv[AES_INIT_VECTOR_SIZE]; FILE *fp; CK_BYTE output[ENCRYPT_SIZE]; CK_ULONG_32 totallen, outputlen; /* generate an iv... */ if ((get_randombytes(iv, AES_INIT_VECTOR_SIZE)) != CKR_OK) { TRACE_DEBUG("Could not generate an iv.\n"); return CKR_FUNCTION_FAILED; } /* encrypt the racf passwd using the masterkey */ rc = encrypt_aes(racf, racflen, key, iv, output, &outputlen); if (rc != 0) { TRACE_DEBUG("Failed to encrypt racf pwd.\n"); return CKR_FUNCTION_FAILED; } /* store the following in the RACF file: * 1. total length = v + encrypted data * 2. iv * 3. encrypted data */ /* get the total length */ totallen = outputlen + AES_INIT_VECTOR_SIZE; fp = fopen(RACFFILE, "w"); if (!fp) { TRACE_ERROR("fopen failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } /* set permisions on the file */ rc = set_perms(fileno(fp)); if (rc != 0) { TRACE_ERROR("Failed to set permissions on RACF file.\n"); fclose(fp); return CKR_FUNCTION_FAILED; } /* write the info to the file */ (void)fwrite(&totallen, sizeof(CK_ULONG_32), 1, fp); (void)fwrite(iv, AES_INIT_VECTOR_SIZE, 1, fp); (void)fwrite(output, outputlen, 1, fp); fclose(fp); return rc; } CK_RV secure_masterkey(CK_BYTE *masterkey, CK_ULONG len, CK_BYTE *pin, CK_ULONG pinlen, CK_BYTE *fname) { CK_RV rc = CKR_OK; CK_BYTE salt[SALTSIZE]; CK_BYTE dkey[AES_KEY_SIZE_256]; CK_ULONG_32 totallen, dkey_size; int outputlen; CK_BYTE output[ENCRYPT_SIZE]; FILE *fp; memset(salt, 0, SALTSIZE); memset(dkey, 0, AES_KEY_SIZE_256); dkey_size = AES_KEY_SIZE_256; /* get a salt for the password based key derivation function. */ if ((get_randombytes(salt, SALTSIZE)) != CKR_OK) { TRACE_DEBUG("Could not get a salt for pbkdf.\n"); return CKR_FUNCTION_FAILED; } /* get a 32 byte key */ rc = pbkdf(pin, pinlen, salt, dkey, dkey_size); if (rc != 0) { TRACE_DEBUG("Failed to derive a key for encryption.\n"); return CKR_FUNCTION_FAILED; } /* encrypt the masterkey using the derived key */ /* re-use the salt for the iv... */ rc = encrypt_aes(masterkey, len, dkey, salt, output, &outputlen); if (rc != 0) { TRACE_DEBUG("Failed to encrypt masterkey.\n"); return CKR_FUNCTION_FAILED; } /* write the encrypted masterkey to named file */ /* store the following: * 1. total length = salt + encrypted data * 2. salt (always SALTSIZE) * 3. encrypted data */ /* get the total length */ totallen = outputlen + SALTSIZE; fp = fopen(fname, "w"); if (!fp) { TRACE_ERROR("fopen failed: %s\n", strerror(errno)); return CKR_FUNCTION_FAILED; } /* set permisions on the file */ rc = set_perms(fileno(fp)); if (rc != 0) { TRACE_ERROR("Failed to set permissions on encrypted file.\n"); fclose(fp); return CKR_FUNCTION_FAILED; } /* write the info to the file */ (void)fwrite(&totallen, sizeof(CK_ULONG_32), 1, fp); (void)fwrite(salt, SALTSIZE, 1, fp); (void)fwrite(output, outputlen, 1, fp); fclose(fp); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/icsf_config.h0000644000175000017500000003677612630407154022553 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2013 */ #ifndef ICSF_CONFIG_H #define ICSF_CONFIG_H #include #include "pkcs11types.h" #include "icsf.h" #define ICSF_CFG_MECH_SIMPLE 0 #define ICSF_CFG_MECH_SASL 1 /* ICSF specific slot data */ struct icsf_config { char name[ICSF_TOKEN_NAME_LEN + 1]; char manuf[ICSF_MANUFACTURER_LEN + 1]; char model[ICSF_MODEL_LEN + 1]; char serial[ICSF_SERIAL_LEN + 1]; char uri[PATH_MAX + 1]; char dn[NAME_MAX + 1]; char ca_file[PATH_MAX + 1]; char cert_file[PATH_MAX + 1]; char key_file[PATH_MAX + 1]; int mech; }; CK_RV parse_config_file(const char *conf_name, CK_SLOT_ID slot_id, struct icsf_config *data); #endif opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/icsf_specific.h0000644000175000017500000001064412630407154023055 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token - ICSF token functions * * (C) COPYRIGHT International Business Machines Corp. 2015 * */ #ifndef ICSF_SPECIFIC_H #define ICSF_SPECIFIC_H #include "pkcs11types.h" CK_RV icsftok_init(CK_SLOT_ID slot_id, char *conf_name); CK_RV icsftok_close_all_sessions(void); CK_RV icsftok_init_token(CK_SLOT_ID slot_id, CK_CHAR_PTR pin, CK_ULONG pin_len, CK_CHAR_PTR label); CK_RV icsftok_init_pin(SESSION *sess, CK_CHAR_PTR pPin, CK_ULONG ulPinLen); CK_RV icsftok_set_pin(SESSION *sess, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen); CK_RV icsftok_open_session(SESSION *sess); CK_RV icsftok_close_session(SESSION *session); CK_RV icsftok_login(SESSION *sess, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen); CK_RV icsftok_create_object(SESSION *session, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle); CK_RV icsftok_copy_object(SESSION * session, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE src, CK_OBJECT_HANDLE_PTR dst); CK_RV icsftok_destroy_object(SESSION *sess, CK_OBJECT_HANDLE handle); CK_RV icsftok_get_attribute_value(SESSION *sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount); CK_RV icsftok_set_attribute_value(SESSION *sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount); CK_RV icsftok_find_objects_init(SESSION *sess, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount); CK_RV icsftok_encrypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key); CK_RV icsftok_encrypt(SESSION *session, CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len); CK_RV icsftok_encrypt_update(SESSION *session, CK_BYTE_PTR input_part, CK_ULONG input_part_len, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len); CK_RV icsftok_encrypt_final(SESSION *session, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len); CK_RV icsftok_decrypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key); CK_RV icsftok_decrypt(SESSION *session, CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len); CK_RV icsftok_decrypt_update(SESSION *session, CK_BYTE_PTR input_part, CK_ULONG input_part_len, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len); CK_RV icsftok_decrypt_final(SESSION *session, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len); CK_RV icsftok_sign_init(SESSION *session, CK_MECHANISM *mech, CK_OBJECT_HANDLE key); CK_RV icsftok_sign(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG *sig_len); CK_RV icsftok_sign_update(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV icsftok_sign_final(SESSION *session, CK_BYTE *signature, CK_ULONG *sig_len); CK_RV icsftok_verify_init(SESSION *session, CK_MECHANISM *mech, CK_OBJECT_HANDLE key); CK_RV icsftok_verify(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len); CK_RV icsftok_verify_update(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV icsftok_verify_final(SESSION *session, CK_BYTE *signature, CK_ULONG sig_len); CK_RV icsftok_wrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR p_wrapped_key_len); CK_RV icsftok_unwrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE_PTR p_key); CK_RV icsftok_derive_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE hBaseKey, CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len); CK_RV icsftok_generate_key_pair(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR pub_attrs, CK_ULONG pub_attrs_len, CK_ATTRIBUTE_PTR priv_attrs, CK_ULONG priv_attrs_len, CK_OBJECT_HANDLE_PTR p_pub_key, CK_OBJECT_HANDLE_PTR p_priv_key); CK_RV icsftok_generate_key(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle); CK_RV icsf_get_handles(CK_SLOT_ID slot_id); #endif opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/pbkdf.h0000644000175000017500000000250412630407154021346 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token - LDAP functions * * (C) COPYRIGHT International Business Machines Corp. 2012 * * Author: Joy Latten (jmlatten@linux.vnet.ibm.com) * */ #ifndef PBKDF_H #define PBKDF_H #define SALTSIZE 16 // salt is 16 bytes #define DKEYLEN 32 // 256 bytes is max key size to be derived #define PIN_SIZE 80 // samedefine in pkcsconf #define ENCRYPT_SIZE 96 // PIN_SIZE + AES_BLOCK_SIZE (for padding) #define ICSF_CONFIG_PATH CONFIG_PATH "/icsf" #define RACFFILE ICSF_CONFIG_PATH "/RACF" CK_RV get_randombytes(char *output, int bytes); CK_RV encrypt_aes(CK_BYTE *racfpwd, int racflen, CK_BYTE *dkey, CK_BYTE *iv, CK_BYTE *outbuf, int *outbuflen); CK_RV decrypt_aes(CK_BYTE *edata, int edatalen, CK_BYTE *dkey, CK_BYTE *iv, CK_BYTE *ddata, int *ddatalen); CK_RV get_racf(CK_BYTE *mk, CK_ULONG mklen, CK_BYTE *racfpwd, int *racflen); CK_RV get_masterkey(CK_BYTE *pin, CK_ULONG pinlen, CK_BYTE *fname, CK_BYTE *mk, int *mklen); CK_RV pbkdf(CK_BYTE *passwd, CK_ULONG passwdlen, CK_BYTE *salt, CK_BYTE *dkey, CK_ULONG klen); CK_RV secure_racf(CK_BYTE *racfpwd, CK_ULONG racflen, CK_BYTE *mk, CK_ULONG mklen); CK_RV secure_masterkey(CK_BYTE *masterkey, CK_ULONG len, CK_BYTE *pin, CK_ULONG pinlen, CK_BYTE *fname); #endif opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/icsf.c0000644000175000017500000025310312630407154021202 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token - LDAP functions * * (C) COPYRIGHT International Business Machines Corp. 2012 * * Author: Marcelo Cerri (mhcerri@br.ibm.com) * Eduardo Otubo (eotubo@br.ibm.com) * */ #define _GNU_SOURCE #include #include #include #include #include #include "icsf.h" /* For logging functions: */ #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" /* * Note about ICSF callable services: * * Any ICSF service uses a base data structure containing some common fields. * This base structure is described by the following ASN.1 definition: * * requestValue ::= SEQUENCE { * version INTEGER, * exitData OCTET STRING, * handle OCTET STRING, * ruleArraySeq RuleArraySeq, * requestData CSFPInput * } * * RuleArraySeq ::= SEQUENCE { * ruleArrayCount INTEGER, * ruleArray OCTET STRING * } * * CSFPInput ::= CHOICE { * IQF [CSFIQF] IQFInput, * DMK [CSFPDMK] DMKInput, * DVK [CSFPDVK] DVKInput, * GAV [CSFPGAV] GAVInput, * GKP [CSFPGKP] GKPInput, * GSK [CSFPGSK] GSKInput, * HMG [CSFPHMG] HMGInput, * HMV [CSFPHMV] HMVInput, * OWH [CSFPOWH] OWHInput, * PKS [CSFPPKS] PKSInput, * PKV [CSFPPKV] PKVInput, * SAV [CSFPSAV] SAVInput, * SKD [CSFPSKD] SKDInput, * SKE [CSFPSKE] SKEInput, * TRC [CSFPTRC] TRCInput, * TRD [CSFPTRD] TRDInput, * TRL [CSFPTRL] TRLInput, * UWK [CSFPUWK] UWKInput, * WPK [CSFPWPK] WPKInput, * GLDTRD [GLDTRD] GLDTRDInput, * IQA [CSFIQA] IQAInput * } * * CSFPInput defines which service is being called. A different tag number * and data structure is defined for each service. * * In the same way, the output is also based on a common data structure. * * responseValue ::= SEQUENCE { * version INTEGER, * ICSFRc INTEGER (0 .. MaxCSFPInteger), * ICSFRsnCode INTEGER (0 .. MaxCSFPInteger), * exitData OCTET STRING, * handle OCTET STRING, * responseData CSFPOutput * } * * CSFPOutput ::= CHOICE { * IQF [CSFIQF] IQFOutput, * DMK [CSFPDMK] DMKOutput, * DVK [CSFPDVK] DVKOutput, * GAV [CSFPGAV] GAVOutput, * GKP [CSFPGKP] GKPOutput, * GSK [CSFPGSK] GSKOutput, * HMG [CSFPHMG] HMGOutput, * HMV [CSFPHMV] HMVOutput, * OWH [CSFPOWH] OWHOutput, * PKS [CSFPPKS] PKSOutput, * PKV [CSFPPKV] PKVOutput, * SAV [CSFPSAV] SAVOutput, * SKD [CSFPSKD] SKDOutput, * SKE [CSFPSKE] SKEOutput, * TRC [CSFPTRC] TRCOutput, * TRD [CSFPTRD] TRDOutput, * TRL [CSFPTRL] TRLOutput, * UWK [CSFPUWK] UWKOutput, * WPK [CSFPWPK] WPKOutput, * GLDTRD [GLDTRD] GLDTRDOutput, * IQA [CSFIQA] IQAOutput * } * * ICSFRc is the return code: 0 indicates success, 4 partial success and * values greater than 4 indicates an error. ICSFRsnCode is the reason code * that provides further details about an error. */ /* Macros for argument checking */ #define CHECK_ARG_NON_NULL(_arg) \ if (_arg == NULL) { \ TRACE_ERROR("Null argument \"%s\".\n", #_arg); \ return -1; \ } #define CHECK_ARG_MAX_LEN(_arg, _length) \ if (_arg && (strlen(_arg) > _length)) { \ TRACE_ERROR("String too long %s=\"%s\"\n", \ #_arg, _arg); \ return -1; \ } #define CHECK_ARG_NON_NULL_AND_MAX_LEN(_arg, _length) \ CHECK_ARG_NON_NULL(_arg); \ CHECK_ARG_MAX_LEN(_arg, _length); /* * Copy a null terminated string from `orig` to the buffer `dest` of length * `len` and fill the remaining bytes with `padding_char`. The result string is * not null terminated. */ static void strpad(char *dest, const char *orig, size_t len, int padding_char) { size_t str_len = strlen(orig); if (str_len > len) str_len = len; memcpy(dest, orig, str_len); if ((len - str_len) > 0) memset(dest + str_len, ' ', len - str_len); } /* Copy a string `orig` of length `len` and padded with `padding_char` to a null * terminated string `dest`. `dest` should be at least `len` + 1 bytes long. */ static void strunpad(char *dest, const char *orig, size_t len, int padding_char) { size_t i; for (i = len - 1; i; i--) if (orig[i - 1] != padding_char) break; strncpy(dest, orig, i); dest[i] = '\0'; } /* * Build a token handle based on token name. * * `handle` must be at least ICSF_HANDLE_LEN long. */ static void token_name_to_handle(char *handle, const char *token_name) { /* The first 32 bytes of `handle` specifies the token's name, the * remaining bytes should be blank. */ strpad(handle, token_name, ICSF_TOKEN_NAME_LEN, ' '); memset(handle + ICSF_TOKEN_NAME_LEN, ' ', ICSF_HANDLE_LEN - ICSF_TOKEN_NAME_LEN); } /* * Parse a structure object record to a handle. * * `data` must be at least ICSF_HANDLE_LEN long. */ void object_record_to_handle(char *data, const struct icsf_object_record *record) { /* * Object handle is composed by token name, sequence number * converted to hexadecimal and ID padded with blanks. */ size_t offset = 0; char hex_seq[ICSF_SEQUENCE_LEN + 1]; strpad(data + offset, record->token_name, ICSF_TOKEN_NAME_LEN, ' '); offset += ICSF_TOKEN_NAME_LEN; snprintf(hex_seq, sizeof(hex_seq), "%0*lX", ICSF_SEQUENCE_LEN, record->sequence); memcpy(data + offset, hex_seq, ICSF_SEQUENCE_LEN); offset += ICSF_SEQUENCE_LEN; memset(data + offset, ' ', ICSF_HANDLE_LEN - offset); data[offset] = record->id; } /* * Parse a raw object handle into token name, sequence and object type. */ void handle_to_object_record(struct icsf_object_record *record, const char *data) { size_t offset = 0; char hex_seq[ICSF_SEQUENCE_LEN + 1]; strunpad(record->token_name, data + offset, ICSF_TOKEN_NAME_LEN + 1, ' '); offset += ICSF_TOKEN_NAME_LEN; memcpy(hex_seq, data + offset, ICSF_SEQUENCE_LEN); hex_seq[ICSF_SEQUENCE_LEN] = '\0'; sscanf(hex_seq, "%lx", &record->sequence); offset += ICSF_SEQUENCE_LEN; record->id = data[offset]; } /* * Ensure that LDAPv3 is used. V3 is needed for extended operations. */ static int icsf_force_ldap_v3(LDAP *ld) { int rc; int version = 0; CHECK_ARG_NON_NULL(ld); rc = ldap_get_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version); if (rc != LDAP_OPT_SUCCESS) { TRACE_ERROR("Failed to get LDAP version: %s (%d)\n", ldap_err2string(rc), rc); return -1; } if (version < LDAP_VERSION3) { TRACE_INFO("Changing version from %d to %d.\n", version, LDAP_VERSION3); version = LDAP_VERSION3; rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version); if (rc != LDAP_OPT_SUCCESS) { TRACE_ERROR("Failed to set LDAP version: %s (%d)\n", ldap_err2string(rc), rc); return -1; } } return 0; } /* * Perform a simple bind to `uri` using `dn` and `password` as credentials. */ int icsf_login(LDAP **ld, const char *uri, const char *dn, const char *password) { int rc; struct berval cred; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(password); /* Handle empty and null string in the same way */ uri = (uri && uri[0]) ? uri : NULL; dn = (dn && dn[0]) ? dn : NULL; /* Connect to LDAP server */ TRACE_DEVEL("Connecting to: %s\n", uri ? uri : "(null)"); rc = ldap_initialize(ld, uri); if (rc != LDAP_SUCCESS) { TRACE_ERROR("Failed to connect to \"%s\": %s (%d)\n", uri ? uri : "(null)", ldap_err2string(rc), rc); return -1; } if (icsf_force_ldap_v3(*ld)) return -1; TRACE_DEVEL("Binding with DN: %s\n", dn ? dn : "(null)"); cred.bv_len = strlen(password); cred.bv_val = (char *) password; rc = ldap_sasl_bind_s(*ld, dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL); if (rc != LDAP_SUCCESS) { TRACE_ERROR("LDAP bind failed: %s (%d)\n", ldap_err2string(rc), rc); return -1; } return 0; } /* * Set the paths for private key, certificate and CA, which are used for * SASL authentication using external certificate. * * TODO: check why these options just work as globals (ld == NULL) */ static int icsf_set_sasl_params(LDAP *ld, const char *cert, const char *key, const char *ca, const char *ca_dir) { int rc; CHECK_ARG_NON_NULL(ld); TRACE_DEVEL("Preparing environment for TLS\n"); if (cert && *cert) { TRACE_DEVEL("Using certificate: %s\n", cert); rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE, cert); if (rc != LDAP_SUCCESS) { TRACE_ERROR("Failed to set certificate file for TLS: " "%s (%d)\n", ldap_err2string(rc), rc); return -1; } } if (key && *key) { TRACE_DEVEL("Using private key: %s\n", key); rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_KEYFILE, key); if (rc != LDAP_SUCCESS) { TRACE_ERROR("Failed to set key file for TLS: " "%s (%d)\n", ldap_err2string(rc), rc); return -1; } } if (ca && *ca) { TRACE_DEVEL("Using CA certificate file: %s\n", ca); rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ca); if (rc != LDAP_SUCCESS) { TRACE_ERROR("Failed to set CA certificate file for TLS:" " %s (%d)\n", ldap_err2string(rc), rc); return -1; } } if (ca_dir && *ca_dir) { TRACE_DEVEL("Using CA certificate dir: %s\n", ca_dir); rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR, ca_dir); if (rc != LDAP_SUCCESS) { TRACE_ERROR("Failed to set CA certificate dir for TLS: " "%s (%d)\n", ldap_err2string(rc), rc); return -1; } } return 0; } /* * Perform a SASL bind to `uri` using the given certificate, private key * and CA paths. */ int icsf_sasl_login(LDAP **ld, const char *uri, const char *cert, const char *key, const char *ca, const char *ca_dir) { int rc; CHECK_ARG_NON_NULL(ld); /* Handle empty and null string in the same way */ uri = (uri && uri[0]) ? uri : NULL; /* Connect to LDAP server */ TRACE_DEVEL("Connecting to: %s\n", uri ? uri : "(null)"); rc = ldap_initialize(ld, uri); if (rc != LDAP_SUCCESS) { TRACE_ERROR("Failed to connect to \"%s\": %s (%d)\n", uri ? uri : "(null)", ldap_err2string(rc), rc); return -1; } if (icsf_force_ldap_v3(*ld)) return -1; /* Initialize TLS */ if (icsf_set_sasl_params(*ld, cert, key, ca, ca_dir)) return -1; TRACE_DEVEL("Binding\n"); rc = ldap_sasl_bind_s(*ld, NULL, "EXTERNAL", NULL, NULL, NULL, NULL); if (rc != LDAP_SUCCESS) { char *ext_msg = NULL; ldap_get_option(*ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &ext_msg); TRACE_ERROR("LDAP bind failed: %s (%d)%s%s\n", ldap_err2string(rc), rc, ext_msg ? "\nDetailed message: " : "", ext_msg ? ext_msg : ""); if (ext_msg) ldap_memfree(ext_msg); return -1; } return 0; } /* * Disconnect from the server. */ int icsf_logout(LDAP *ld) { int rc; CHECK_ARG_NON_NULL(ld); rc = ldap_unbind_ext_s(ld, NULL, NULL); if (rc != LDAP_SUCCESS) { TRACE_ERROR("Failed to unbind: %s (%d)\n", ldap_err2string(rc), rc); return -1; } return 0; } /* * Check if the ICSF LDAP extension is supported by the server. */ int icsf_check_pkcs_extension(LDAP *ld) { int rc = -1; int ret; LDAPMessage *res = NULL; LDAPMessage *entry = NULL; BerElement *ber = NULL; char *attr = NULL; char expected_attr[] = "supportedextension"; char *attr_list[] = { expected_attr, NULL }; const char *expected_oid = ICSF_REQ_OID; CHECK_ARG_NON_NULL(ld); /* Search root DSE. */ ret = ldap_search_ext_s(ld, "", /* Base DN */ LDAP_SCOPE_BASE, /* Scope */ "(objectclass=*)", /* Filter */ attr_list, /* Attribute list */ 0, /* Attributes only */ NULL, /* Server controls */ NULL, /* Client controls */ NULL, /* Timeout */ 0, /* Size limit */ &res); if (ret) goto cleanup; /* It should contain just one entry */ entry = ldap_first_entry(ld, res); if (entry == NULL) goto cleanup; /* Loop through attributes */ attr = ldap_first_attribute(ld, entry, &ber); while (attr) { if (!strcmp(expected_attr, attr)) { /* Get the value for each attribute */ struct berval **it; struct berval **values = ldap_get_values_len(ld, entry, attr); if (values == NULL) goto cleanup; /* Print each value */ for (it = values; *it; it++) if (!strncmp(expected_oid, (*it)->bv_val, strlen(expected_oid))) { /* It's supported */ rc = 0; } ldap_value_free_len(values); if (rc == 0) goto cleanup; } /* Get next attribute */ ldap_memfree(attr); attr = ldap_next_attribute(ld, entry, ber); } /* Not supported. */ rc = 1; cleanup: if (attr) ldap_memfree(attr); if (ber) ber_free(ber, 0); if (res) ldap_msgfree(res); return rc; } /* * `icsf_call` is a generic helper function for ICSF services. * * Every request message to an ICSF service has some common fields and a * specific field that depends on the service that is called. The structure of * this field differs for each service and it's also marked with a specific tag * that identifies the service. * * `handle` identifies a token or object. It should be always 44 bytes long. * * `reason` returns the ICSF reason code. It's ignored when NULL. * * `rule_array` should be a sequence of 8 bytes strings padded with blanks. Each * 8 bytes is an item and can change the behaviour of a call. * * `tag` identifies the ICSF service. * * `specific` is the service-specific field of the request message. A NULL value * indicates an empty field. * * `result` points to the service-specific part of the response message. If a * non-NULL value is given, the caller must free it. */ static int icsf_call(LDAP *ld, int *reason, char *handle, size_t handle_len, const char *rule_array, size_t rule_array_len, ber_tag_t tag, BerElement *specific, BerElement **result) { int rc; BerElement *ber_req = NULL; BerElement *ber_res = NULL; struct berval *raw_req = NULL; struct berval *raw_res = NULL; struct berval *raw_specific = NULL; char *response_oid = NULL; /* Variables used as input */ int version = 1; char *exit_data = ""; /* Ignored */ int rule_array_count; /* Variables used as output */ int return_code = 0; int reason_code = 0; struct berval *out_handle = NULL; /* Check sizes */ if (handle_len != ICSF_HANDLE_LEN) { TRACE_ERROR("Invalid handle length: %lu\n", handle_len); return -1; } if ((rule_array_len % ICSF_RULE_ITEM_LEN)) { TRACE_ERROR("Invalid rule array length: %lu\n", rule_array_len); return -1; } rule_array_count = rule_array_len / ICSF_RULE_ITEM_LEN; /* Allocate ber_req to encode message. */ ber_req = ber_alloc_t(LBER_USE_DER); if (ber_req == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = -1; goto cleanup; } if (specific) { rc = ber_flatten(specific, &raw_specific); if (rc) { TRACE_ERROR("Failed to flatten specific data.\n"); rc = -1; goto cleanup; } } /* Encode message: * * requestValue ::= SEQUENCE { * version INTEGER, * exitData OCTET STRING, * handle_len OCTET STRING, * ruleArraySeq RuleArraySeq, * requestData CSFPInput * } * * RuleArraySeq ::= SEQUENCE { * ruleArrayCount INTEGER, * ruleArray OCTET STRING * } * * CSFPInput ::= CHOICE { * IQF [CSFIQF] IQFInput, * DMK [CSFPDMK] DMKInput, * DVK [CSFPDVK] DVKInput, * GAV [CSFPGAV] GAVInput, * GKP [CSFPGKP] GKPInput, * GSK [CSFPGSK] GSKInput, * HMG [CSFPHMG] HMGInput, * HMV [CSFPHMV] HMVInput, * OWH [CSFPOWH] OWHInput, * PKS [CSFPPKS] PKSInput, * PKV [CSFPPKV] PKVInput, * SAV [CSFPSAV] SAVInput, * SKD [CSFPSKD] SKDInput, * SKE [CSFPSKE] SKEInput, * TRC [CSFPTRC] TRCInput, * TRD [CSFPTRD] TRDInput, * TRL [CSFPTRL] TRLInput, * UWK [CSFPUWK] UWKInput, * WPK [CSFPWPK] WPKInput, * GLDTRD [GLDTRD] GLDTRDInput, * IQA [CSFIQA] IQAInput * } */ tag |= LBER_CLASS_CONTEXT | LBER_CONSTRUCTED; rc = ber_printf(ber_req, "{iso{io}to}", version, exit_data, handle, handle_len, rule_array_count, rule_array, rule_array_len,tag, (raw_specific) ? raw_specific->bv_val : "", (raw_specific) ? raw_specific->bv_len : 0); if (rc < 0) { TRACE_ERROR("Failed to encode message.\n"); rc = -1; goto cleanup; } rc = ber_flatten(ber_req, &raw_req); if (rc) { TRACE_ERROR("Failed to flatten BER data.\n"); rc = -1; goto cleanup; } /* Call ICSF service */ rc = ldap_extended_operation_s(ld, ICSF_REQ_OID, raw_req, NULL, NULL, &response_oid, &raw_res); if (rc != LDAP_SUCCESS) { char *ext_msg = NULL; ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &ext_msg); TRACE_ERROR("ICSF call failed: %s (%d)%s%s\n", ldap_err2string(rc), rc, ext_msg ? "\nDetailed message: " : "", ext_msg ? ext_msg : ""); if (ext_msg) ldap_memfree(ext_msg); rc = -1; goto cleanup; } /* Decode result */ ber_res = ber_init(raw_res); if (ber_res == NULL) { TRACE_ERROR("Failed to create a response buffer\n"); rc = -1; goto cleanup; } /* Decode common response fields: */ rc = ber_scanf(ber_res, "{iiixO", &version, &return_code, &reason_code, &out_handle); if (rc < 0) { TRACE_ERROR("Failed to decode message.\n"); rc = -1; goto cleanup; } /* Copy handle */ if (out_handle == NULL) { memset(handle, 0, handle_len); } else { size_t len = (handle_len < out_handle->bv_len) ? handle_len : out_handle->bv_len; memcpy(handle, out_handle->bv_val, len); memset(handle + len, 0, handle_len - len); } TRACE_DEVEL("ICSF call result: %d (%d)\n", return_code, reason_code); if (ICSF_RC_IS_ERROR(return_code)) { TRACE_ERROR("ICSF call failed: %d (%d)\n", return_code, reason_code); } rc = return_code; cleanup: if (reason) *reason = reason_code; if (result) *result = ber_res; else if (ber_res) ber_free(ber_res, 1); if (ber_req) ber_free(ber_req, 1); if (raw_req) ber_bvfree(raw_req); if (raw_res) ber_bvfree(raw_res); if (response_oid) ldap_memfree(response_oid); if (out_handle) ber_bvfree(out_handle); if (raw_specific) ber_bvfree(raw_specific); return rc; } /* * Create a new token. All parameters must be null terminated strings. */ int icsf_create_token(LDAP *ld, int *reason, const char *token_name, const char *manufacturer, const char *model, const char *serial) { int rc = -1; char handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; char attribute_list[68] = { 0, }; BerElement *msg= NULL; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL_AND_MAX_LEN(token_name, ICSF_TOKEN_NAME_LEN); CHECK_ARG_NON_NULL_AND_MAX_LEN(manufacturer, ICSF_MANUFACTURER_LEN); CHECK_ARG_NON_NULL_AND_MAX_LEN(model, ICSF_MODEL_LEN); CHECK_ARG_NON_NULL_AND_MAX_LEN(serial, ICSF_SERIAL_LEN); token_name_to_handle(handle, token_name); /* Should be 8 bytes padded. It's a token creation and if the token * already exists it is recreated. */ strpad(rule_array, "TOKEN", ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + ICSF_RULE_ITEM_LEN, "RECREATE", ICSF_RULE_ITEM_LEN, ' '); /* For token creation, handle is composed by 32 bytes for manufacturer * id, 16 bytes for model, 16 bytes for serial number, and 4 trailing * bytes with zeros. */ strpad(attribute_list, manufacturer, ICSF_MANUFACTURER_LEN, ' '); strpad(attribute_list + ICSF_MANUFACTURER_LEN, model, ICSF_MODEL_LEN, ' '); strpad(attribute_list + ICSF_MANUFACTURER_LEN + ICSF_MODEL_LEN, serial, ICSF_SERIAL_LEN, ' '); /* Allocate ber_req to encode message. */ msg = ber_alloc_t(LBER_USE_DER); if (msg == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto cleanup; } /* Encode message: * * TRCInput ::= SEQUENCE { * trcAttrs ::= CHOICE { * tokenAttrString [0] OCTET STRING, * } * } */ rc = ber_printf(msg, "to", 0 | LBER_CLASS_CONTEXT, attribute_list, sizeof(attribute_list)); if (rc < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } rc = icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPTRC, msg, NULL); cleanup: if (msg) ber_free(msg, 1); return rc; } /* * Destroy a token. */ int icsf_destroy_token(LDAP *ld, int *reason, char *token_name) { /* Variables used as input */ char handle[ICSF_HANDLE_LEN]; char rule_array[1 * ICSF_RULE_ITEM_LEN]; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL_AND_MAX_LEN(token_name, ICSF_TOKEN_NAME_LEN); token_name_to_handle(handle, token_name); /* Should be 8 bytes padded. */ strpad(rule_array, "TOKEN", ICSF_RULE_ITEM_LEN, ' '); /* * CSFPTRD service is used to destroy a token or an object. Handle * indicates the token or object that must be destroyed and no * additional data is needed. */ return icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPTRD, NULL, NULL); } /* * Parse a sequence of bytes `data` returned by a CSFPTRL call containing the * attributes of a token and store the parsed value in the structure `record`. * * The data is formated as the following: * - 32 bytes for token name; * - 32 bytes for manufacturer name; * - 16 bytes for model identification; * - 16 bytes for serial number; * - 8 bytes for date in UTC of the last change encoded as a string in the * format "yyyymmdd". * - 8 bytes for time in UTC of the last change encoded as a string in the * format "hhmmssth". * - 4 bytes of flags (the first bit of the first byte indicate that the * token is write protected). */ static void parse_token_record(struct icsf_token_record *record, const char *data) { size_t offset = 0; strunpad(record->name, data + offset, ICSF_TOKEN_NAME_LEN + 1, ' '); offset += ICSF_TOKEN_NAME_LEN; strunpad(record->manufacturer, data + offset, ICSF_MANUFACTURER_LEN + 1, ' '); offset += ICSF_MANUFACTURER_LEN; strunpad(record->model, data + offset, ICSF_MODEL_LEN + 1, ' '); offset += ICSF_MODEL_LEN; strunpad(record->serial, data + offset, ICSF_SERIAL_LEN + 1, ' '); offset += ICSF_SERIAL_LEN; strunpad(record->date, data + offset, ICSF_DATE_LEN + 1, ' '); offset += ICSF_DATE_LEN; strunpad(record->time, data + offset, ICSF_TIME_LEN + 1, ' '); offset += ICSF_TIME_LEN; /* Flags are not a string, just a bunch of flags. So it doesn't need * to be null terminated. */ memcpy(record->flags, data + offset, ICSF_FLAGS_LEN); } /* helper function to determine if a specific keyword is in the rule array */ int in_rulearray(const char *keyword, const char *rulearray, int count) { int i = 0; while(count) { if (memcmp(keyword, rulearray + i, 8) == 0) return 1; i += 8; count--; } return 0; } /* * This function indicates if an attribute should be BER encoded as a number or * not, based on its type. */ static int is_numeric_attr(CK_ULONG type) { switch (type) { case CKA_CLASS: case CKA_KEY_TYPE: case CKA_CERTIFICATE_TYPE: case CKA_KEY_GEN_MECHANISM: case CKA_VALUE_LEN: case CKA_MODULUS_BITS: return 1; } return 0; } /* * This helper functions receives a list of attributes containing type, length * and value and encode it in BER encoding. Numeric and non numeric attributes * are encoded using different rules. * * The attributes are encoded following rules: * * Attributes ::= SEQUENCE OF SEQUENCE { * attrName INTEGER, * attrValue AttributeValue * } * * AttributeValue ::= CHOICE { * charValue [0] OCTET STRING, * intValue [1] INTEGER * } * */ static int icsf_ber_put_attribute_list(BerElement *ber, CK_ATTRIBUTE * attrs, CK_ULONG attrs_len) { size_t i; for (i = 0; i < attrs_len; i++) { if (!is_numeric_attr(attrs[i].type)) { /* Non numeric attributes are encode as octet strings */ if (ber_printf(ber, "{ito}", attrs[i].type, 0 | LBER_CLASS_CONTEXT, attrs[i].pValue, attrs[i].ulValueLen) < 0) { goto encode_error; } } else { long value; unsigned long mask; /* `long` is used here to support any size of integer, * however if the value is shorter than a `long` then * just the significant bits should be used. */ if (attrs[i].ulValueLen > sizeof(long)) { TRACE_ERROR ("Integer value too long for attribute\n"); goto encode_error; } /* Calculate a mask to get just the bits in the range of * the given length. */ mask = (1UL << (8 * attrs[i].ulValueLen)) - 1; if (mask == 0) mask = (unsigned long) -1; value = *((unsigned long *) attrs[i].pValue) & mask; /* Encode integer attribute. */ if (ber_printf(ber, "{iti}", attrs[i].type, 1 | LBER_CLASS_CONTEXT, value) < 0) { goto encode_error; } } } return 0; encode_error: TRACE_ERROR("Failed to encode message.\n"); return -1; } /* * * `icsf_list` is a helper function for CSFPTRL service, * which is used for token and object listing. * * `handle` identifies the last token or object returned by a previous call of * `icsf_list`. It should be always 44 bytes long and be in the following * format: * * - For tokens: * * 32 bytes containing the token name padded with blanks; * * remaining bytes filled with blanks. * * - For objects: * * 32 bytes containing the token name padded with blanks; * * 8 bytes containing the object's sequence number encoded int * hexadecimal. * * 1 byte with the character 'T' for token objects or 'S' for session * objects. * * remaining bytes filled with blanks. * * `rule_array` should be a sequence of 8 bytes strings padded with blanks. * It indicates if a list of tokens or a objects will be returned (please refer * to `icsf_create_token` and `icsf_create_object` for details). * * `bv_list` is an output buffer for the raw data and should be freed by the * caller. * * `list_len` is used as input to indicate the number of bytes of the buffer to * be returned, and it's updated with the number of bytes returned. * * `list_count` indicates how many items should be returned. */ static int icsf_list(LDAP *ld, int *reason, char *handle, size_t handle_len, CK_ULONG attrs_len, CK_ATTRIBUTE *attrs, const char *rule_array, size_t rule_array_len, struct berval **bv_list, size_t *list_len, size_t list_count) { int rc = -1; BerElement *msg = NULL; BerElement *result = NULL; int out_list_len = 0; int objectInRuleArray = 0; /* Allocate request message. */ msg = ber_alloc_t(LBER_USE_DER); if (msg == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto cleanup; } /* Encode message: * * TRLInput ::= SEQUENCE { * inListLen INTEGER (0 .. MaxCSFPInteger), * maxHandleCount INTEGER (0 .. MaxCSFPInteger), * searchTemplate [0] Attributes OPTIONAL * } * */ if (ber_printf(msg, "ii", *list_len, list_count) < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } objectInRuleArray = in_rulearray("OBJECT ", rule_array, rule_array_len / ICSF_RULE_ITEM_LEN); if ((objectInRuleArray) && (attrs != NULL)) { if (ber_printf(msg, "t{", 0|LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) < 0) { TRACE_ERROR("Failed to flatten attribute list\n"); goto cleanup; } if (icsf_ber_put_attribute_list(msg, attrs, attrs_len) < 0) { TRACE_ERROR("Failed to flatten attribute list\n"); goto cleanup; } if (ber_printf(msg, "}") < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } } rc = icsf_call(ld, reason, handle, handle_len, rule_array, rule_array_len, ICSF_TAG_CSFPTRL, msg, &result); if (ICSF_RC_IS_ERROR(rc)) goto cleanup; /* Decode result: * * TRLOutput ::= SEQUENCE { * outList CHOICE { * tokenList [0] OCTET STRING, * handleList [1] OCTET STRING * }, * outListLen INTEGER (0 .. MaxCSFPInteger) * } */ if (ber_scanf(result, "{Oi}", bv_list, &out_list_len) < 0) { TRACE_ERROR("Failed to decode message.\n"); rc = -1; goto cleanup; } *list_len = out_list_len; cleanup: if (msg) ber_free(msg, 1); if (result) ber_free(result, 1); return rc; } /* * List tokens on the server. * * `previous` must point to the last token returned by a previous call of * `icsf_list_tokens` or should be NULL for the first call. * * `records` must point to a buffer of token records with `records_len` * elements. `records_len` is updated with the number of tokens returned * and it's zero when there's no more records left. */ int icsf_list_tokens(LDAP *ld, int *reason, struct icsf_token_record *previous, struct icsf_token_record *records, size_t *records_len) { int rc = -1; char handle[44]; char rule_array[ICSF_RULE_ITEM_LEN]; struct berval *bv_list = NULL; size_t list_len; size_t i; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(records); CHECK_ARG_NON_NULL(records_len); /* The first record that must be returned in `records` is the next one * after `previous`, and for that the `previous` handle must be * provided. When `previous` is null a blank handle should be used * instead. */ if (previous) token_name_to_handle(handle, previous->name); else memset(handle, ' ', sizeof(handle)); /* Should be 8 bytes padded. */ strpad(rule_array, "TOKEN", ICSF_RULE_ITEM_LEN, ' '); list_len = ICSF_TOKEN_RECORD_LEN * *records_len; rc = icsf_list(ld, reason, handle, sizeof(handle), 0, NULL, rule_array, sizeof(rule_array), &bv_list, &list_len, *records_len); if (ICSF_RC_IS_ERROR(rc)) goto cleanup; /* Parse result */ *records_len = list_len / ICSF_TOKEN_RECORD_LEN; for (i = 0; i < *records_len; i++) { size_t offset = i * ICSF_TOKEN_RECORD_LEN; parse_token_record(&records[i], bv_list->bv_val + offset); } cleanup: if (bv_list) ber_bvfree(bv_list); return rc; } int icsf_copy_object(LDAP * ld, int *reason, CK_ATTRIBUTE * attrs, CK_ULONG attrs_len, struct icsf_object_record *src, struct icsf_object_record *dst) { int rc = -1; char handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(src); CHECK_ARG_NON_NULL(attrs); object_record_to_handle(handle, src); /* Allocate ber_req to encode message. */ msg = ber_alloc_t(LBER_USE_DER); if (msg == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto cleanup; } if (attrs_len != 0) { rc = ber_printf(msg, "t{", 1 | LBER_CLASS_CONTEXT | LBER_CONSTRUCTED); if (rc < 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); goto cleanup; } if (icsf_ber_put_attribute_list(msg, attrs, attrs_len) < 0) { TRACE_DEVEL("icsf_ber_put_attribute_list failed\n"); goto cleanup; } if (ber_printf(msg, "}") < 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); goto cleanup; } } else { rc = ber_printf(msg, "tn", 1 | LBER_CLASS_CONTEXT | LBER_CONSTRUCTED); if (rc < 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); goto cleanup; } } /* Should be 8 bytes padded. */ strpad(rule_array, "OBJECT", ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + ICSF_RULE_ITEM_LEN, "COPY", ICSF_RULE_ITEM_LEN, ' '); rc = icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPTRC, msg, NULL); if (!rc && dst) handle_to_object_record(dst, handle); cleanup: if (msg) ber_free(msg, 1); return rc; } /* * Create an object in the token defined by the given `token_name`. * * `attrs` is a list of attributes each one consisting in a type, a length and a * value (a sequence of bytes). `attrs_len` indicates how many attributes the * input list has. * * `obj_handle` is the buffer that will receive the handler for the new object. * And it should be at least 44 bytes long (indicated by `obj_handle_len`). */ int icsf_create_object(LDAP *ld, int *reason, const char *token_name, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, struct icsf_object_record *object) { int rc = -1; char handle[ICSF_HANDLE_LEN]; char rule_array[ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL_AND_MAX_LEN(token_name, ICSF_TOKEN_NAME_LEN); CHECK_ARG_NON_NULL(attrs); token_name_to_handle(handle, token_name); /* Should be 8 bytes padded. */ strpad(rule_array, "OBJECT", sizeof(rule_array), ' '); /* Allocate ber_req to encode message. */ msg = ber_alloc_t(LBER_USE_DER); if (msg == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto cleanup; } /* Encode message: * * TRCInput ::= SEQUENCE { * trcAttrs ::= CHOICE { * objectAttrList [1] Attributes * } * } * * Attributes ::= SEQUENCE OF SEQUENCE { * attrName INTEGER, * attrValue AttributeValue * } * * AttributeValue ::= CHOICE { * charValue [0] OCTET STRING, * intValue [1] INTEGER * } * */ if (ber_printf(msg, "t{", 1 | LBER_CLASS_CONTEXT | LBER_CONSTRUCTED) < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } if (icsf_ber_put_attribute_list(msg, attrs, attrs_len) < 0) { TRACE_ERROR("Failed to flatten attribute list\n"); goto cleanup; } if (ber_printf(msg, "}") < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } rc = icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPTRC, msg, NULL); cleanup: if (msg) ber_free(msg, 1); if (!rc && object) handle_to_object_record(object, handle); return rc; } /* * List objects for a token indicated by `token_name`. * * `previous` must point to the last object returned by a previous call of * `icsf_list_objects` or should be NULL for the first call. * * `records` must point to a buffer of object records with `records_len` * elements. `records_len` is updated with the number of objects returned * and it's zero when there's no more records left. */ int icsf_list_objects(LDAP *ld, int *reason, const char *token_name, CK_ULONG attrs_len, CK_ATTRIBUTE *attrs, struct icsf_object_record *previous, struct icsf_object_record *records, size_t *records_len, int all) { int rc = -1; char handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; size_t rule_array_count = 1; struct berval *bv_list = NULL; size_t list_len; size_t i; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL_AND_MAX_LEN(token_name, ICSF_TOKEN_NAME_LEN); CHECK_ARG_NON_NULL(records); CHECK_ARG_NON_NULL(records_len); /* The first record that must be returned in `records` is the next one * after `previous`, and for that the `previous` handle must be * provided. When `previous` is null, the token handle should be used * instead. */ if (previous) object_record_to_handle(handle, previous); else token_name_to_handle(handle, token_name); /* Should be 8 bytes padded. */ strpad(rule_array, "OBJECT", ICSF_RULE_ITEM_LEN, ' '); if (all) { strpad(rule_array + ICSF_RULE_ITEM_LEN, "ALL", ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; } list_len = ICSF_HANDLE_LEN * *records_len; rc = icsf_list(ld, reason, handle, sizeof(handle), attrs_len, attrs, rule_array, rule_array_count * ICSF_RULE_ITEM_LEN, &bv_list, &list_len, *records_len); if (ICSF_RC_IS_ERROR(rc)) goto cleanup; /* Parse result */ *records_len = list_len / ICSF_HANDLE_LEN; for (i = 0; i < *records_len; i++) { size_t offset = i * ICSF_HANDLE_LEN; handle_to_object_record(&records[i], bv_list->bv_val + offset); } cleanup: if (bv_list) ber_bvfree(bv_list); return rc; } /* * Destroy an object. */ int icsf_destroy_object(LDAP *ld, int *reason, struct icsf_object_record *obj) { /* Variables used as input */ char handle[ICSF_HANDLE_LEN]; char rule_array[1 * ICSF_RULE_ITEM_LEN]; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(obj); object_record_to_handle(handle, obj); /* Should be 8 bytes padded. */ strpad(rule_array, "OBJECT", ICSF_RULE_ITEM_LEN, ' '); /* * CSFPTRD service is used to destroy a token or an object. Handle * indicates the token or object that must be destroyed and no * additional data is needed. */ return icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPTRD, NULL, NULL); } /* * Generate an asymmetric key pair. */ int icsf_generate_key_pair(LDAP *ld, int *reason, const char *token_name, CK_ATTRIBUTE *pub_attrs, CK_ULONG pub_attrs_len, CK_ATTRIBUTE *priv_attrs, CK_ULONG priv_attrs_len, struct icsf_object_record *pub_key_object, struct icsf_object_record *priv_key_object) { int rc = -1; char handle[ICSF_HANDLE_LEN]; BerElement *msg = NULL; BerElement *result = NULL; struct berval bv_priv_handle = { 0, NULL }; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL_AND_MAX_LEN(token_name, ICSF_TOKEN_NAME_LEN); CHECK_ARG_NON_NULL(pub_attrs); CHECK_ARG_NON_NULL(priv_attrs); CHECK_ARG_NON_NULL(pub_key_object); CHECK_ARG_NON_NULL(priv_key_object); token_name_to_handle(handle, token_name); if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return rc; } /* Encode message: * * GKPInput ::= SEQUENCE { * publicKeyAttrList Attributes, * privateKeyAttrList Attributes * } * * Attribute lists are built by icsf_ber_put_attribute_list() */ if (ber_printf(msg, "{") < 0 || icsf_ber_put_attribute_list(msg, pub_attrs, pub_attrs_len) < 0 || ber_printf(msg, "}{") < 0 || icsf_ber_put_attribute_list(msg, priv_attrs, priv_attrs_len) < 0 || ber_printf(msg, "}") < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } rc = icsf_call(ld, reason, handle, sizeof(handle), "", 0, ICSF_TAG_CSFPGKP, msg, &result); if (rc) goto cleanup; /* Get private key handle from GKP response */ if (ber_scanf(result, "m", &bv_priv_handle) < 0) { TRACE_ERROR("Failed to decode the response.\n"); rc = -1; goto cleanup; } if (bv_priv_handle.bv_len != ICSF_HANDLE_LEN) { TRACE_ERROR("Invalid length for handle: %lu\n", (unsigned long) bv_priv_handle.bv_len); rc = -1; goto cleanup; } handle_to_object_record(priv_key_object, bv_priv_handle.bv_val); /* Get public key handle from common ICSF header */ handle_to_object_record(pub_key_object, handle); cleanup: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); return rc; } /* * Generate a symmetric key. */ int icsf_generate_secret_key(LDAP *ld, int *reason, const char *token_name, CK_MECHANISM_PTR mech, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, struct icsf_object_record *object) { int rc = -1; char handle[ICSF_HANDLE_LEN]; char rule_array[1 * ICSF_RULE_ITEM_LEN]; char param[2]; size_t param_len; CK_VERSION_PTR version; BerElement *msg = NULL; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL_AND_MAX_LEN(token_name, ICSF_TOKEN_NAME_LEN); CHECK_ARG_NON_NULL(mech); CHECK_ARG_NON_NULL(attrs); token_name_to_handle(handle, token_name); /* Map mechanism into the rule array */ switch (mech->mechanism) { case CKM_TLS_PRE_MASTER_KEY_GEN: strpad(rule_array, "TLS", sizeof(rule_array), ' '); break; case CKM_SSL3_PRE_MASTER_KEY_GEN: strpad(rule_array, "SSL", sizeof(rule_array), ' '); break; case CKM_DSA_PARAMETER_GEN: case CKM_DH_PKCS_PARAMETER_GEN: strpad(rule_array, "PARMS", sizeof(rule_array), ' '); break; default: strpad(rule_array, "KEY", sizeof(rule_array), ' '); } /* Fill parameters if necessary */ switch (mech->mechanism) { case CKM_TLS_PRE_MASTER_KEY_GEN: case CKM_SSL3_PRE_MASTER_KEY_GEN: /* Check expected length */ if (mech->ulParameterLen != sizeof(*version)) { TRACE_ERROR("Invalid mechanism parameter length: " "%lu\n", (unsigned long) mech->ulParameterLen); return -1; } /* Fill parameter with version numbers */ version = (CK_VERSION_PTR) mech->pParameter; param[0] = version->major; param[1] = version->minor; param_len = 2; break; default: /* Parameter should be empty */ param_len = 0; } if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return rc; } /* Encode message: * * GSKInput ::= SEQUENCE { * attrList Attributes, * parmsList OCTET STRING * } * * attrList is built by icsf_ber_put_attribute_list() */ if (ber_printf(msg, "{") < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } if (icsf_ber_put_attribute_list(msg, attrs, attrs_len) < 0 || ber_printf(msg, "}o", param, param_len) < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } rc = icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPGSK, msg, NULL); if (!rc) handle_to_object_record(object, handle); cleanup: if (msg) ber_free(msg, 1); return rc; } /* * Return the rule array element for the given mechanism. */ static const char * get_algorithm_rule(CK_MECHANISM_PTR mech, int arg) { switch (mech->mechanism) { case CKM_DES_ECB: case CKM_DES_CBC: case CKM_DES_CBC_PAD: return "DES"; case CKM_DES3_ECB: case CKM_DES3_CBC: case CKM_DES3_CBC_PAD: return "DES3"; case CKM_AES_ECB: case CKM_AES_CBC: case CKM_AES_CBC_PAD: case CKM_AES_CTR: return "AES"; case CKM_DSA: return "DSA"; case CKM_ECDSA: return "ECDSA"; case CKM_RSA_X_509: return "RSA-ZERO"; case CKM_RSA_PKCS: return "RSA-PKCS"; case CKM_SHA_1_HMAC: return "SHA-1"; case CKM_SHA256_HMAC: return "SHA-256"; case CKM_SHA384_HMAC: return "SHA-384"; case CKM_SHA512_HMAC: return "SHA-512"; case CKM_MD5_HMAC: return "MD5"; case CKM_SSL3_MD5_MAC: return "SSL3-MD5"; case CKM_SSL3_SHA1_MAC: return "SSL3-SHA"; case CKM_SHA1_RSA_PKCS: if (arg) return "SHA-1 VER-RSA"; else return "SHA-1 SIGN-RSA"; case CKM_SHA256_RSA_PKCS: if (arg) return "SHA-256 VER-RSA"; else return "SHA-256 SIGN-RSA"; case CKM_SHA384_RSA_PKCS: if (arg) return "SHA-384 VER-RSA"; else return "SHA-384 SIGN-RSA"; case CKM_SHA512_RSA_PKCS: if (arg) return "SHA-512 VER-RSA"; else return "SHA-512 SIGN-RSA"; case CKM_MD5_RSA_PKCS: if (arg) return "MD5 VER-RSA"; else return "MD5 SIGN-RSA"; case CKM_DSA_SHA1: if (arg) return "SHA-1 VER-DSA"; else return "SHA-1 SIGN-DSA"; case CKM_ECDSA_SHA1: if (arg) return "SHA-1 VER-EC"; else return "SHA-1 SIGN-EC"; case CKM_SSL3_KEY_AND_MAC_DERIVE: return "SSL-KM"; case CKM_TLS_KEY_AND_MAC_DERIVE: return "TLS-KM"; } return NULL; } /* * Return the rule array element for the cipher mode based on the given * mechanism. */ static const char * get_cipher_mode(CK_MECHANISM_PTR mech) { switch (mech->mechanism) { case CKM_DES_ECB: case CKM_DES3_ECB: case CKM_AES_ECB: return "ECB"; case CKM_DES_CBC: case CKM_DES3_CBC: case CKM_AES_CBC: return "CBC"; case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_AES_CBC_PAD: return "CBC-PAD"; } return NULL; } /* * Get the block size of supported algorithms/mechanism. */ CK_RV icsf_block_size(CK_MECHANISM_TYPE mech_type, CK_ULONG_PTR p_block_size) { CK_ULONG block_size; switch (mech_type) { case CKM_DES_CBC: case CKM_DES_CBC_PAD: case CKM_DES3_CBC: case CKM_DES3_CBC_PAD: case CKM_DES_ECB: case CKM_DES3_ECB: block_size = DES_BLOCK_SIZE; break; case CKM_AES_CBC: case CKM_AES_CBC_PAD: case CKM_AES_ECB: block_size = AES_BLOCK_SIZE; break; case CKM_MD5_RSA_PKCS: block_size = MD5_BLOCK_SIZE; break; case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: block_size = SHA1_BLOCK_SIZE; break; case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: block_size = SHA3_BLOCK_SIZE; break; default: return CKR_MECHANISM_INVALID; } if (p_block_size) *p_block_size = block_size; return CKR_OK; } /* * Extract and check the initialization vector contained in the given mechanism. */ static CK_RV icsf_encrypt_initial_vector(CK_MECHANISM_PTR mech, char *iv, size_t *iv_len) { CK_RV rc; int use_iv = 0; size_t expected_iv_len = 0; if ((rc = icsf_block_size(mech->mechanism, &expected_iv_len))) return rc; switch (mech->mechanism) { case CKM_DES_CBC: case CKM_DES_CBC_PAD: case CKM_DES3_CBC: case CKM_DES3_CBC_PAD: case CKM_AES_CBC: case CKM_AES_CBC_PAD: use_iv = 1; } if (iv_len && *iv_len < expected_iv_len) { TRACE_ERROR("IV too small.\n"); return CKR_FUNCTION_FAILED; } /* Set the Initialization vector */ if (iv) memset(iv, 0, expected_iv_len); if (use_iv) { /* * Otherwise use the mechanism parameter as the IV. */ if (mech->ulParameterLen != expected_iv_len) { TRACE_ERROR("Invalid mechanism parameter length: %lu " "(expected %lu)\n", (unsigned long) mech->ulParameterLen, (unsigned long) expected_iv_len); return CKR_MECHANISM_PARAM_INVALID; } if (iv) memcpy(iv, mech->pParameter, expected_iv_len); } if (iv_len) *iv_len = expected_iv_len; return 0; } /* * Symmetric key encrypt. */ int icsf_secret_key_encrypt(LDAP *ld, int *p_reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, int chaining, const char *clear_text, size_t clear_text_len, char *cipher_text, size_t *p_cipher_text_len, char *chaining_data, size_t *p_chaining_data_len) { int rc = 0; char handle[ICSF_HANDLE_LEN]; char rule_array[3 * ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; BerElement *result = NULL; char init_vector[32]; size_t init_vector_len = sizeof(init_vector); struct berval bv_cipher_data = { 0UL, NULL }; struct berval bv_chaining_data = { 0UL, NULL }; const char *rule_alg, *rule_cipher; int reason = 0, length = 0; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(key); CHECK_ARG_NON_NULL(mech); CHECK_ARG_NON_NULL(clear_text); CHECK_ARG_NON_NULL(p_cipher_text_len); if (!ICSF_CHAINING_IS_VALID(chaining)) { TRACE_ERROR("Invalid value for chaining: %d\n", chaining); return -1; } object_record_to_handle(handle, key); /* * Add to rule array the algorithm, the cipher mode and the * chaining mode. */ if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } if (!(rule_cipher = get_cipher_mode(mech))) { TRACE_ERROR("Invalid cipher mode: %lu\n", (unsigned long) mech->mechanism); return -1; } strpad(rule_array + 0 * ICSF_RULE_ITEM_LEN, rule_alg, ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + 1 * ICSF_RULE_ITEM_LEN, rule_cipher, ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + 2 * ICSF_RULE_ITEM_LEN, ICSF_CHAINING(chaining), ICSF_RULE_ITEM_LEN, ' '); /* Set the IV based on the given mechanism */ if (chaining != ICSF_CHAINING_INITIAL && chaining != ICSF_CHAINING_ONLY) { rc = icsf_encrypt_initial_vector(mech, NULL, NULL); memset(init_vector, 0, init_vector_len); } else { rc = icsf_encrypt_initial_vector(mech, init_vector, &init_vector_len); } if (rc) return -1; /* Build request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } if (ber_printf(msg, "toooi", 0 | LBER_CLASS_CONTEXT, init_vector, init_vector_len, (chaining_data) ? chaining_data : "", (p_chaining_data_len) ? *p_chaining_data_len : 0UL, clear_text, clear_text_len, (cipher_text) ? *p_cipher_text_len : 0UL) < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call service */ rc = icsf_call(ld, &reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPSKE, msg, &result); if (p_reason) *p_reason = reason; if (ICSF_RC_IS_ERROR(rc) && reason != ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) goto done; /* Parse response */ if (ber_scanf(result, "{mmi", &bv_chaining_data, &bv_cipher_data, &length) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } *p_cipher_text_len = length; /* Copy encrypted data */ if (bv_cipher_data.bv_len > *p_cipher_text_len) { TRACE_ERROR("Cipher data longer than expected: %lu " "(expected %lu)\n", (unsigned long) bv_cipher_data.bv_len, (unsigned long) *p_cipher_text_len); rc = -1; goto done; } if (cipher_text) memcpy(cipher_text, bv_cipher_data.bv_val, bv_cipher_data.bv_len); /* Copy chaining data */ if (p_chaining_data_len) { if (bv_chaining_data.bv_len > *p_chaining_data_len) { TRACE_ERROR("Chaining data longer than expected: %lu " "(expected %lu)\n", (unsigned long) bv_chaining_data.bv_len, (unsigned long) *p_chaining_data_len); rc = -1; goto done; } *p_chaining_data_len = bv_chaining_data.bv_len; if (chaining_data) { memcpy(chaining_data, bv_chaining_data.bv_val, *p_chaining_data_len); } } done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); return rc; } /* * Symmetric key decrypt. */ int icsf_secret_key_decrypt(LDAP *ld, int *p_reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, int chaining, const char *cipher_text, size_t cipher_text_len, char *clear_text, size_t *p_clear_text_len, char *chaining_data, size_t *p_chaining_data_len) { int rc = 0; char handle[ICSF_HANDLE_LEN]; char rule_array[3 * ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; BerElement *result = NULL; char init_vector[32]; size_t init_vector_len = sizeof(init_vector); struct berval bv_clear_data = { 0UL, NULL }; struct berval bv_chaining_data = { 0UL, NULL }; const char *rule_alg, *rule_cipher; int reason = 0, length = 0; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(key); CHECK_ARG_NON_NULL(mech); CHECK_ARG_NON_NULL(cipher_text); CHECK_ARG_NON_NULL(p_clear_text_len); if (!ICSF_CHAINING_IS_VALID(chaining)) { TRACE_ERROR("Invalid value for chaining: %d\n", chaining); return -1; } object_record_to_handle(handle, key); /* * Add to rule array the algorithm, the cipher mode and the * chaining mode. */ if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } if (!(rule_cipher = get_cipher_mode(mech))) { TRACE_ERROR("Invalid cipher mode: %lu\n", (unsigned long) mech->mechanism); return -1; } strpad(rule_array + 0 * ICSF_RULE_ITEM_LEN, rule_alg, ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + 1 * ICSF_RULE_ITEM_LEN, rule_cipher, ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + 2 * ICSF_RULE_ITEM_LEN, ICSF_CHAINING(chaining), ICSF_RULE_ITEM_LEN, ' '); /* Set the IV based on the given mechanism */ if (chaining != ICSF_CHAINING_INITIAL && chaining != ICSF_CHAINING_ONLY) { rc = icsf_encrypt_initial_vector(mech, NULL, NULL); memset(init_vector, 0, init_vector_len); } else { rc = icsf_encrypt_initial_vector(mech, init_vector, &init_vector_len); } if (rc) return -1; /* Build request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } if (ber_printf(msg, "totototi", 0 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE, init_vector, init_vector_len, 2 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE, (chaining_data) ? chaining_data : "", (p_chaining_data_len) ? *p_chaining_data_len : 0UL, 3 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE, cipher_text, cipher_text_len, 4 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE, (clear_text) ? *p_clear_text_len : 0UL) < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call service */ rc = icsf_call(ld, &reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPSKD, msg, &result); if (p_reason) *p_reason = reason; if (ICSF_RC_IS_ERROR(rc) && reason != ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) goto done; /* Parse response */ if (ber_scanf(result, "{mmi", &bv_chaining_data, &bv_clear_data, &length) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } *p_clear_text_len = length; /* Copy encrypted data */ if (bv_clear_data.bv_len > *p_clear_text_len) { TRACE_ERROR("Clear data longer than expected: %lu " "(expected %lu)\n", (unsigned long) bv_clear_data.bv_len, (unsigned long) *p_clear_text_len); rc = -1; goto done; } if (clear_text) memcpy(clear_text, bv_clear_data.bv_val, bv_clear_data.bv_len); /* Copy chaining data */ if (p_chaining_data_len) { if (bv_chaining_data.bv_len > *p_chaining_data_len) { TRACE_ERROR("Chaining data longer than expected: %lu " "(expected %lu)\n", (unsigned long) bv_chaining_data.bv_len, (unsigned long) *p_chaining_data_len); rc = -1; goto done; } *p_chaining_data_len = bv_chaining_data.bv_len; if (chaining_data) { memcpy(chaining_data, bv_chaining_data.bv_val, *p_chaining_data_len); } } rc = 0; done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); return rc; } static int icsf_ber_decode_get_attribute_list(BerElement *berbuf, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len) { int attrtype; struct berval attrbval = {0, NULL}; ber_int_t intval; int i, found = 0; ber_tag_t tag; CK_RV rc = CKR_OK; if (ber_scanf(berbuf, "{{") == LBER_ERROR) goto decode_error; while (1) { /* get tag preceding sequence */ if (ber_scanf(berbuf, "t", &tag) == LBER_ERROR) goto decode_error; /* is it a sequence (thus attribute) */ if (tag != (LBER_CLASS_UNIVERSAL | LBER_CONSTRUCTED | LBER_SEQUENCE)) break; /* sequence, so get attribute info */ if (ber_scanf(berbuf, "{it", &attrtype, &tag) == LBER_ERROR) goto decode_error; if ((tag & LBER_BIG_TAG_MASK) == 0) { if (ber_scanf(berbuf, "o}", &attrbval) == LBER_ERROR) goto decode_error; } else { if (ber_scanf(berbuf, "i}", &intval) == LBER_ERROR) goto decode_error; attrbval.bv_len = sizeof(CK_ULONG); } /* see if this type matches any that we need to * get value for. if so, then get the value, otherwise * continue until we have found all of them or there * are no more attributes to search */ for (i = 0; i < attrs_len; i++) { if (attrs[i].type != attrtype) continue; /* we have decoded attribute, now add the values */ if (attrs[i].pValue == NULL) { attrs[i].ulValueLen = attrbval.bv_len; } else if (attrs[i].ulValueLen >= attrbval.bv_len) { if ((tag & LBER_BIG_TAG_MASK) == 0) { memcpy(attrs[i].pValue, attrbval.bv_val, attrbval.bv_len); } else { *((CK_ULONG *) attrs[i].pValue) = intval; } attrs[i].ulValueLen = attrbval.bv_len; } else { rc = CKR_BUFFER_TOO_SMALL; attrs[i].ulValueLen = -1; goto decode_error; } /* keep count of how many are found. */ found++; } /* if we have found all the values for our list, then * we are done. */ if (found == attrs_len) break; } /* if we have gone through the entire loop and could not find * all of the attributes in our list, mark this as an error. */ if (found < attrs_len) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); rc = CKR_ATTRIBUTE_TYPE_INVALID; goto decode_error; } return rc; decode_error: TRACE_ERROR("Failed to decode message.\n"); if (!rc) rc = CKR_FUNCTION_FAILED; return rc; } int icsf_get_attribute(LDAP *ld, int *reason, struct icsf_object_record *object, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len) { char handle[ICSF_HANDLE_LEN]; BerElement *msg = NULL; BerElement *result = NULL; int rc = 0; int i; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(attrs); CHECK_ARG_NON_NULL(object); object_record_to_handle(handle, object); if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } /* Encode message: * * GAVInput ::= attrListLen * * attrListLen ::= INTEGER (0 .. MaxCSFPInteger) * */ rc = ber_printf(msg, "i", attrs_len); if (rc < 0) goto cleanup; rc = icsf_call(ld, reason, handle, sizeof(handle), "", 0, ICSF_TAG_CSFPGAV, msg, &result); if (rc != 0) { TRACE_DEVEL("icsf_call failed.\n"); goto cleanup; } /* Before decoding the result, initialize the attribute values length. * This will help to indicate which attributes were not found * or not enough storage was allocated for the value. */ for (i = 0; i < attrs_len; i++) attrs[i].ulValueLen = (CK_ULONG)-1; /* Decode the result: * * GAVOutput ::= SEQUENCE { * attrList Attributes, * attrListLen INTEGER (0 .. MaxCSFPInteger) * } * * asn.1 {{{ito|i} {ito|i} ...}i} */ rc = icsf_ber_decode_get_attribute_list(result, attrs, attrs_len); if (rc < 0) { TRACE_ERROR("Failed to decode message.\n"); goto cleanup; } cleanup: if (msg) ber_free(msg, 1); if (result) ber_free(result, 1); return rc; } int icsf_set_attribute(LDAP *ld, int *reason, struct icsf_object_record *object, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len) { int rc = -1; char handle[ICSF_HANDLE_LEN]; BerElement *msg = NULL; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(attrs); object_record_to_handle(handle, object); if (!(msg = ber_alloc_t(LBER_USE_DER))) { return rc; } /* Encode message: * * SAVInput ::= Attributes * * attrList is built by icsf_ber_put_attribute_list() */ if (icsf_ber_put_attribute_list(msg, attrs, attrs_len) < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } rc = icsf_call(ld, reason, handle, sizeof(handle), "", 0, ICSF_TAG_CSFPSAV, msg, NULL); if (rc < 0) { TRACE_ERROR("icsf_call failed.\n"); goto cleanup; } /* Decode message: * * SAVOutput ::= NULL * */ cleanup: if (msg) ber_free(msg, 1); return rc; } /* * Sign or decrypt data using a private key. */ int icsf_private_key_sign(LDAP *ld, int *p_reason, int decrypt, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *cipher_text, size_t cipher_text_len, char *clear_text, size_t *p_clear_text_len) { int rc; int reason = 0; char handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; size_t rule_array_count = 0; const char *rule_alg; BerElement *msg = NULL; BerElement *result = NULL; struct berval bv_clear_text = { 0, NULL }; int length = 0; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(key); CHECK_ARG_NON_NULL(mech); CHECK_ARG_NON_NULL(cipher_text); CHECK_ARG_NON_NULL(p_clear_text_len); object_record_to_handle(handle, key); /* Build rule array based on mechanism */ if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } strpad(rule_array, rule_alg, ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; if (decrypt) { strpad(rule_array + (rule_array_count * ICSF_RULE_ITEM_LEN), "DECRYPT", ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; } /* Build request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } if (ber_printf(msg, "oi", cipher_text, (ber_int_t) cipher_text_len, (!clear_text) ? 0 : ((ber_int_t) *p_clear_text_len)) < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call service */ rc = icsf_call(ld, &reason, handle, sizeof(handle), rule_array, rule_array_count * ICSF_RULE_ITEM_LEN, ICSF_TAG_CSFPPKS, msg, &result); if (p_reason) *p_reason = reason; if (ICSF_RC_IS_ERROR(rc) && reason != ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) goto done; if (ber_scanf(result, "{mi}", &bv_clear_text, &length) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } /* Copy clear data */ *p_clear_text_len = length; if (bv_clear_text.bv_len > *p_clear_text_len) { TRACE_ERROR("Clear data longer than expected: %lu " "(expected %lu)\n", (unsigned long) bv_clear_text.bv_len, (unsigned long) *p_clear_text_len); rc = -1; goto done; } if (clear_text) memcpy(clear_text, bv_clear_text.bv_val, *p_clear_text_len); done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); return rc; } /* * Verify or encrypt using a public. key. */ int icsf_public_key_verify(LDAP *ld, int *p_reason, int encrypt, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *clear_text, size_t clear_text_len, char *cipher_text, size_t *p_cipher_text_len) { int rc; int reason = 0; char handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; size_t rule_array_count = 0; const char *rule_alg; BerElement *msg = NULL; BerElement *result = NULL; struct berval bv_cipher_text = { 0, NULL }; int length = 0; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(key); CHECK_ARG_NON_NULL(mech); CHECK_ARG_NON_NULL(clear_text); CHECK_ARG_NON_NULL(p_cipher_text_len); object_record_to_handle(handle, key); /* Build rule array based on mechanism */ if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } strpad(rule_array, rule_alg, ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; if (encrypt) { strpad(rule_array + (rule_array_count * ICSF_RULE_ITEM_LEN), "ENCRYPT", ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; } /* Build request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } if (encrypt) { rc = ber_printf(msg, "oti", clear_text, clear_text_len, 0 | LBER_CLASS_CONTEXT, *p_cipher_text_len); } else { rc = ber_printf(msg, "oto", cipher_text, *p_cipher_text_len, 1 | LBER_CLASS_CONTEXT, clear_text, clear_text_len); } if (rc < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call request */ rc = icsf_call(ld, &reason, handle, sizeof(handle), rule_array, rule_array_count * ICSF_RULE_ITEM_LEN, ICSF_TAG_CSFPPKV, msg, &result); if (p_reason) *p_reason = reason; if (ICSF_RC_IS_ERROR(rc) && reason != ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) goto done; /* There's no output data when verifying */ if (!encrypt) goto done; if (ber_scanf(result, "{mi}", &bv_cipher_text, &length) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } /* Copy clear data */ *p_cipher_text_len = length; if (bv_cipher_text.bv_len != *p_cipher_text_len) { TRACE_ERROR("Cipher data length different that expected: %lu " "(expected %lu)\n", (unsigned long) bv_cipher_text.bv_len, (unsigned long) *p_cipher_text_len); rc = -1; goto done; } if (cipher_text) memcpy(cipher_text, bv_cipher_text.bv_val, *p_cipher_text_len); done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); return rc; } int icsf_hmac_sign(LDAP *ld, int *reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *chain_rule, const char *clear_text, size_t clear_text_len, char *hmac, size_t *hmac_len, char *chain_data, size_t *chain_data_len) { int rc = 0; char handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; BerElement *result = NULL; struct berval bvHmac = { 0, NULL }; struct berval bvChain = { 0, NULL }; int hmac_length; const char *rule_alg; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(key); CHECK_ARG_NON_NULL(mech); object_record_to_handle(handle, key); /* Add to rule array, the algorithm and chaining mode */ if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } strpad(rule_array + 0 * ICSF_RULE_ITEM_LEN, rule_alg, ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + 1 * ICSF_RULE_ITEM_LEN, chain_rule, ICSF_RULE_ITEM_LEN, ' '); /* Build the request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } /* Input ASN.1 for CSFPHMG. * HMGInput ::= SEQUENCE { * text OCTET STRING, * chainData OCTET STRING, * hmacLength INTEGER (0 .. MaxCSFPInteger) * } */ if (ber_printf(msg, "ooi", (clear_text) ? clear_text : "", clear_text_len, chain_data, *chain_data_len, *hmac_len) < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call service */ rc = icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPHMG, msg, &result); if (ICSF_RC_IS_ERROR(rc)) { TRACE_DEVEL("icsf_call failed\n"); goto done; } /* Parse the response. * HMGOutput ::= SEQUENCE { * chainData OCTET STRING, * hmac OCTET STRING, * hmacLength INTEGER (0 .. MaxCSFPInteger) * } * * Where, * chainData - A string that specifies the chaining data returned * during multi-part HMAC hashing in the CSFPHMG callable service. * This chainData must be specified on subsequent calls to * the CSFPHMG callable service. * hmac - A string containing the HMAC value * hmacLength - ignored by ICSF * * NOTE: * - chainData is always blindly returned, whether it is pertinent * or not. * - For a FIRST or MIDDLE request, hmac is returned as a zero length * string. * - For a LAST or ONLY request, hmac is returned as a string of * appropriate length based on the mechanism. The validity of the hmac * contents are subject to ICSF behavior, based on the ICSF return * code and ICSF reason code. * - The hmacLength is ignored by ICSF and has no affect on how we * encode the returned hmac. The hmacLength is passed along through * the BER encoded messages and in and out of the ICSF call in case * this changes in the future. */ if (ber_scanf(result, "{ooi}", &bvChain, &bvHmac, &hmac_length) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } /* copy the chained data even if not using it*/ *chain_data_len = bvChain.bv_len; memcpy(chain_data, bvChain.bv_val, bvChain.bv_len); /* copy the hmac when needed */ if (*hmac_len) { if (*hmac_len >= bvHmac.bv_len) { memcpy(hmac, bvHmac.bv_val, bvHmac.bv_len); *hmac_len = bvHmac.bv_len; } else /* supplied buffer is too small */ *reason = 3003; } done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); if (bvHmac.bv_val) ber_memfree(bvHmac.bv_val); if (bvChain.bv_val) ber_memfree(bvChain.bv_val); return rc; } int icsf_hmac_verify(LDAP *ld, int *reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *chain_rule, const char *clear_text, size_t clear_text_len, char *hmac, size_t hmac_len, char *chain_data, size_t *chain_data_len) { int rc = 0; char handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; BerElement *result = NULL; struct berval bvChain = { 0UL, NULL }; const char *rule_alg; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(key); CHECK_ARG_NON_NULL(mech); object_record_to_handle(handle, key); /* Add to rule array, the algorithm and chaining mode */ if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } strpad(rule_array + 0 * ICSF_RULE_ITEM_LEN, rule_alg, ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + 1 * ICSF_RULE_ITEM_LEN, chain_rule, ICSF_RULE_ITEM_LEN, ' '); /* Build the request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } /* * Input ASN.1 for CSFPHMV. * HMVInput ::= SEQUENCE { * text OCTET STRING, * chainData OCTET STRING, * hmac OCTET STRING * } * * Where, * text - A string that identifies the text to test an HMAC hash * in the CSFPHMV callable service. * chainData - A string that specifies the chaining data maintained * during multi-part HMAC hashing in the CSFPHMV callable * service. * hmac - A string that identifies the HMAC hash to verify * against the text in the CSFPHMV callable service. * NOTE: * - chainData is always required, even on a FIRST call (where it is * not really an input) and even on an ONLY call (where there is no * chaining). An HMV ONLY call fails with reason_code=11000 when * chain_data_length is 0. * - For an ONLY call or LAST call, hmac MUST be at least as * many bytes in length as required based on the mechanism. * - For a FIRST or MIDDLE call, hmac is ignored. */ if (ber_printf(msg, "ooo", (clear_text) ? clear_text : "", clear_text_len, chain_data, *chain_data_len, hmac, hmac_len) < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call service */ rc = icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPHMV, msg, &result); if (ICSF_RC_IS_ERROR(rc)) { TRACE_DEVEL("icsf_call failed\n"); goto done; } /* Parse the response. * HMVOutput ::= chainData OCTET STRING * * Where, * chainData - A string that specifies the chaining data returned * during multi-part HMAC hashing in the CSFPHMV callable service. * This chainData must be specified on subsequent calls to * the CSFPHMV callable service. * * NOTE: * - chainData is always blindly returned, whether it is pertinent * or not. */ if (ber_scanf(result, "m", &bvChain) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } /* if chaining, copy the chained data */ *chain_data_len = bvChain.bv_len; memcpy(chain_data, bvChain.bv_val, bvChain.bv_len); done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); return rc; } /* * Wrap a key. */ int icsf_wrap_key(LDAP *ld, int *p_reason, CK_MECHANISM_PTR mech, struct icsf_object_record *wrapping_key, struct icsf_object_record *key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR p_wrapped_key_len) { int rc = 0; int reason = 0; char handle[ICSF_HANDLE_LEN]; char wrapping_handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; size_t rule_array_count = 0; const char *rule_fmt = NULL; const char *rule_alg = NULL; BerElement *msg = NULL; BerElement *result = NULL; struct berval bv_wrapped_key = { 0, NULL }; ber_int_t wrapped_key_len = 0; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(mech); CHECK_ARG_NON_NULL(wrapping_key); CHECK_ARG_NON_NULL(key); CHECK_ARG_NON_NULL(p_wrapped_key_len); object_record_to_handle(handle, key); object_record_to_handle(wrapping_handle, wrapping_key); /* Build rule array based on mechanism */ switch (mech->mechanism) { case CKM_RSA_PKCS: rule_fmt= "PKCS-1.2"; break; case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_AES_CBC_PAD: rule_fmt = "PKCS-8"; if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return -1; } strpad(rule_array, rule_fmt, ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; if (rule_alg) { strpad(rule_array + (rule_array_count * ICSF_RULE_ITEM_LEN), rule_alg, ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; } /* Build request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } /* Encode message: * * WPKInput ::= SEQUENCE { * wrappingHandle OCTET STRING, * wrappedKeyMaxLen INTEGER (0 .. MaxCSFPInteger), * initialValue OCTET STRING * } */ rc = ber_printf(msg, "ois", wrapping_handle, sizeof(wrapping_handle), (ber_int_t) *p_wrapped_key_len, ""); if (rc < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call request */ rc = icsf_call(ld, &reason, handle, sizeof(handle), rule_array, rule_array_count * ICSF_RULE_ITEM_LEN, ICSF_TAG_CSFPWPK, msg, &result); if (p_reason) *p_reason = reason; if (ICSF_RC_IS_ERROR(rc) && reason != ICSF_REASON_OUTPUT_PARAMETER_TOO_SHORT) goto done; /* Decode message: * * WPKOutput ::= SEQUENCE { * wrappedKey OCTET STRING, * wrappedKeyLen INTEGER * } */ if (ber_scanf(result, "{mi}", &bv_wrapped_key, &wrapped_key_len) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } *p_wrapped_key_len = wrapped_key_len; /* Copy wrapped key*/ if (bv_wrapped_key.bv_len > *p_wrapped_key_len) { TRACE_ERROR("Wrapped key length different that expected: %lu " "(expected %lu)\n", (unsigned long) bv_wrapped_key.bv_len, (unsigned long) *p_wrapped_key_len); rc = -1; goto done; } if (wrapped_key) memcpy(wrapped_key, bv_wrapped_key.bv_val, *p_wrapped_key_len); done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); return rc; } /* * Unwrap a key. */ int icsf_unwrap_key(LDAP *ld, int *p_reason, CK_MECHANISM_PTR mech, struct icsf_object_record *unwrapping_key, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, struct icsf_object_record *key) { int rc = 0; int reason = 0; char handle[ICSF_HANDLE_LEN]; char rule_array[2 * ICSF_RULE_ITEM_LEN]; size_t rule_array_count = 0; const char *rule_fmt = NULL; const char *rule_alg = NULL; BerElement *msg = NULL; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(mech); CHECK_ARG_NON_NULL(unwrapping_key); CHECK_ARG_NON_NULL(wrapped_key); CHECK_ARG_NON_NULL(key); object_record_to_handle(handle, unwrapping_key); /* Build rule array based on mechanism */ switch (mech->mechanism) { case CKM_RSA_PKCS: rule_fmt= "PKCS-1.2"; break; case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_AES_CBC_PAD: rule_fmt = "PKCS-8"; if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return -1; } strpad(rule_array, rule_fmt, ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; if (rule_alg) { strpad(rule_array + (rule_array_count * ICSF_RULE_ITEM_LEN), rule_alg, ICSF_RULE_ITEM_LEN, ' '); rule_array_count += 1; } /* Build request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } /* Encode message: * * UWKInput ::= SEQUENCE { * wrappedKey OCTET STRING, * initialValue OCTET STRING, * attrList Attributes * } */ if (ber_printf(msg, "os", wrapped_key, wrapped_key_len, "") < 0 || ber_printf(msg, "{") < 0 || icsf_ber_put_attribute_list(msg, attrs, attrs_len) || ber_printf(msg, "}") < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call request */ rc = icsf_call(ld, &reason, handle, sizeof(handle), rule_array, rule_array_count * ICSF_RULE_ITEM_LEN, ICSF_TAG_CSFPUWK, msg, NULL); if (p_reason) *p_reason = reason; if (ICSF_RC_IS_ERROR(rc)) goto done; handle_to_object_record(key, handle); done: if (msg) ber_free(msg, 1); return rc; } int icsf_hash_signverify(LDAP *ld, int *reason, struct icsf_object_record *key, CK_MECHANISM_PTR mech, const char *chain_rule, const char *clear_text, unsigned long clear_text_len, char *sig, unsigned long *sig_len, char *chain_data, size_t *chain_data_len, int verify) { int rc = 0; char handle[ICSF_HANDLE_LEN]; char rule_array[3 * ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; BerElement *result = NULL; struct berval bvSig = { 0, NULL }; struct berval bvChain = { 0, NULL }; int length, reason_code; const char *rule_alg; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(key); CHECK_ARG_NON_NULL(mech); object_record_to_handle(handle, key); /* Add to rule array, the algorithm and chaining mode */ if (!(rule_alg = get_algorithm_rule(mech, verify))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } strpad(rule_array + 0 * ICSF_RULE_ITEM_LEN, rule_alg, 2 * ICSF_RULE_ITEM_LEN, ' '); strpad(rule_array + 2 * ICSF_RULE_ITEM_LEN, chain_rule, ICSF_RULE_ITEM_LEN, ' '); /* Build the request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } if (ber_printf(msg, "ooo", (clear_text) ? clear_text : "", clear_text_len, (chain_data) ? chain_data : "", (chain_data_len) ? *chain_data_len : 0UL, (sig) ? sig : "", (sig_len) ? *sig_len : 0) < 0) { rc = -1; TRACE_ERROR("Failed to encode message: %d.\n", rc); goto done; } /* Call service */ rc = icsf_call(ld, &reason_code, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPOWH, msg, &result); if (reason) *reason = reason_code; /* If there was an error related to buffer being too small, * don't exit until you get the max required length from response. */ if (ICSF_RC_IS_ERROR(rc) && (reason_code != 3003)) goto done; /* Parse the response. */ if (ber_scanf(result, "{ooi}", &bvChain, &bvSig, &length) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } /* Only need to return the length for signing */ if (sig_len && !verify) *sig_len = length; /* leave if just returning the length. */ if (!verify && *reason == 3003) goto done; /* copy the chained data when required */ if (chain_data) memcpy(chain_data, bvChain.bv_val, bvChain.bv_len); /* copy signature when signing */ if (!verify) memcpy(sig, bvSig.bv_val, bvSig.bv_len); done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); if (bvSig.bv_val) ber_memfree(bvSig.bv_val); if (bvChain.bv_val) ber_memfree(bvChain.bv_val); return rc; } /* * Derive a symmetric key. */ int icsf_derive_key(LDAP *ld, int *reason, CK_MECHANISM_PTR mech, struct icsf_object_record *baseKey, struct icsf_object_record *object, CK_ATTRIBUTE *attrs, CK_ULONG attrs_len) { int rc = -1; char handle[ICSF_HANDLE_LEN]; char rule_array[1 * ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; BerElement *result = NULL; CK_VERSION_PTR version = NULL; CK_SSL3_MASTER_KEY_DERIVE_PARAMS * params = NULL; CK_SSL3_RANDOM_DATA * random_data = NULL; struct berval clientData = {0, NULL}, serverData = {0, NULL}; struct berval publicValue = {0, NULL}, bvParam = {0, NULL}; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(mech); object_record_to_handle(handle, baseKey); /* Map mechanism into the rule array */ switch (mech->mechanism) { case CKM_SSL3_MASTER_KEY_DERIVE: strpad(rule_array, "SSL-MS", ICSF_RULE_ITEM_LEN, ' '); break; case CKM_DH_PKCS_DERIVE: strpad(rule_array, "PKCS-DH", ICSF_RULE_ITEM_LEN, ' '); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return -1; } if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return rc; } /* Encode message: * * DVKInput ::= SEQUENCE { * attrList Attributes, * parmsListChoice DVKInputParmsList * } * * DVKInputParmsList ::= CHOICE { * PKCS-DH_publicValue [0] OCTET STRING, * SSL-TLS [1] SSL-TLS_DVKInputParmsList, * EC-DH [2] EC-DH_DVKInputParmsList * } * * SSL-TLS_DVKInputParmsList ::= SEQUENCE { * clientRandomData OCTET STRING, * serverRandomData OCTET STRING * } * * EC-DH is not supported * * attrList is built by icsf_ber_put_attribute_list() */ if (ber_printf(msg, "{") < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } if (icsf_ber_put_attribute_list(msg, attrs, attrs_len) < 0 ) { TRACE_DEVEL("Failed to encode message.\n"); goto cleanup; } if (ber_printf(msg, "}") < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } /* Attribute list depends on type of mechanism */ switch (mech->mechanism) { case CKM_DH_PKCS_DERIVE: if ((!mech->pParameter) || ((mech->ulParameterLen < 64) || (mech->ulParameterLen > 256))) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } publicValue.bv_val = mech->pParameter; publicValue.bv_len = mech->ulParameterLen; if (ber_printf(msg, "tO", 0|LBER_PRIMITIVE|LBER_CLASS_CONTEXT, &publicValue) < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } break; case CKM_SSL3_MASTER_KEY_DERIVE: params = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)mech->pParameter; random_data = (CK_SSL3_RANDOM_DATA *) (¶ms->RandomInfo); clientData.bv_len = random_data->ulClientRandomLen; clientData.bv_val = random_data->pClientRandom; serverData.bv_len = random_data->ulServerRandomLen; serverData.bv_val = random_data->pServerRandom; if (ber_printf(msg, "t{OO}", 1|LBER_CLASS_CONTEXT|LBER_CONSTRUCTED, &clientData, &serverData) < 0) { TRACE_ERROR("Failed to encode message.\n"); goto cleanup; } break; default: TRACE_ERROR("Mechanism not supported.\n"); return -1; } rc = icsf_call(ld, reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPDVK, msg, &result); if (!rc) { handle_to_object_record(object, handle); /* Decode the result: * * DVKOutput ::= SEQUENCE { * parmsListChoice DVKOutputParmsList * } * * DVKOutputParmsList ::= CHOICE { * PKCS-DH_Output [0] NULL, * SSL-TLS_Output [1] OCTET STRING, * EC-DH_Output [2] NULL (not supported) * } */ if (mech->mechanism == CKM_SSL3_MASTER_KEY_DERIVE){ if (ber_scanf(result, "o", &bvParam) < 0 ){ TRACE_ERROR("Failed to Derive Key\n"); rc = -1; goto cleanup; } params = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)mech->pParameter; version = (CK_VERSION_PTR) (¶ms->pVersion); version->major = bvParam.bv_val[0]; version->minor = bvParam.bv_val[1]; } } rc = 0; cleanup: if (msg) ber_free(msg, 1); if (result) ber_free(result, 1); return rc; } /* * Devive multiple keys at once. */ int icsf_derive_multple_keys(LDAP *ld, int *p_reason, CK_MECHANISM_PTR mech, struct icsf_object_record *key, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, struct icsf_object_record *client_mac_handle, struct icsf_object_record *server_mac_handle, struct icsf_object_record *client_key_handle, struct icsf_object_record *server_key_handle, unsigned char *client_iv, unsigned char *server_iv) { int rc = 0; const char *rule_alg; char handle[ICSF_HANDLE_LEN]; char rule_array[ICSF_RULE_ITEM_LEN]; BerElement *msg = NULL; BerElement *result = NULL; ber_tag_t tag; CK_SSL3_KEY_MAT_PARAMS *params; struct berval bv_client_random_data; struct berval bv_server_random_data; struct berval bv_client_mac_handle = { 0, NULL }; struct berval bv_server_mac_handle = { 0, NULL }; struct berval bv_client_key_handle = { 0, NULL }; struct berval bv_server_key_handle = { 0, NULL }; struct berval bv_client_iv = { 0, NULL }; struct berval bv_server_iv = { 0, NULL }; CHECK_ARG_NON_NULL(ld); CHECK_ARG_NON_NULL(mech); CHECK_ARG_NON_NULL(key); object_record_to_handle(handle, key); /* Build rule array based on mechanism */ if (!(rule_alg = get_algorithm_rule(mech, 0))) { TRACE_ERROR("Invalid algorithm: %lu\n", (unsigned long) mech->mechanism); return -1; } strpad(rule_array, rule_alg, ICSF_RULE_ITEM_LEN, ' '); /* Build request */ if (!(msg = ber_alloc_t(LBER_USE_DER))) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return -1; } /** * DMKInput sequence. * * DMKInput ::= SEQUENCE { * attrList Attributes, * parmsListChoice DMKInputParmsList * } * * DMKInputParmsList ::= CHOICE { * SSL-KM_TLS-KM [0] SSL_TLS_DMKInputParmsList * } * * SSL_TLS_DMKInputParmsList ::= SEQUENCE { * export BOOLEAN, * macSize INTEGER, * keySize INTEGER, * ivSize INTEGER, * clientRandomData OCTET STRING, * serverRandomData OCTET STRING * } */ params = (CK_SSL3_KEY_MAT_PARAMS *) mech->pParameter; if (!params) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } rc = ber_printf(msg, "{"); if (rc < 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); goto done; } if (icsf_ber_put_attribute_list(msg, attrs, attrs_len) < 0) { TRACE_ERROR("icsf_ber_put_attribute_list failed\n"); goto done; } if (ber_printf(msg, "}") < 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); goto done; } tag = 0 | LBER_CLASS_CONTEXT | LBER_CONSTRUCTED; bv_client_random_data.bv_len = params->RandomInfo.ulClientRandomLen; bv_client_random_data.bv_val = params->RandomInfo.pClientRandom; bv_server_random_data.bv_len = params->RandomInfo.ulServerRandomLen; bv_server_random_data.bv_val = params->RandomInfo.pServerRandom; rc = ber_printf(msg, "t{biiiOO}", tag, (ber_int_t) params->bIsExport, (ber_int_t) params->ulMacSizeInBits, (ber_int_t) params->ulKeySizeInBits, (ber_int_t) params->ulIVSizeInBits, &bv_client_random_data, &bv_server_random_data); if (rc < 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); goto done; } /* Call request */ rc = icsf_call(ld, p_reason, handle, sizeof(handle), rule_array, sizeof(rule_array), ICSF_TAG_CSFPDMK, msg, &result); if (ICSF_RC_IS_ERROR(rc)) goto done; /* * DMKOutput ::= SEQUENCE { * parmsListChoice DMKOutputParmsList * } * * DMKOutputParmsList ::= CHOICE { * SSL-KM_TLS-KM [0] SSL_TLS_DMKOutputParmsList * } * * SSL_TLS_DMKOutputParmsList ::= SEQUENCE { * clientMACHandle OCTET STRING, * clientMACHandle OCTET STRING, * clientKeyHandle OCTET STRING, * serverKeyHandle OCTET STRING, * clientIV OCTET STRING, * serverIV OCTET STRING * } */ /* * Since we are copying the values after all, "m" has the advantage of * not needing to free the returned values... */ if (ber_scanf(result, "{t{mmmmmm}}", &tag, &bv_client_mac_handle, &bv_server_mac_handle, &bv_client_key_handle, &bv_server_key_handle, &bv_client_iv, &bv_server_iv) < 0) { rc = -1; TRACE_ERROR("Failed to decode the response.\n"); goto done; } /* Copy key handles */ if (bv_client_mac_handle.bv_len != ICSF_HANDLE_LEN || bv_server_mac_handle.bv_len != ICSF_HANDLE_LEN || bv_client_key_handle.bv_len != ICSF_HANDLE_LEN || bv_server_key_handle.bv_len != ICSF_HANDLE_LEN) { TRACE_ERROR("Invalid key handle size: %lu/%lu/%lu/%lu\n", (unsigned long) bv_client_mac_handle.bv_len, (unsigned long) bv_server_mac_handle.bv_len, (unsigned long) bv_client_key_handle.bv_len, (unsigned long) bv_server_key_handle.bv_len); rc = CKR_FUNCTION_FAILED; goto done; } handle_to_object_record(client_mac_handle, bv_client_mac_handle.bv_val); handle_to_object_record(server_mac_handle, bv_server_mac_handle.bv_val); handle_to_object_record(client_key_handle, bv_client_key_handle.bv_val); handle_to_object_record(server_key_handle, bv_server_key_handle.bv_val); /* Copy IVs */ if (params->ulIVSizeInBits) { if (8 * bv_client_iv.bv_len != params->ulIVSizeInBits) { TRACE_ERROR("Invalid client IV size: %lu\n", (unsigned long) bv_client_iv.bv_len); rc = CKR_FUNCTION_FAILED; goto done; } memcpy(params->pReturnedKeyMaterial->pIVClient, bv_client_iv.bv_val, bv_client_iv.bv_len); if (8 * bv_server_iv.bv_len != params->ulIVSizeInBits) { TRACE_ERROR("Invalid server IV size: %lu\n", (unsigned long) bv_server_iv.bv_len); rc = CKR_FUNCTION_FAILED; goto done; } memcpy(params->pReturnedKeyMaterial->pIVServer, bv_server_iv.bv_val, bv_server_iv.bv_len); } done: if (result) ber_free(result, 1); if (msg) ber_free(msg, 1); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/tok_struct.h0000644000175000017500000000552412630407154022466 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * openCryptoki ICSF token * * (C) COPYRIGHT International Business Machines Corp. 2013 * */ #ifndef __TOK_STRUCT_H #define __TOK_STRUCT_H #include #include "tok_spec_struct.h" #ifndef ICSF_CONFIG_PATH #ifndef CONFIG_PATH #warning CONFIG_PATH not set, using default (/usr/local/var/lib/opencryptoki) #define CONFIG_PATH "/usr/local/var/lib/opencryptoki" #endif // #ifndef CONFIG_PATH #define ICSF_CONFIG_PATH CONFIG_PATH "/icsf" #endif // #ifndef ICSF_CONFIG_PATH token_spec_t token_specific = { ICSF_CONFIG_PATH, "icsf", // Key token size (0 is default) 0, // Token data info: { FALSE, // Don't use per guest data store FALSE, // Don't use master key. Remaining fields are ignored 0, // Data store encryption NULL, // Default initialization vector for pins NULL, // Default initialization vector for objects }, NULL, // creatlock &token_specific_attach_shm, NULL, &token_specific_init_token_data, &token_specific_load_token_data, &token_specific_save_token_data, NULL, // rng NULL, // final NULL, // init token NULL, // login NULL, // logout NULL, // initpin NULL, // setpin // DES NULL, // des_key_gen NULL, // des_ecb NULL, // des_cb // Triple DES NULL, // tdes_ecb NULL, // tdes_cbc NULL, // tdes_ofb NULL, // tdes_cfb NULL, // tdes_mac // RSA NULL, // rsa_decrypt NULL, // rsa_encrypt NULL, // rsa_sign NULL, // rsa_verify NULL, // rsa_verify_recover NULL, // rsa_x509_decrypt NULL, // rsa_x509_encrypt NULL, // rsa_x509_sign NULL, // rsa_x509_verify NULL, // rsa_x509_verify_recover NULL, // rsa_oaep_decrypt NULL, // rsa_oaep_encrypt NULL, // rsa_pss_sign NULL, // rsa_pss_verify NULL, // rsa_generate_keypair // Elliptic Curve NULL, // ec_sign NULL, // ec_verify NULL, // ec_generate_keypair #ifndef NODH // DH NULL, // dh_pkcs_derive NULL, // dh_pkcs_key_pair_gen #else NULL, NULL, #endif // SHA NULL, // sha_init NULL, // sha NULL, // sha_update NULL, // sha_final //HMAC NULL, // hmac_sign_init NULL, // hmac_sign NULL, // hmac_sign_update NULL, // hmac_sign_final NULL, // hmac_verify_init NULL, // hmac_verify NULL, // hmac_verify_update NULL, // hmac_verify_final NULL, // generic_secret_key_gen // AES NULL, // aes_key_gen NULL, // aes_ecb NULL, // aes_cbc NULL, // aes_ctr NULL, // aes_gcm_init NULL, // aes_gcm NULL, // aes_gcm_update NULL, // aes_gcm_final NULL, // aes_ofb NULL, // aes_cfb NULL, // aes_mac // DSA NULL, // dsa_generate_keypair NULL, // dsa_sign NULL, // dsa_verify NULL, // get_mechanism_list NULL, // get_mechanism_info NULL // object_add }; #endif opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/Makefile.am0000644000175000017500000000555712630407154022156 0ustar xnoxxnox# Makefile.am for ICSF token for openCryptoki # nobase_lib_LTLIBRARIES=opencryptoki/stdll/libpkcs11_icsf.la AUTOMAKE_OPTIONS = gnu BUILT_SOURCES = icsf_config_parse.h AM_YFLAGS = -d -v # TODO: check which defines are really needed here # Not all versions of automake observe libname_CFLAGS opencryptoki_stdll_libpkcs11_icsf_la_CFLAGS = -DNOCDMF \ -DNODSA \ -DNODH \ -DMMAP \ -I. \ -I../../../include \ -I../../../include/pkcs11 \ -I../common \ -DSTDLL_NAME=\"icsftok\" opencryptoki_stdll_libpkcs11_icsf_la_LDFLAGS = -shared \ -Wl,-Bsymbolic \ -lcrypto \ -lldap \ -lpthread \ -lrt \ -llber opencryptoki_stdll_libpkcs11_icsf_la_SOURCES = ../common/asn1.c \ ../common/btree.c \ ../common/dig_mgr.c \ ../common/hwf_obj.c \ ../common/trace.c \ ../common/key.c \ ../common/mech_dh.c \ ../common/mech_rng.c \ new_host.c \ ../common/sign_mgr.c \ ../common/cert.c \ ../common/dp_obj.c \ ../common/mech_aes.c \ ../common/mech_rsa.c \ ../common/mech_ec.c \ ../common/obj_mgr.c \ ../common/template.c \ ../common/p11util.c \ ../common/data_obj.c \ ../common/encr_mgr.c \ ../common/key_mgr.c \ ../common/mech_md2.c \ ../common/mech_sha.c \ ../common/object.c \ ../common/decr_mgr.c \ ../common/globals.c \ ../common/sw_crypt.c \ ../common/loadsave.c \ ../common/utility.c \ ../common/mech_des.c \ ../common/mech_des3.c \ ../common/mech_md5.c \ ../common/mech_ssl3.c \ ../common/sess_mgr.c \ ../common/verify_mgr.c \ ../common/mech_list.c \ ../common/shared_memory.c\ ../common/attributes.c \ pbkdf.c \ icsf_specific.c \ icsf_config_parse.y \ icsf_config_lexer.l \ icsf.c noinst_HEADERS = icsf.h pbkdf.h install-data-hook: $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/opencryptoki/icsf cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ ln -sf libpkcs11_icsf.so PKCS11_ICSF.so $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/opencryptoki/icsf $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/icsf $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/icsf $(MKDIR_P) $(DESTDIR)$(lockdir)/icsf $(CHGRP) pkcs11 $(DESTDIR)$(lockdir)/icsf $(CHMOD) 0770 $(DESTDIR)$(lockdir)/icsf uninstall-hook: if test -d $(DESTDIR)$(libdir)/opencryptoki/stdll; then \ cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ rm -rf PKCS11_ICSF.so; fi opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/icsf_config_parse.y0000644000175000017500000004633012630407154023751 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2013 */ %{ #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "icsf_config.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" /* Global vars used as parameter to bison/flex parser. */ extern FILE *yyin; CK_SLOT_ID in_slot_id; int expected_slot; struct icsf_config out_config; char out_str_mech[64] = ""; int out_rc; /* Function used to report error. */ void yyerror(const char *str); /* */ struct ref { char *key; char *addr; size_t len; int required; }; struct ref refs[] = { { "token_name", out_config.name, sizeof(out_config.name), 1 }, { "token_manufacture", out_config.manuf, sizeof(out_config.manuf), 1 }, { "token_model", out_config.model, sizeof(out_config.model), 1 }, { "token_serial", out_config.serial, sizeof(out_config.serial), 1 }, { "mech", out_str_mech, sizeof(out_str_mech), 1 }, { "uri", out_config.uri, sizeof(out_config.uri), 0 }, { "binddn", out_config.dn, sizeof(out_config.dn), 0 }, { "cacert", out_config.ca_file, sizeof(out_config.ca_file), 0 }, { "cert", out_config.cert_file, sizeof(out_config.cert_file), 0 }, { "key", out_config.key_file, sizeof(out_config.key_file), 0 }, }; size_t refs_len = sizeof(refs)/sizeof(*refs); %} %union { unsigned int num; char *str; }; %token STRING %token INTEGER %token SLOT %token BEGIN_DEF %token END_DEF %token EQUAL %% slots: slots slot | ; slot: SLOT INTEGER { expected_slot = ($2 == in_slot_id); } BEGIN_DEF key_values END_DEF ; key_values: key_values key_value | ; key_value: STRING EQUAL STRING { char *key = $1; char *value = $3; size_t i; /* Check if this keyword belongs to the expected slot. */ if (!expected_slot || out_rc) goto done; /* Check key and value */ if (!key || !value) { out_rc = 1; TRACE_ERROR("Null %s found.\n", (!key) ? "key" : "value"); goto done; } /* Check if this keyword is expected. */ for (i = 0; i < strlen(key); i++) key[i] = tolower(key[i]); for(i = 0; i < refs_len; i++) { if (!strcmp(refs[i].key, key)) { strncpy(refs[i].addr, value, refs[i].len); refs[i].addr[refs[i].len - 1] = '\0'; goto done; } } out_rc = 1; TRACE_ERROR("Invalid keyword: %s\n", key); done: if (key) free(key); if (value) free(value); } ; %% void yyerror(const char *str) { out_rc = 1; fprintf(stderr,"Error: %s\n", str); TRACE_DEBUG("Failed to parse config file. %s\n", str); } static int check_keys(const char *conf_name) { size_t i; for (i = 0; i < refs_len; i++) { if (refs[i].required && *refs[i].addr == '\0') { TRACE_ERROR("Missing required key \"%s\" in \"%s\".\n", refs[i].key, conf_name); return -1; } } return 0; } /* * Parse config file using yacc. */ CK_RV parse_config_file(const char *conf_name, CK_SLOT_ID slot_id, struct icsf_config *data) { CK_RV rc; struct stat stat_info; /* Check is file exists. */ if (stat(conf_name, &stat_info) || !S_ISREG(stat_info.st_mode)) { TRACE_ERROR("File \"%s\" does not exist or is invalid.\n", conf_name); return CKR_FUNCTION_FAILED; } /* Set parameters used by the parser */ in_slot_id = slot_id; out_rc = 0; memset(&out_config, 0, sizeof(*data)); expected_slot = FALSE; /* Open config file */ yyin = fopen(conf_name, "r"); if (yyin == NULL) { TRACE_ERROR("Failed to open \"%s\".\n", conf_name); return CKR_FUNCTION_FAILED; } /* Parse config file */ rc = yyparse(); fclose(yyin); if (rc || out_rc) { TRACE_ERROR("Failed to parser file \"%s\" (%lu:%d).\n", conf_name, rc, out_rc); return CKR_FUNCTION_FAILED; } /* Check required keys*/ if (check_keys(conf_name)) return CKR_FUNCTION_FAILED; /* Parse mechanism type */ if (!strcmp(out_str_mech, "SIMPLE")) { out_config.mech = ICSF_CFG_MECH_SIMPLE; } else if (!strcmp(out_str_mech, "SASL")) { out_config.mech = ICSF_CFG_MECH_SASL; } else { TRACE_ERROR("Unknown mechanism type found: %s\n", out_str_mech); return CKR_FUNCTION_FAILED; } /* Copy output data. */ memcpy(data, &out_config, sizeof(*data)); #if DEBUG { size_t i; TRACE_DEVEL("ICSF configs for slot %lu.\n", slot_id); for (i = 0; i < refs_len; i++) { TRACE_DEVEL(" %s = \"%s\"\n", refs[i].key, refs[i].addr); } } #endif return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/icsf_stdll/new_host.c0000644000175000017500000025516312630407154022114 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2015 */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "stdll.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "pkcs32.h" #include "trace.h" #include "icsf_specific.h" #include "../api/apiproto.h" /* Declared in obj_mgr.c */ extern pthread_rwlock_t obj_list_rw_mutex; void SC_SetFunctionList(void); CK_ULONG usage_count = 0; /* track DLL usage */ void Fork_Initializer(void) { /* Initialize spinlock. */ XProcLock_Init(); /* Force logout. This cleans out the private session and list * and cleans out the private object map */ session_mgr_logout_all(); /* Clean out the public object map * First parm is no longer used.. */ object_mgr_purge_map((SESSION *)0xFFFF, PUBLIC); object_mgr_purge_map((SESSION *)0xFFFF, PRIVATE); /* This should clear the entire session list out */ session_mgr_close_all_sessions(); /* Clean out the global login state variable * When implemented... Although logout_all should clear this up. */ bt_destroy(&priv_token_obj_btree, object_free); bt_destroy(&publ_token_obj_btree, object_free); /* Need to do something to prevent the shared memory from * having the objects loaded again.... The most likely place * is in the obj_mgr file where the object is added to shared * memory (object_mgr_add_to_shm) a query should be done to * the appropriate object list.... */ } /* verify that the mech specified is in the * mech list for this token... */ CK_RV valid_mech(CK_MECHANISM_PTR m, CK_FLAGS f) { CK_RV rc; CK_MECHANISM_INFO info; if (m) { memset(&info, 0, sizeof(info)); rc = ock_generic_get_mechanism_info(m->mechanism, &info); if (rc != CKR_OK || !(info.flags & (f))) return CKR_MECHANISM_INVALID; } return CKR_OK; } /* In an STDLL this is called once for each card in the system * therefore the initialized only flags certain one time things. */ CK_RV ST_Initialize(void **FunctionList, CK_SLOT_ID SlotNumber, char *conf_name, struct trace_handle_t t) { CK_RV rc = CKR_OK; if ((rc = check_user_and_group()) != CKR_OK) return rc; /* assume that the upper API prevents multiple calls of initialize * since that only happens on C_Initialize and that is the * resonsibility of the upper layer.. */ initialized = FALSE; /* So the rest of the code works correctly */ /* If we're not already initialized, grab the mutex and do the * initialization. Check to see if another thread did so while we * were waiting... * * One of the things we do during initialization is create the mutex * for PKCS#11 operations; until we do so, we have to use the native * mutex... */ if (pthread_mutex_lock(&native_mutex)) { rc = CKR_FUNCTION_FAILED; TRACE_ERROR("Failed to lock mutex.\n"); } /* SAB need to call Fork_Initializer here * instead of at the end of the loop... * it may also need to call destroy of the following 3 mutexes.. * it may not matter... */ Fork_Initializer(); /* set trace info */ set_trace(t); MY_CreateMutex(&pkcs_mutex); MY_CreateMutex(&obj_list_mutex); if (pthread_rwlock_init(&obj_list_rw_mutex, NULL)) { TRACE_ERROR("Mutex lock failed.\n"); } MY_CreateMutex(&sess_list_mutex); MY_CreateMutex(&login_mutex); /* Create lockfile */ if (CreateXProcLock() != CKR_OK) { TRACE_ERROR("Process lock failed.\n"); goto done; } init_data_store((char *)PK_DIR); /* Handle global initialization issues first if we have not * been initialized. */ if (initialized == FALSE) { rc = attach_shm(SlotNumber, &global_shm); if (rc != CKR_OK) { TRACE_ERROR("Could not attach to shared memory.\n"); goto done; } nv_token_data = &global_shm->nv_token_data; initialized = TRUE; SC_SetFunctionList(); rc = icsftok_init(SlotNumber, conf_name); if (rc != 0) { *FunctionList = NULL; TRACE_DEVEL("Token Specific Init failed.\n"); goto done; } } rc = load_token_data(SlotNumber); if (rc != CKR_OK) { *FunctionList = NULL; TRACE_DEVEL("Failed to load token data.\n"); goto done; } /* no need to return error here, we load the token data we can * and syslog the rest */ load_public_token_objects(); XProcLock(); global_shm->publ_loaded = TRUE; XProcUnLock(); init_slotInfo(); usage_count++; (*FunctionList) = &function_list; done: if (pthread_mutex_unlock(&native_mutex)) { TRACE_ERROR("Failed to unlock mutex.\n"); rc = CKR_FUNCTION_FAILED; } return rc; } /* What does this really have to do in this new token... probably * need to close the adapters that are opened, and clear the other * stuff */ CK_RV SC_Finalize(CK_SLOT_ID sid) { CK_RV rc, rc_mutex; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } rc = MY_LockMutex(&pkcs_mutex); if (rc != CKR_OK) { TRACE_ERROR("Mutex lock failed.\n"); return rc; } /* If somebody else has taken care of things, leave... */ if (initialized == FALSE) { MY_UnlockMutex(&pkcs_mutex); TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } usage_count--; if (usage_count == 0) { initialized = FALSE; } session_mgr_close_all_sessions(); object_mgr_purge_token_objects(); detach_shm(); /* close spin lock file */ CloseXProcLock(); rc = icsftok_close_all_sessions(); if (rc != CKR_OK) { TRACE_ERROR("Token specific final call failed.\n"); goto done; } done: rc_mutex = MY_UnlockMutex(&pkcs_mutex); if (rc_mutex != CKR_OK) { TRACE_ERROR("Mutex unlock failed.\n"); return rc_mutex; } return rc; } CK_RV SC_GetTokenInfo(CK_SLOT_ID sid, CK_TOKEN_INFO_PTR pInfo) { CK_RV rc = CKR_OK; time_t now; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto done; } copy_token_contents_sensibly(pInfo, nv_token_data); /* Set the time */ now = time ((time_t *)NULL); strftime((char *)pInfo->utcTime, 16, "%X", localtime(&now)); done: TRACE_INFO("C_GetTokenInfo: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } /* * Get the mechanism type list for the current token. */ CK_RV SC_GetMechanismList(CK_SLOT_ID sid, CK_MECHANISM_TYPE_PTR pMechList, CK_ULONG_PTR count) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto out; } if (count == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto out; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto out; } rc = ock_generic_get_mechanism_list(pMechList, count); if (rc == CKR_OK) { /* To accomodate certain special cases, we may need to * make adjustments to the token's mechanism list. */ mechanism_list_transformations(pMechList, count); } out: TRACE_INFO("C_GetMechanismList: rc = 0x%08lx, # mechanisms: %lu\n", rc, *count); return rc; } /* * Get the mechanism info for the current type and token. */ CK_RV SC_GetMechanismInfo(CK_SLOT_ID sid, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto out; } if (pInfo == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto out; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto out; } rc = ock_generic_get_mechanism_info(type, pInfo); out: TRACE_INFO("C_GetMechanismInfo: rc = 0x%08lx, mech type = 0x%08lx\n", rc, type); return rc; } /* * This routine should only be called if no other processes are * attached to the token. we need to somehow check that this is the * only process Meta API should prevent this since it knows session * states in the shared memory. */ CK_RV SC_InitToken(CK_SLOT_ID sid, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPin || !pLabel) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (nv_token_data->token_info.flags & CKF_SO_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } rc = icsftok_init_token(sid, pPin, ulPinLen, pLabel); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; } done: TRACE_INFO("C_InitToken: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_InitPIN(ST_SESSION_HANDLE *sSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; CK_FLAGS_32 *flags = NULL; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPin) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_locked(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } if (sess->session_info.state != CKS_RW_SO_FUNCTIONS) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } rc = icsftok_init_pin(sess, pPin, ulPinLen); if (rc == CKR_OK) { flags = &nv_token_data->token_info.flags; *flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW); rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) TRACE_DEVEL("Failed to save token data.\n"); } done: TRACE_INFO("C_InitPin: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_SetPIN(ST_SESSION_HANDLE *sSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_locked(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } rc = icsftok_set_pin(sess, pOldPin, ulOldLen, pNewPin, ulNewLen); done: TRACE_INFO("C_SetPin: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_OpenSession(CK_SLOT_ID sid, CK_FLAGS flags, CK_SESSION_HANDLE_PTR phSession) { CK_BBOOL locked = FALSE; CK_RV rc = CKR_OK; SESSION *sess; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (phSession == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto done; } flags |= CKF_SERIAL_SESSION; if ((flags & CKF_RW_SESSION) == 0) { if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_WRITE_SO_EXISTS)); rc = CKR_SESSION_READ_WRITE_SO_EXISTS; goto done; } } /* Get the mutex because we may modify the pid_list */ rc = MY_LockMutex(&pkcs_mutex); if (rc != CKR_OK) { TRACE_ERROR("Failed to get mutex lock.\n"); goto done; } locked = TRUE; MY_UnlockMutex(&pkcs_mutex); locked = FALSE; rc = session_mgr_new(flags, sid, phSession); if (rc != CKR_OK) { TRACE_DEVEL("session_mgr_new() failed\n"); goto done; } sess = session_mgr_find(*phSession); rc = icsftok_open_session(sess); done: if (locked) MY_UnlockMutex(&pkcs_mutex); TRACE_INFO("C_OpenSession: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_CloseSession(ST_SESSION_HANDLE *sSession) { CK_RV rc = CKR_OK; SESSION *sess = NULL; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); rc = icsftok_close_session(sess); if (rc) goto done; rc = session_mgr_close_session(sSession->sessionh); done: TRACE_INFO("C_CloseSession: rc = 0x%08lx sess = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_CloseAllSessions(CK_SLOT_ID sid) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } rc = session_mgr_close_all_sessions(); if (rc != CKR_OK) { TRACE_DEVEL("session_mgr_close_all_sessions() failed.\n"); goto done; } rc = icsftok_close_all_sessions(); if (rc != CKR_OK) TRACE_DEVEL("Failed to remove icsf specific session_states.\n"); done: TRACE_INFO("C_CloseAllSessions: rc = 0x%08lx slot = %lu\n", rc, sid); return rc; } CK_RV SC_GetSessionInfo(ST_SESSION_HANDLE *sSession, CK_SESSION_INFO_PTR pInfo) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } memcpy(pInfo, &sess->session_info, sizeof(CK_SESSION_INFO)); done: TRACE_INFO("C_GetSessionInfo: session = %lu\n", sSession->sessionh); return rc; } CK_RV SC_GetOperationState(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulOperationStateLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (!pOperationState) length_only = TRUE; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = session_mgr_get_op_state(sess, length_only, pOperationState, pulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_get_op_state() failed.\n"); done: TRACE_INFO("C_GetOperationState: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_SetOperationState(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pOperationState || (ulOperationStateLen == 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey, pOperationState, ulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_set_op_state() failed.\n"); done: TRACE_INFO("C_SetOperationState: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_Login(ST_SESSION_HANDLE *sSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { SESSION *sess = NULL; CK_FLAGS_32 *flags = NULL; CK_RV rc = CKR_OK; rc = MY_LockMutex(&login_mutex); if (rc != CKR_OK) { TRACE_ERROR("Failed to get mutex lock.\n"); return CKR_FUNCTION_FAILED; } if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } flags = &nv_token_data->token_info.flags; if (!pPin || ulPinLen > MAX_PIN_LEN) { set_login_flags(userType, flags); TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* PKCS #11 v2.01 requires that all sessions have the same login status: * --> all sessions are public, all are SO or all are USER */ if (userType == CKU_USER) { if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_ANOTHER_ALREADY_LOGGED_IN)); rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } if (session_mgr_user_session_exists()) { TRACE_ERROR("%s\n",ock_err(ERR_USER_ALREADY_LOGGED_IN)); rc = CKR_USER_ALREADY_LOGGED_IN; } } else if (userType == CKU_SO) { if (session_mgr_user_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_ANOTHER_ALREADY_LOGGED_IN)); rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n",ock_err(ERR_USER_ALREADY_LOGGED_IN)); rc = CKR_USER_ALREADY_LOGGED_IN; } if (session_mgr_readonly_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY_EXISTS)); rc = CKR_SESSION_READ_ONLY_EXISTS; } } else { rc = CKR_USER_TYPE_INVALID; TRACE_ERROR("%s\n", ock_err(ERR_USER_TYPE_INVALID)); } if (rc != CKR_OK) goto done; if (userType == CKU_USER) { if (*flags & CKF_USER_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } rc = icsftok_login(sess, userType, pPin, ulPinLen); if (rc == CKR_OK) { *flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW); } else if (rc == CKR_PIN_INCORRECT) set_login_flags(userType, flags); } else { if (*flags & CKF_SO_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } rc = icsftok_login(sess, userType, pPin, ulPinLen); if (rc == CKR_OK) { *flags &= ~(CKF_SO_PIN_LOCKED | CKF_SO_PIN_FINAL_TRY | CKF_SO_PIN_COUNT_LOW); } else if (rc == CKR_PIN_INCORRECT) set_login_flags(userType, flags); } done: if (rc == CKR_OK) { rc = session_mgr_login_all(userType); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_login_all failed.\n"); else rc = icsf_get_handles(sess->session_info.slotID); } TRACE_INFO("C_Login: rc = 0x%08lx\n", rc); save_token_data(sess->session_info.slotID); MY_UnlockMutex(&login_mutex); return rc; } CK_RV SC_Logout(ST_SESSION_HANDLE *sSession) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* all sessions have the same state so we just have to check one */ if (session_mgr_public_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } rc = session_mgr_logout_all(); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_logout_all failed.\n"); memset(user_pin_md5, 0x0, MD5_HASH_SIZE); memset(so_pin_md5, 0x0, MD5_HASH_SIZE); object_mgr_purge_private_token_objects(); done: TRACE_INFO("C_Logout: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_CreateObject(ST_SESSION_HANDLE *sSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = icsftok_create_object(sess, pTemplate, ulCount, phObject); if (rc != CKR_OK) TRACE_DEVEL("icsftok_create_object() failed.\n"); done: TRACE_INFO("C_CreateObject: rc = 0x%08lx\n", rc); #ifdef DEBUG int i; for (i = 0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { TRACE_DEBUG("Object Type: 0x%02lx\n", *((CK_ULONG *) pTemplate[i].pValue)); } } if (rc == CKR_OK) TRACE_DEBUG("Handle: %lu\n", *phObject); #endif return rc; } CK_RV SC_CopyObject(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = icsftok_copy_object(sess, pTemplate, ulCount, hObject, phNewObject); if (rc != CKR_OK) TRACE_DEVEL("icsftok_copy_object() failed\n"); done: TRACE_INFO("C_CopyObject:rc = 0x%08lx, old handle = %lu, " "new handle = %lu\n", rc, hObject, *phNewObject); return rc; } CK_RV SC_DestroyObject(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = icsftok_destroy_object(sess, hObject); if (rc != CKR_OK) TRACE_DEVEL("icsftok_destroy_object() failed\n"); done: TRACE_INFO("C_DestroyObject:rc = 0x%08lx, handle = %lu\n", rc, hObject); return rc; } CK_RV SC_GetObjectSize(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_GetAttributeValue(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = icsftok_get_attribute_value(sess, hObject, pTemplate, ulCount); if (rc != CKR_OK) TRACE_DEVEL("icsftok_get_attribute_value() failed.\n"); done: TRACE_INFO("C_GetAttributeValue: rc = 0x%08lx, handle = %lu\n", rc, hObject); #ifdef DEBUG int i; CK_BYTE *ptr = NULL; CK_ATTRIBUTE *attr = NULL; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_SetAttributeValue(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = icsftok_set_attribute_value(sess, hObject, pTemplate, ulCount); if (rc != CKR_OK) TRACE_DEVEL("icsftok_set_attribute_values() failed.\n"); done: TRACE_INFO("C_SetAttributeValue: rc = 0x%08lx, handle = %lu\n", rc, hObject); #ifdef DEBUG int i; CK_ATTRIBUTE *attr = NULL; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_FindObjectsInit(ST_SESSION_HANDLE *sSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->find_active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = icsftok_find_objects_init(sess, pTemplate, ulCount); done: TRACE_INFO("C_FindObjectsInit: rc = 0x%08lx\n", rc); #ifdef DEBUG int i; CK_ATTRIBUTE *attr = NULL; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_FindObjects(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { SESSION *sess = NULL; CK_ULONG count = 0; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!phObject || !pulObjectCount) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->find_active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!sess->find_list) { TRACE_DEVEL("sess->find_list is NULL.\n"); rc = CKR_FUNCTION_FAILED; goto done; } count = MIN(ulMaxObjectCount, (sess->find_count - sess->find_idx)); memcpy(phObject, sess->find_list + sess->find_idx, count * sizeof(CK_OBJECT_HANDLE)); *pulObjectCount = count; sess->find_idx += count; rc = CKR_OK; done: TRACE_INFO("C_FindObjects: rc = 0x%08lx, returned %lu objects\n", rc, count); return rc; } CK_RV SC_FindObjectsFinal(ST_SESSION_HANDLE *sSession) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->find_active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (sess->find_list) free(sess->find_list); sess->find_list = NULL; sess->find_len = 0; sess->find_idx = 0; sess->find_active = FALSE; rc = CKR_OK; done: TRACE_INFO("C_FindObjectsFinal: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_EncryptInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_ENCRYPT); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->encr_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = icsftok_encrypt_init(sess, pMechanism, hKey); done: TRACE_INFO("C_EncryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Encrypt(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pulEncryptedDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pEncryptedData) length_only = TRUE; rc = icsftok_encrypt(sess, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_encrypt() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_EncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if ((!pPart && ulPartLen != 0) || !pulEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = icsftok_encrypt_update(sess, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_encrypt_update() failed.\n"); done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); return rc; } CK_RV SC_EncryptFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulLastEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pLastEncryptedPart) length_only = TRUE; rc = icsftok_encrypt_final(sess, pLastEncryptedPart, pulLastEncryptedPartLen); if (rc != CKR_OK) TRACE_ERROR("icsftok_encrypt_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); return rc; } CK_RV SC_DecryptInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DECRYPT); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->decr_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = icsftok_decrypt_init(sess, pMechanism, hKey); if (rc != CKR_OK) TRACE_DEVEL("icsftok_decrypt_init() failed.\n"); done: TRACE_INFO("C_DecryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Decrypt(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pEncryptedData || !pulDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pData) length_only = TRUE; rc = icsftok_decrypt(sess, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_decrypt() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulEncryptedDataLen); return rc; } CK_RV SC_DecryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if ((!pEncryptedPart && ulEncryptedPartLen != 0) || !pulPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = icsftok_decrypt_update(sess, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_decrypt_update() failed.\n"); done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulEncryptedPartLen); return rc; } CK_RV SC_DecryptFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulLastPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pLastPart) length_only = TRUE; rc = icsftok_decrypt_final(sess, pLastPart, pulLastPartLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_decrypt_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, *pulLastPartLen); return rc; } CK_RV SC_DigestInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DIGEST); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->digest_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = digest_mgr_init(sess, &sess->digest_ctx, pMechanism); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_init() failed.\n"); done: TRACE_INFO("C_DigestInit: rc = 0x%08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Digest(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } /* Netscape has been known to pass a null pData to DigestUpdate * but never for Digest. It doesn't really make sense to allow it here */ if (!pData || !pulDigestLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pDigest) length_only = TRUE; rc = digest_mgr_digest(sess, length_only, &sess->digest_ctx, pData, ulDataLen, pDigest, pulDigestLen); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest() failed.\n"); done: TRACE_INFO("C_Digest: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_DigestUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } /* If there is data to hash, do so. */ if (ulPartLen) { rc = digest_mgr_digest_update(sess, &sess->digest_ctx, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest_update() failed.\n"); } done: TRACE_INFO("C_DigestUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_DigestKey(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = digest_mgr_digest_key(sess, &sess->digest_ctx, hKey); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest_key() failed.\n"); done: TRACE_INFO("C_DigestKey: rc = %08lx, sess = %ld, key = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, hKey); return rc; } CK_RV SC_DigestFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulDigestLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pDigest) length_only = TRUE; rc = digest_mgr_digest_final(sess, length_only, &sess->digest_ctx, pDigest, pulDigestLen); if (rc != CKR_OK) TRACE_ERROR("digest_mgr_digest_final() failed.\n"); done: TRACE_INFO("C_DigestFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_SignInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism ) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = valid_mech(pMechanism, CKF_SIGN); if (rc != CKR_OK) goto done; if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->sign_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); goto done; } rc = icsftok_sign_init(sess, pMechanism, hKey); if (rc != CKR_OK) TRACE_DEVEL("icsftok_sign_init() failed.\n"); done: TRACE_INFO("C_SignInit: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Sign(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = icsftok_sign(sess, pData, ulDataLen, pSignature, pulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_sign() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_Sign: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_SignUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = icsftok_sign_update(sess, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_sign_update() failed.\n"); done: if (rc != CKR_OK) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_SignFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = icsftok_sign_final(sess, pSignature, pulSignatureLen); if (rc != CKR_OK) TRACE_ERROR("icsftok_sign_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_SignRecoverInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_SignRecover(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_VerifyInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism ) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_VERIFY); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->verify_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); goto done; } rc = icsftok_verify_init(sess, pMechanism, hKey); if (rc != CKR_OK) TRACE_DEVEL("icsftok_verify_init() failed.\n"); done: TRACE_INFO("C_VerifyInit: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Verify(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pSignature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = icsftok_verify(sess, pData, ulDataLen, pSignature, ulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_verify() failed.\n"); done: verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_Verify: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_VerifyUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = icsftok_verify_update(sess, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_verify_update() failed.\n"); done: if (rc != CKR_OK) verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_VerifyFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pSignature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = icsftok_verify_final(sess, pSignature, ulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("icsftok_verify_final() failed.\n"); done: verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_VerifyRecoverInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_VerifyRecover(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_DigestEncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_DecryptDigestUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_SignEncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_DecryptVerifyUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_GenerateKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !phKey || (pTemplate == NULL && ulCount != 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_GENERATE); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = icsftok_generate_key(sess, pMechanism, pTemplate, ulCount, phKey); if (rc != CKR_OK) TRACE_DEVEL("icsftok_generate_key() failed.\n"); done: TRACE_INFO("C_GenerateKey: rc = %08lx, sess = %ld, mech = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, pMechanism->mechanism); #ifdef DEBUG int i; CK_ATTRIBUTE *attr = NULL; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx,Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) { TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } } #endif return rc; } CK_RV SC_GenerateKeyPair(ST_SESSION_HANDLE *sSession, 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) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !phPublicKey || !phPrivateKey || (!pPublicKeyTemplate && (ulPublicKeyAttributeCount != 0)) || (!pPrivateKeyTemplate && (ulPrivateKeyAttributeCount != 0))) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_GENERATE_KEY_PAIR); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = icsftok_generate_key_pair(sess, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); if (rc != CKR_OK) TRACE_DEVEL("icsftok_generate_key_pair() faild.\n"); done: TRACE_INFO("C_GenerateKeyPair: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL) ? -1 : ((CK_LONG) sess->handle), pMechanism->mechanism); #ifdef DEBUG int i; CK_ATTRIBUTE *attr = NULL; if (rc == CKR_OK) { TRACE_DEBUG("Public handle: %lu, Private handle: %lu\n", *phPublicKey, *phPrivateKey); } TRACE_DEBUG("Public Template:\n"); attr = pPublicKeyTemplate; for (i = 0; i < ulPublicKeyAttributeCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } TRACE_DEBUG("Private Template:\n"); attr = pPublicKeyTemplate; for (i = 0; i < ulPublicKeyAttributeCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_WrapKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !pulWrappedKeyLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_WRAP); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = icsftok_wrap_key(sess, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen); if (rc != CKR_OK) TRACE_DEVEL("*_wrap_key() failed.\n"); done: TRACE_INFO("C_WrapKey: rc = %08lx, sess = %ld, encrypting key = %lu, " "wrapped key = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, hWrappingKey, hKey); return rc; } CK_RV SC_UnwrapKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !pWrappedKey || (!pTemplate && ulCount != 0) || !phKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_UNWRAP); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = icsftok_unwrap_key(sess, pMechanism, pTemplate, ulCount, pWrappedKey, ulWrappedKeyLen, hUnwrappingKey, phKey); if (rc != CKR_OK) TRACE_DEVEL("icsftok_unwrap_key() failed.\n"); done: TRACE_INFO("C_UnwrapKey: rc = %08lx, sess = %ld, decrypting key = %lu," "unwrapped key = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, hUnwrappingKey, *phKey); #ifdef DEBUG int i; CK_ATTRIBUTE *attr = NULL; CK_BYTE *ptr = NULL; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_DeriveKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !phKey || (!pTemplate && ulCount != 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DERIVE); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = icsftok_derive_key(sess, pMechanism, hBaseKey, phKey, pTemplate, ulCount); if (rc != CKR_OK) TRACE_DEVEL("icsftok_derive_key() failed.\n"); done: TRACE_INFO("C_DeriveKey: rc = %08lx, sess = %ld, mech = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); #ifdef DEBUG int i; CK_ATTRIBUTE *attr = NULL; CK_BYTE *ptr = NULL; if (rc == CKR_OK) { switch (pMechanism->mechanism) { case CKM_SSL3_KEY_AND_MAC_DERIVE: { CK_SSL3_KEY_MAT_PARAMS *pReq; CK_SSL3_KEY_MAT_OUT *pPtr; pReq = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; pPtr = pReq->pReturnedKeyMaterial; TRACE_DEBUG("Client MAC key: %lu, Server MAC key: %lu, " "Client Key: %lu, Server Key: %lu\n", pPtr->hClientMacSecret, pPtr->hServerMacSecret, pPtr->hClientKey, pPtr->hServerKey); } break; case CKM_DH_PKCS_DERIVE: { TRACE_DEBUG("DH Shared Secret:\n"); } break ; default: TRACE_DEBUG("Derived key: %lu\n", *phKey); } } attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif /* DEBUG */ return rc; } CK_RV SC_SeedRandom(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_RANDOM_SEED_NOT_SUPPORTED)); return CKR_RANDOM_SEED_NOT_SUPPORTED; } CK_RV SC_GenerateRandom(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pRandomData && ulRandomLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = rng_generate(pRandomData, ulRandomLen); if (rc != CKR_OK) TRACE_DEVEL("rng_generate() failed.\n"); done: TRACE_INFO("C_GenerateRandom: rc = %08lx, %lu bytes\n", rc, ulRandomLen); return rc; } CK_RV SC_GetFunctionStatus(ST_SESSION_HANDLE *sSession) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL)); return CKR_FUNCTION_NOT_PARALLEL; } CK_RV SC_CancelFunction(ST_SESSION_HANDLE *sSession) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL)); return CKR_FUNCTION_NOT_PARALLEL; } void SC_SetFunctionList(void) { function_list.ST_Initialize = (void *)ST_Initialize; function_list.ST_GetTokenInfo = SC_GetTokenInfo; function_list.ST_GetMechanismList = SC_GetMechanismList; function_list.ST_GetMechanismInfo = SC_GetMechanismInfo; function_list.ST_InitToken = SC_InitToken; function_list.ST_InitPIN = SC_InitPIN; function_list.ST_SetPIN = SC_SetPIN; function_list.ST_OpenSession = SC_OpenSession; function_list.ST_CloseSession = SC_CloseSession; function_list.ST_GetSessionInfo = SC_GetSessionInfo; function_list.ST_GetOperationState = SC_GetOperationState; function_list.ST_SetOperationState = SC_SetOperationState; function_list.ST_Login = SC_Login; function_list.ST_Logout = SC_Logout; function_list.ST_CreateObject = SC_CreateObject; function_list.ST_CopyObject = SC_CopyObject; function_list.ST_DestroyObject = SC_DestroyObject; function_list.ST_GetObjectSize = SC_GetObjectSize; function_list.ST_GetAttributeValue = SC_GetAttributeValue; function_list.ST_SetAttributeValue = SC_SetAttributeValue; function_list.ST_FindObjectsInit = SC_FindObjectsInit; function_list.ST_FindObjects = SC_FindObjects; function_list.ST_FindObjectsFinal = SC_FindObjectsFinal; function_list.ST_EncryptInit = SC_EncryptInit; function_list.ST_Encrypt = SC_Encrypt; function_list.ST_EncryptUpdate = SC_EncryptUpdate; function_list.ST_EncryptFinal = SC_EncryptFinal; function_list.ST_DecryptInit = SC_DecryptInit; function_list.ST_Decrypt = SC_Decrypt; function_list.ST_DecryptUpdate = SC_DecryptUpdate; function_list.ST_DecryptFinal = SC_DecryptFinal; function_list.ST_DigestInit = SC_DigestInit; function_list.ST_Digest = SC_Digest; function_list.ST_DigestUpdate = SC_DigestUpdate; function_list.ST_DigestKey = SC_DigestKey; function_list.ST_DigestFinal = SC_DigestFinal; function_list.ST_SignInit = SC_SignInit; function_list.ST_Sign = SC_Sign; function_list.ST_SignUpdate = SC_SignUpdate; function_list.ST_SignFinal = SC_SignFinal; function_list.ST_SignRecoverInit = SC_SignRecoverInit; function_list.ST_SignRecover = SC_SignRecover; function_list.ST_VerifyInit = SC_VerifyInit; function_list.ST_Verify = SC_Verify; function_list.ST_VerifyUpdate = SC_VerifyUpdate; function_list.ST_VerifyFinal = SC_VerifyFinal; function_list.ST_VerifyRecoverInit = SC_VerifyRecoverInit; function_list.ST_VerifyRecover = SC_VerifyRecover; function_list.ST_DigestEncryptUpdate = NULL; // SC_DigestEncryptUpdate; function_list.ST_DecryptDigestUpdate = NULL; // SC_DecryptDigestUpdate; function_list.ST_SignEncryptUpdate = NULL; //SC_SignEncryptUpdate; function_list.ST_DecryptVerifyUpdate = NULL; // SC_DecryptVerifyUpdate; function_list.ST_GenerateKey = SC_GenerateKey; function_list.ST_GenerateKeyPair = SC_GenerateKeyPair; function_list.ST_WrapKey = SC_WrapKey; function_list.ST_UnwrapKey = SC_UnwrapKey; function_list.ST_DeriveKey = SC_DeriveKey; function_list.ST_SeedRandom = SC_SeedRandom ; function_list.ST_GenerateRandom = SC_GenerateRandom; function_list.ST_GetFunctionStatus = NULL; // SC_GetFunctionStatus; function_list.ST_CancelFunction = NULL; // SC_CancelFunction; } opencryptoki+dfsg/usr/lib/pkcs11/Makefile.am0000644000175000017500000000061312630407154020014 0ustar xnoxxnoxif ENABLE_ICATOK ICA_DLL = ica_s390_stdll endif if ENABLE_EP11TOK EP11_DLL = ep11_stdll endif if ENABLE_SWTOK SW_DLL = soft_stdll endif if ENABLE_TPMTOK TPM_DLL = tpm_stdll endif if ENABLE_CCATOK CCA_DLL = cca_stdll endif if ENABLE_ICSFTOK ICSF_DLL = icsf_stdll endif if ENABLE_LIBRARY API = api endif SUBDIRS = $(API) $(SW_DLL) $(ICA_DLL) $(TPM_DLL) $(CCA_DLL) $(ICSF_DLL) $(EP11_DLL) opencryptoki+dfsg/usr/lib/pkcs11/common/0000755000175000017500000000000012630407154017250 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/common/key.c0000755000175000017500000052256612630407154020227 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: key.c // // Functions contained within: // // key_object_check_required_attributes // key_object_set_default_attributes // key_object_validate_attribute // // publ_key_check_required_attributes // publ_key_set_default_attributes // publ_key_validate_attribute // // priv_key_check_required_attributes // priv_key_set_default_attributes // priv_key_validate_attribute // // secret_key_check_required_attributes // secret_key_set_default_attributes // secret_key_validate_attribute // // rsa_publ_check_required_attributes // rsa_publ_validate_attribute // rsa_priv_check_required_attributes // rsa_priv_validate_attribute // rsa_priv_check_exportability // // dsa_publ_check_required_attributes // dsa_publ_validate_attribute // dsa_priv_check_required_attributes // dsa_priv_validate_attribute // dsa_priv_check_exportability // // ecdsa_publ_check_required_attributes // ecdsa_publ_validate_attribute // ecdsa_priv_checK_required_attributes // ecdsa_priv_validate_attribute // ecdsa_priv_check_exportability // // dh_publ_check_required_attributes // dh_publ_validate_attribute // dh_priv_check_required_attributes // dh_priv_validate_attribute // dh_priv_check_exportability // // kea_publ_check_required_attributes // kea_publ_validate_attribute // kea_priv_check_required_attributes // kea_priv_validate_attribute // kea_priv_check_exportability // // generic_secret_check_required_attributes // generic_secret_validate_attribute // generic_secret_set_default_attributes // // rc2_check_required_attributes // rc2_validate_attribute // rc2_priv_check_exportability // // rc4_check_required_attributes // rc4_validate_attribute // rc4_priv_check_exportability // // rc5_check_required_attributes // rc5_validate_attribute // rc5_priv_check_exportability // // des_check_required_attributes // des_validate_attribute // des_priv_check_exportability // // des2_check_required_attributes // des2_validate_attribute // des2_priv_check_exportability // // des3_check_required_attributes // des3_validate_attribute // des3_priv_check_exportability // // cast_check_required_attributes // cast_validate_attribute // cast_priv_check_exportability // // cast3_check_required_attributes // cast3_validate_attribute // cast3_priv_check_exportability // // cast5_check_required_attributes // cast5_validate_attribute // cast5_priv_check_exportability // // idea_check_required_attributes // idea_validate_attribute // idea_priv_check_exportability // // cdmf_check_required_attributes // cdmf_validate_attribute // cdmf_priv_check_exportability // // skipjack_check_required_attributes // skipjack_validate_attribute // skipjack_priv_check_exportability // // baton_check_required_attributes // baton_validate_attribute // baton_priv_check_exportability // // juniper_check_required_attributes // juniper_validate_attribute // juniper_priv_check_exportability // #include #include #include // for memcmp() et al #include "pkcs11types.h" #include "p11util.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" #include "tok_spec_struct.h" // key_object_check_required_attributes() // // Check required common attributes for key objects // CK_RV key_object_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_KEY_TYPE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return template_check_required_base_attributes( tmpl, mode ); } // key_object_set_default_attributes() // CK_RV key_object_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * id_attr = NULL; CK_ATTRIBUTE * sdate_attr = NULL; CK_ATTRIBUTE * edate_attr = NULL; CK_ATTRIBUTE * derive_attr = NULL; CK_ATTRIBUTE * local_attr = NULL; // satisfy the compiler // if (mode) id_attr = NULL; id_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); sdate_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); edate_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); derive_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); local_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!id_attr || !sdate_attr || !edate_attr || !derive_attr || !local_attr) { if (id_attr) free( id_attr ); if (sdate_attr) free( sdate_attr ); if (edate_attr) free( edate_attr ); if (derive_attr) free( derive_attr ); if (local_attr) free( local_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } id_attr->type = CKA_ID; id_attr->ulValueLen = 0; id_attr->pValue = NULL; sdate_attr->type = CKA_START_DATE; sdate_attr->ulValueLen = 0; sdate_attr->pValue = NULL; edate_attr->type = CKA_END_DATE; edate_attr->ulValueLen = 0; edate_attr->pValue = NULL; derive_attr->type = CKA_DERIVE; derive_attr->ulValueLen = sizeof(CK_BBOOL); derive_attr->pValue = (CK_BYTE *)derive_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)derive_attr->pValue = FALSE; local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = FALSE; template_update_attribute( tmpl, id_attr ); template_update_attribute( tmpl, sdate_attr ); template_update_attribute( tmpl, edate_attr ); template_update_attribute( tmpl, derive_attr ); template_update_attribute( tmpl, local_attr ); return CKR_OK; } // key_object_validate_attribute() // CK_RV key_object_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_KEY_TYPE: if (mode == MODE_CREATE || mode == MODE_DERIVE || mode == MODE_KEYGEN || mode == MODE_UNWRAP) return CKR_OK; else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_ID: case CKA_START_DATE: case CKA_END_DATE: case CKA_DERIVE: return CKR_OK; case CKA_LOCAL: // CKA_LOCAL is only set by the key-generate routine // TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; default: return template_validate_base_attribute( tmpl, attr, mode ); } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; } // publ_key_check_required_attributes() // CK_RV publ_key_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { // CKO_PUBLIC_KEY has no required attributes // return key_object_check_required_attributes( tmpl, mode ); } // publ_key_set_default_attributes() // // some of the common public key attributes have defaults but none of the specific // public keytypes have default attributes // CK_RV publ_key_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *subject_attr = NULL; CK_ATTRIBUTE *encrypt_attr = NULL; CK_ATTRIBUTE *verify_attr = NULL; CK_ATTRIBUTE *verify_recover_attr = NULL; CK_ATTRIBUTE *wrap_attr = NULL; CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_RV rc; rc = key_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK){ TRACE_DEVEL("key_object_set_default_attributes failed\n"); return rc; } // add the default CKO_PUBLIC_KEY attributes // class_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); subject_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); encrypt_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); verify_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); verify_recover_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); wrap_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!class || !subject_attr || !encrypt_attr || !verify_attr || !verify_recover_attr || !wrap_attr) { if (class_attr) free( class_attr ); if (subject_attr) free( subject_attr ); if (encrypt_attr) free( encrypt_attr ); if (verify_attr) free( verify_attr ); if (verify_recover_attr) free( verify_recover_attr ); if (wrap_attr) free( wrap_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_PUBLIC_KEY; subject_attr->type = CKA_SUBJECT; subject_attr->ulValueLen = 0; // empty string subject_attr->pValue = NULL; encrypt_attr->type = CKA_ENCRYPT; encrypt_attr->ulValueLen = sizeof(CK_BBOOL); encrypt_attr->pValue = (CK_BYTE *)encrypt_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)encrypt_attr->pValue = TRUE; verify_attr->type = CKA_VERIFY; verify_attr->ulValueLen = sizeof(CK_BBOOL); verify_attr->pValue = (CK_BYTE *)verify_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)verify_attr->pValue = TRUE; verify_recover_attr->type = CKA_VERIFY_RECOVER; verify_recover_attr->ulValueLen = sizeof(CK_BBOOL); verify_recover_attr->pValue = (CK_BYTE *)verify_recover_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)verify_recover_attr->pValue = TRUE; wrap_attr->type = CKA_WRAP; wrap_attr->ulValueLen = sizeof(CK_BBOOL); wrap_attr->pValue = (CK_BYTE *)wrap_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)wrap_attr->pValue = TRUE; template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, subject_attr ); template_update_attribute( tmpl, encrypt_attr ); template_update_attribute( tmpl, verify_attr ); template_update_attribute( tmpl, verify_recover_attr ); template_update_attribute( tmpl, wrap_attr ); return CKR_OK; } // publ_key_validate_attribute // CK_RV publ_key_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_SUBJECT: return CKR_OK; case CKA_ENCRYPT: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_WRAP: if (mode == MODE_MODIFY) { if (nv_token_data->tweak_vector.allow_key_mods == TRUE) return CKR_OK; TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } return CKR_OK; default: return key_object_validate_attribute( tmpl, attr, mode ); } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; } // priv_key_check_required_attributes() // CK_RV priv_key_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { // CKO_PRIVATE_KEY has no required attributes // return key_object_check_required_attributes( tmpl, mode ); } // priv_key_set_default_attributes() // // some of the common private key attributes have defaults but none of the specific // private keytypes have default attributes // CK_RV priv_key_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *subject_attr = NULL; CK_ATTRIBUTE *sensitive_attr = NULL; CK_ATTRIBUTE *decrypt_attr = NULL; CK_ATTRIBUTE *sign_attr = NULL; CK_ATTRIBUTE *sign_recover_attr = NULL; CK_ATTRIBUTE *unwrap_attr = NULL; CK_ATTRIBUTE *extractable_attr = NULL; CK_ATTRIBUTE *never_extr_attr = NULL; CK_ATTRIBUTE *always_sens_attr = NULL; CK_RV rc; rc = key_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK){ TRACE_DEVEL("key_object_set_default_attributes failed\n"); return rc; } // add the default CKO_PUBLIC_KEY attributes // class_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); subject_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); sensitive_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); decrypt_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); sign_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); sign_recover_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); unwrap_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); extractable_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); never_extr_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); always_sens_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!class_attr || !subject_attr || !sensitive_attr || !decrypt_attr || !sign_attr || !sign_recover_attr || !unwrap_attr || !extractable_attr || !never_extr_attr || !always_sens_attr ) { if (class_attr) free( class_attr ); if (subject_attr) free( subject_attr ); if (sensitive_attr) free( sensitive_attr ); if (decrypt_attr) free( decrypt_attr ); if (sign_attr) free( sign_attr ); if (sign_recover_attr) free( sign_recover_attr ); if (unwrap_attr) free( unwrap_attr ); if (extractable_attr) free( extractable_attr ); if (always_sens_attr) free( always_sens_attr ); if (never_extr_attr) free( never_extr_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_PRIVATE_KEY; subject_attr->type = CKA_SUBJECT; subject_attr->ulValueLen = 0; // empty string subject_attr->pValue = NULL; sensitive_attr->type = CKA_SENSITIVE; sensitive_attr->ulValueLen = sizeof(CK_BBOOL); sensitive_attr->pValue = (CK_BYTE *)sensitive_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)sensitive_attr->pValue = FALSE; decrypt_attr->type = CKA_DECRYPT; decrypt_attr->ulValueLen = sizeof(CK_BBOOL); decrypt_attr->pValue = (CK_BYTE *)decrypt_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)decrypt_attr->pValue = TRUE; sign_attr->type = CKA_SIGN; sign_attr->ulValueLen = sizeof(CK_BBOOL); sign_attr->pValue = (CK_BYTE *)sign_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)sign_attr->pValue = TRUE; sign_recover_attr->type = CKA_SIGN_RECOVER; sign_recover_attr->ulValueLen = sizeof(CK_BBOOL); sign_recover_attr->pValue = (CK_BYTE *)sign_recover_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)sign_recover_attr->pValue = TRUE; unwrap_attr->type = CKA_UNWRAP; unwrap_attr->ulValueLen = sizeof(CK_BBOOL); unwrap_attr->pValue = (CK_BYTE *)unwrap_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)unwrap_attr->pValue = TRUE; extractable_attr->type = CKA_EXTRACTABLE; extractable_attr->ulValueLen = sizeof(CK_BBOOL); extractable_attr->pValue = (CK_BYTE *)extractable_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)extractable_attr->pValue = TRUE; // by default, we'll set NEVER_EXTRACTABLE == FALSE and ALWAYS_SENSITIVE == FALSE // If the key is being created with KEYGEN, it will adjust as necessary. // never_extr_attr->type = CKA_NEVER_EXTRACTABLE; never_extr_attr->ulValueLen = sizeof(CK_BBOOL); never_extr_attr->pValue = (CK_BYTE *)never_extr_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)never_extr_attr->pValue = FALSE; always_sens_attr->type = CKA_ALWAYS_SENSITIVE; always_sens_attr->ulValueLen = sizeof(CK_BBOOL); always_sens_attr->pValue = (CK_BYTE *)always_sens_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)always_sens_attr->pValue = FALSE; template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, subject_attr ); template_update_attribute( tmpl, sensitive_attr ); template_update_attribute( tmpl, decrypt_attr ); template_update_attribute( tmpl, sign_attr ); template_update_attribute( tmpl, sign_recover_attr ); template_update_attribute( tmpl, unwrap_attr ); template_update_attribute( tmpl, extractable_attr ); template_update_attribute( tmpl, never_extr_attr ); template_update_attribute( tmpl, always_sens_attr ); return CKR_OK; } // // CK_RV priv_key_unwrap( TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL isopaque ) { CK_ATTRIBUTE *extractable = NULL; CK_ATTRIBUTE *always_sens = NULL; CK_ATTRIBUTE *never_extract = NULL; CK_ATTRIBUTE *sensitive = NULL; CK_ATTRIBUTE *local = NULL; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_RV rc; switch (keytype) { case CKK_RSA: rc = rsa_priv_unwrap( tmpl, data, data_len, isopaque ); break; case CKK_DSA: rc = dsa_priv_unwrap( tmpl, data, data_len ); break; default: TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID)); return CKR_WRAPPED_KEY_INVALID; } if (rc != CKR_OK) { TRACE_DEVEL("priv unwrap failed\n"); return rc; } // make sure // CKA_LOCAL == FALSE // CKA_ALWAYS_SENSITIVE == FALSE // CKA_EXTRACTABLE == TRUE // CKA_NEVER_EXTRACTABLE == FALSE // rc = build_attribute( CKA_LOCAL, &false, 1, &local ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } rc = build_attribute( CKA_ALWAYS_SENSITIVE, &false, 1, &always_sens ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } rc = build_attribute( CKA_SENSITIVE, &false, 1, &sensitive ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } rc = build_attribute( CKA_EXTRACTABLE, &true, 1, &extractable ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } rc = build_attribute( CKA_NEVER_EXTRACTABLE, &false, 1, &never_extract ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } template_update_attribute( tmpl, local ); template_update_attribute( tmpl, always_sens ); template_update_attribute( tmpl, sensitive ); template_update_attribute( tmpl, extractable ); template_update_attribute( tmpl, never_extract ); return CKR_OK; cleanup: if (local) free(local); if (always_sens) free(always_sens); if (extractable) free(extractable); if (never_extract) free(never_extract); return rc; } // priv_key_validate_attribute() // CK_RV priv_key_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_SUBJECT: return CKR_OK; case CKA_DECRYPT: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_UNWRAP: // we might want to do this for MODE_COPY too // if (mode == MODE_MODIFY) { if (nv_token_data->tweak_vector.allow_key_mods == TRUE) return CKR_OK; TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } return CKR_OK; // after key creation, CKA_SENSITIVE may only be set to TRUE // case CKA_SENSITIVE: { CK_BBOOL value; if (mode == MODE_CREATE || mode == MODE_KEYGEN) return CKR_OK; value = *(CK_BBOOL *)attr->pValue; if (value != TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } } return CKR_OK; // after key creation, CKA_EXTRACTABLE may only be set to FALSE // case CKA_EXTRACTABLE: { CK_BBOOL value; value = *(CK_BBOOL *)attr->pValue; if ((mode != MODE_CREATE && mode != MODE_KEYGEN) && value != FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (value == FALSE) { CK_ATTRIBUTE *attr; attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!attr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } attr->type = CKA_NEVER_EXTRACTABLE; attr->ulValueLen = sizeof(CK_BBOOL); attr->pValue = (CK_BYTE *)attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)attr->pValue = FALSE; template_update_attribute( tmpl, attr ); } } return CKR_OK; case CKA_ALWAYS_SENSITIVE: case CKA_NEVER_EXTRACTABLE: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; default: return key_object_validate_attribute( tmpl, attr, mode ); } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; } // secret_key_check_required_attributes() // CK_RV secret_key_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { return key_object_check_required_attributes( tmpl, mode ); } // secret_key_set_default_attributes() // // some of the common secret key attributes have defaults but none of the specific // secret keytypes have default attributes // CK_RV secret_key_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *sensitive_attr = NULL; CK_ATTRIBUTE *encrypt_attr = NULL; CK_ATTRIBUTE *decrypt_attr = NULL; CK_ATTRIBUTE *sign_attr = NULL; CK_ATTRIBUTE *verify_attr = NULL; CK_ATTRIBUTE *wrap_attr = NULL; CK_ATTRIBUTE *unwrap_attr = NULL; CK_ATTRIBUTE *extractable_attr = NULL; CK_ATTRIBUTE *never_extr_attr = NULL; CK_ATTRIBUTE *always_sens_attr = NULL; CK_RV rc; rc = key_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK) return rc; // add the default CKO_DATA attributes // class_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); sensitive_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); encrypt_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); decrypt_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); sign_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); verify_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); wrap_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); unwrap_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); extractable_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); never_extr_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); always_sens_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!class_attr || !sensitive_attr || !encrypt_attr || !decrypt_attr || !sign_attr || !verify_attr || !wrap_attr || !unwrap_attr || !extractable_attr || !never_extr_attr || !always_sens_attr) { if (class_attr) free( class_attr ); if (sensitive_attr) free( sensitive_attr ); if (encrypt_attr) free( encrypt_attr ); if (decrypt_attr) free( decrypt_attr ); if (sign_attr) free( sign_attr ); if (verify_attr) free( verify_attr ); if (wrap_attr) free( wrap_attr ); if (unwrap_attr) free( unwrap_attr ); if (extractable_attr) free( extractable_attr ); if (never_extr_attr) free( never_extr_attr ); if (always_sens_attr) free( always_sens_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY; sensitive_attr->type = CKA_SENSITIVE; sensitive_attr->ulValueLen = sizeof(CK_BBOOL); sensitive_attr->pValue = (CK_BYTE *)sensitive_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)sensitive_attr->pValue = FALSE; encrypt_attr->type = CKA_ENCRYPT; encrypt_attr->ulValueLen = sizeof(CK_BBOOL); encrypt_attr->pValue = (CK_BYTE *)encrypt_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)encrypt_attr->pValue = TRUE; decrypt_attr->type = CKA_DECRYPT; decrypt_attr->ulValueLen = sizeof(CK_BBOOL); decrypt_attr->pValue = (CK_BYTE *)decrypt_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)decrypt_attr->pValue = TRUE; sign_attr->type = CKA_SIGN; sign_attr->ulValueLen = sizeof(CK_BBOOL); sign_attr->pValue = (CK_BYTE *)sign_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)sign_attr->pValue = TRUE; verify_attr->type = CKA_VERIFY; verify_attr->ulValueLen = sizeof(CK_BBOOL); verify_attr->pValue = (CK_BYTE *)verify_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)verify_attr->pValue = TRUE; wrap_attr->type = CKA_WRAP; wrap_attr->ulValueLen = sizeof(CK_BBOOL); wrap_attr->pValue = (CK_BYTE *)wrap_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)wrap_attr->pValue = TRUE; unwrap_attr->type = CKA_UNWRAP; unwrap_attr->ulValueLen = sizeof(CK_BBOOL); unwrap_attr->pValue = (CK_BYTE *)unwrap_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)unwrap_attr->pValue = TRUE; extractable_attr->type = CKA_EXTRACTABLE; extractable_attr->ulValueLen = sizeof(CK_BBOOL); extractable_attr->pValue = (CK_BYTE *)extractable_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)extractable_attr->pValue = TRUE; // by default, we'll set NEVER_EXTRACTABLE == FALSE and ALWAYS_SENSITIVE == FALSE // If the key is being created with KEYGEN, it will adjust as necessary. // always_sens_attr->type = CKA_ALWAYS_SENSITIVE; always_sens_attr->ulValueLen = sizeof(CK_BBOOL); always_sens_attr->pValue = (CK_BYTE *)always_sens_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)always_sens_attr->pValue = FALSE; never_extr_attr->type = CKA_NEVER_EXTRACTABLE; never_extr_attr->ulValueLen = sizeof(CK_BBOOL); never_extr_attr->pValue = (CK_BYTE *)never_extr_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)never_extr_attr->pValue = FALSE; template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, sensitive_attr ); template_update_attribute( tmpl, encrypt_attr ); template_update_attribute( tmpl, decrypt_attr ); template_update_attribute( tmpl, sign_attr ); template_update_attribute( tmpl, verify_attr ); template_update_attribute( tmpl, wrap_attr ); template_update_attribute( tmpl, unwrap_attr ); template_update_attribute( tmpl, extractable_attr ); template_update_attribute( tmpl, never_extr_attr ); template_update_attribute( tmpl, always_sens_attr ); return CKR_OK; } // // CK_RV secret_key_unwrap( TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ) { CK_ATTRIBUTE *local = NULL; CK_ATTRIBUTE *always_sens = NULL; CK_ATTRIBUTE *sensitive = NULL; CK_ATTRIBUTE *extractable = NULL; CK_ATTRIBUTE *never_extract = NULL; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_RV rc; switch (keytype) { case CKK_CDMF: case CKK_DES: rc = des_unwrap( tmpl, data, data_len, fromend, isopaque ); break; case CKK_DES3: rc = des3_unwrap( tmpl, data, data_len, fromend, isopaque ); break; case CKK_AES: rc = aes_unwrap( tmpl, data, data_len, fromend, isopaque ); break; case CKK_GENERIC_SECRET: case CKK_RC2: case CKK_RC4: case CKK_RC5: case CKK_CAST: case CKK_CAST3: case CKK_CAST5: rc = generic_secret_unwrap( tmpl, data, data_len, fromend, isopaque ); break; default: TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID)); return CKR_WRAPPED_KEY_INVALID; } if (rc != CKR_OK) return rc; // make sure // CKA_LOCAL == FALSE // CKA_ALWAYS_SENSITIVE == FALSE // CKA_EXTRACTABLE == TRUE // CKA_NEVER_EXTRACTABLE == FALSE // rc = build_attribute( CKA_LOCAL, &false, 1, &local ); if (rc != CKR_OK){ TRACE_DEVEL("build attribute failed\n"); goto cleanup; } rc = build_attribute( CKA_ALWAYS_SENSITIVE, &false, 1, &always_sens ); if (rc != CKR_OK){ TRACE_DEVEL("build attribute failed\n"); goto cleanup; } rc = build_attribute( CKA_SENSITIVE, &false, 1, &sensitive ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } rc = build_attribute( CKA_EXTRACTABLE, &true, 1, &extractable ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } rc = build_attribute( CKA_NEVER_EXTRACTABLE, &false, 1, &never_extract ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } template_update_attribute( tmpl, local ); template_update_attribute( tmpl, always_sens ); template_update_attribute( tmpl, sensitive ); template_update_attribute( tmpl, extractable ); template_update_attribute( tmpl, never_extract ); return CKR_OK; cleanup: if (local) free(local); if (extractable) free(extractable); if (always_sens) free(always_sens); if (never_extract) free(never_extract); return rc; } // secret_key_validate_attribute() // CK_RV secret_key_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_ENCRYPT: case CKA_DECRYPT: case CKA_SIGN: case CKA_VERIFY: case CKA_WRAP: case CKA_UNWRAP: if (mode == MODE_MODIFY) { if (nv_token_data->tweak_vector.allow_key_mods == TRUE) return CKR_OK; TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } return CKR_OK; // after key creation, CKA_SENSITIVE may only be set to TRUE // case CKA_SENSITIVE: { CK_BBOOL value; value = *(CK_BBOOL *)attr->pValue; if ((mode != MODE_CREATE && mode != MODE_DERIVE && mode != MODE_KEYGEN) && (value != TRUE)){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } } return CKR_OK; // after key creation, CKA_EXTRACTABLE may only be set to FALSE // case CKA_EXTRACTABLE: { CK_BBOOL value; // the unwrap routine will automatically set extractable to TRUE // value = *(CK_BBOOL *)attr->pValue; if ((mode != MODE_CREATE && mode != MODE_DERIVE && mode != MODE_KEYGEN) && (value != FALSE)){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (value == FALSE) { CK_ATTRIBUTE *attr; attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!attr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } attr->type = CKA_NEVER_EXTRACTABLE; attr->ulValueLen = sizeof(CK_BBOOL); attr->pValue = (CK_BYTE *)attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)attr->pValue = FALSE; template_update_attribute( tmpl, attr ); } } return CKR_OK; case CKA_ALWAYS_SENSITIVE: case CKA_NEVER_EXTRACTABLE: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; default: return key_object_validate_attribute( tmpl, attr, mode ); } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; } // secret_key_check_exportability() // CK_BBOOL secret_key_check_exportability( CK_ATTRIBUTE_TYPE type ) { switch (type) { case CKA_VALUE: TRACE_ERROR("%s\n", ock_err(ERR_KEY_UNEXTRACTABLE)); return FALSE; } return TRUE; } // rsa_publ_check_required_attributes() // CK_RV rsa_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_MODULUS, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_MODULUS_BITS, &attr ); if (!found) { if (mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_PUBLIC_EXPONENT, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return publ_key_check_required_attributes( tmpl, mode ); } // rsa_publ_set_default_attributes() // CK_RV rsa_publ_set_default_attributes( TEMPLATE *tmpl, TEMPLATE *basetmpl, CK_ULONG mode ) { CK_ATTRIBUTE *type_attr = NULL; CK_ATTRIBUTE *modulus_attr = NULL; CK_ATTRIBUTE *modulus_bits_attr = NULL; CK_ATTRIBUTE *public_exp_attr = NULL; CK_ATTRIBUTE *tmpattr = NULL; CK_ULONG bits = 0L; CK_BYTE pubExp[3] = { 0x01,0x00,0x01 }; publ_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); modulus_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); modulus_bits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); public_exp_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(pubExp) ); if (!type_attr || !modulus_attr || !modulus_bits_attr || !public_exp_attr) { if (type_attr) free( type_attr ); if (modulus_attr) free( modulus_attr ); if (modulus_bits_attr) free( modulus_bits_attr ); if (public_exp_attr) free( public_exp_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_RSA; modulus_attr->type = CKA_MODULUS; modulus_attr->ulValueLen = 0; modulus_attr->pValue = NULL; modulus_bits_attr->type = CKA_MODULUS_BITS; modulus_bits_attr->ulValueLen = sizeof(CK_ULONG); modulus_bits_attr->pValue = (CK_BYTE *)modulus_bits_attr + sizeof(CK_ATTRIBUTE); if (template_attribute_find( basetmpl, CKA_MODULUS, &tmpattr)) { *(CK_ULONG *)modulus_bits_attr->pValue = 8 * tmpattr->ulValueLen; } else { *(CK_ULONG *)modulus_bits_attr->pValue = bits; } public_exp_attr->type = CKA_PUBLIC_EXPONENT; public_exp_attr->ulValueLen = sizeof(pubExp); public_exp_attr->pValue = (CK_BYTE *)public_exp_attr + sizeof(CK_ATTRIBUTE); memcpy(public_exp_attr->pValue, pubExp, sizeof(pubExp)); template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, modulus_attr ); template_update_attribute( tmpl, modulus_bits_attr ); template_update_attribute( tmpl, public_exp_attr ); return CKR_OK; } // rsa_publ_validate_attributes() // CK_RV rsa_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_MODULUS_BITS: if (mode == MODE_KEYGEN) { if (attr->ulValueLen != sizeof(CK_ULONG)){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else { CK_ULONG mod_bits = *(CK_ULONG *)attr->pValue; if (mod_bits < 512 || mod_bits > 4096){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } if (mod_bits % 8 != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } return CKR_OK; } } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_MODULUS: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_PUBLIC_EXPONENT: if (mode == MODE_CREATE || mode == MODE_KEYGEN) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return publ_key_validate_attribute( tmpl, attr, mode ); } } // rsa_priv_check_required_attributes() // CK_RV rsa_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_MODULUS, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } // // PKCS #11 is flexible with respect to which attributes must be present // in an RSA key. Keys can be specified in Chinese-Remainder format or // they can be specified in modular-exponent format. Right now, I only // support keys created in Chinese-Remainder format. That is, we return // CKR_TEMPLATE_INCOMPLETE if a modular-exponent key is specified. This // is allowed by PKCS #11. // // In the future, we should allow for creation of keys in modular-exponent // format too. This raises some issues. It's easy enough to recognize // when a key has been specified in modular-exponent format. And it's // easy enough to recognize when all attributes have been specified // (which is what we require right now). What's trickier to handle is // the "middle" cases in which more than the minimum yet less than the // full number of attributes have been specified. Do we revert back to // modular-exponent representation? Do we compute the missing attributes // ourselves? Do we simply return CKR_TEMPLATE_INCOMPLETE? // found = template_attribute_find( tmpl, CKA_PUBLIC_EXPONENT, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_PRIVATE_EXPONENT, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_PRIME_1, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_PRIME_2, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_EXPONENT_1, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_EXPONENT_2, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_COEFFICIENT, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } // we should probably verify that the (e != p) and (e != q). ie. gcd(e,n) == 1 // return priv_key_check_required_attributes( tmpl, mode ); } // rsa_priv_set_default_attributes() // CK_RV rsa_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *modulus_attr = NULL; CK_ATTRIBUTE *public_exp_attr = NULL; CK_ATTRIBUTE *private_exp_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; // satisfy the compiler // if (mode) modulus_attr = NULL; priv_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); modulus_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); public_exp_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); private_exp_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !modulus_attr || !public_exp_attr || !private_exp_attr) { if (type_attr) free( type_attr ); if (modulus_attr) free( modulus_attr ); if (public_exp_attr) free( public_exp_attr ); if (private_exp_attr) free( private_exp_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } modulus_attr->type = CKA_MODULUS; modulus_attr->ulValueLen = 0; modulus_attr->pValue = NULL; public_exp_attr->type = CKA_PUBLIC_EXPONENT; public_exp_attr->ulValueLen = 0; public_exp_attr->pValue = NULL; private_exp_attr->type = CKA_PRIVATE_EXPONENT; private_exp_attr->ulValueLen = 0; private_exp_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_RSA; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, modulus_attr ); template_update_attribute( tmpl, public_exp_attr ); template_update_attribute( tmpl, private_exp_attr ); return CKR_OK; } // rsa_priv_validate_attributes() // CK_RV rsa_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_MODULUS: case CKA_PRIVATE_EXPONENT: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_PUBLIC_EXPONENT: case CKA_PRIME_1: case CKA_PRIME_2: case CKA_EXPONENT_1: case CKA_EXPONENT_2: case CKA_COEFFICIENT: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return priv_key_validate_attribute( tmpl, attr, mode ); } } // rsa_priv_check_exportability() // CK_BBOOL rsa_priv_check_exportability( CK_ATTRIBUTE_TYPE type ) { switch (type) { case CKA_PRIVATE_EXPONENT: case CKA_PRIME_1: case CKA_PRIME_2: case CKA_EXPONENT_1: case CKA_EXPONENT_2: case CKA_COEFFICIENT: TRACE_ERROR("%s\n", ock_err(ERR_KEY_UNEXTRACTABLE)); return FALSE; } return TRUE; } // create the ASN.1 encoding for the private key for wrapping as defined // in PKCS #8 // // ASN.1 type PrivateKeyInfo ::= SEQUENCE { // version Version // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier // privateKey PrivateKey // attributes OPTIONAL // } // // Where PrivateKey is defined as follows for RSA: // // ASN.1 type RSAPrivateKey // // RSAPrivateKey ::= SEQUENCE { // version Version // modulus INTEGER // publicExponent INTEGER // privateExponent INTEGER // prime1 INTEGER // prime2 INTEGER // exponent1 INTEGER // exponent2 INTEGER // coefficient INTEGER // } // CK_RV rsa_priv_wrap_get_data( TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ) { CK_ATTRIBUTE *modulus = NULL; CK_ATTRIBUTE *publ_exp = NULL, *priv_exp = NULL; CK_ATTRIBUTE *prime1 = NULL, *prime2 = NULL; CK_ATTRIBUTE *exponent1 = NULL, *exponent2 = NULL; CK_ATTRIBUTE *coeff = NULL; CK_ATTRIBUTE *opaque = NULL; CK_RV rc; // compute the total length of the BER-encoded data // if (template_attribute_find(tmpl, CKA_MODULUS, &modulus) == FALSE){ TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &publ_exp) == FALSE){ TRACE_ERROR("Could not find CKA_PUBLIC_EXPONENT for the key.\n"); return CKR_FUNCTION_FAILED; } // CKA_IBM_OPAQUE is used for secure key, if it is not available, then // assume using clear key and get rest of attributes required for clear key. if (template_attribute_find(tmpl, CKA_IBM_OPAQUE, &opaque) == FALSE){ if (template_attribute_find(tmpl, CKA_PRIVATE_EXPONENT, &priv_exp) == FALSE){ TRACE_ERROR("Could not find private exponent for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_PRIME_1, &prime1) == FALSE){ TRACE_ERROR("Could not find CKA_PRIME_1 for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_PRIME_2, &prime2) == FALSE){ TRACE_ERROR("Could not find CKA_PRIME_2 for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_EXPONENT_1, &exponent1) == FALSE){ TRACE_ERROR("Could not find CKA_EXPONENT_1 for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_EXPONENT_2, &exponent2) == FALSE){ TRACE_ERROR("Could not find CKA_EXPONENT_2 for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_COEFFICIENT, &coeff) == FALSE){ TRACE_ERROR("Could not find CKA_COEFFICIENT for the key.\n"); return CKR_FUNCTION_FAILED; } } rc = ber_encode_RSAPrivateKey(length_only, data, data_len, modulus, publ_exp, priv_exp, prime1, prime2, exponent1, exponent2, coeff, opaque); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_RSAPrivateKey failed\n"); } return rc; } // // CK_RV rsa_priv_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length, CK_BBOOL isopaque ) { CK_ATTRIBUTE *modulus = NULL; CK_ATTRIBUTE *publ_exp = NULL; CK_ATTRIBUTE *priv_exp = NULL; CK_ATTRIBUTE *prime1 = NULL; CK_ATTRIBUTE *prime2 = NULL; CK_ATTRIBUTE *exponent1 = NULL; CK_ATTRIBUTE *exponent2 = NULL; CK_ATTRIBUTE *coeff = NULL; CK_ATTRIBUTE *opaque = NULL; CK_RV rc; rc = ber_decode_RSAPrivateKey( data, total_length, &modulus, &publ_exp, &priv_exp, &prime1, &prime2, &exponent1, &exponent2, &coeff, &opaque, isopaque ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_RSAPrivateKey failed\n"); return rc; } p11_attribute_trim( modulus ); p11_attribute_trim( publ_exp ); if (isopaque) p11_attribute_trim( opaque ); else { p11_attribute_trim( priv_exp ); p11_attribute_trim( prime1 ); p11_attribute_trim( prime2 ); p11_attribute_trim( exponent1 ); p11_attribute_trim( exponent2 ); p11_attribute_trim( coeff ); } template_update_attribute( tmpl, modulus ); template_update_attribute( tmpl, publ_exp ); if (isopaque ) template_update_attribute( tmpl, opaque ); else { template_update_attribute( tmpl, priv_exp ); template_update_attribute( tmpl, prime1 ); template_update_attribute( tmpl, prime2 ); template_update_attribute( tmpl, exponent1 ); template_update_attribute( tmpl, exponent2 ); template_update_attribute( tmpl, coeff ); } return CKR_OK; } // dsa_publ_check_required_attributes() // CK_RV dsa_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_SUBPRIME, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return publ_key_check_required_attributes( tmpl, mode ); } // dsa_publ_set_default_attributes() // CK_RV dsa_publ_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *subprime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) prime_attr = NULL; publ_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); subprime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !prime_attr || !subprime_attr || !base_attr || !value_attr) { if (type_attr) free( type_attr ); if (prime_attr) free( prime_attr ); if (subprime_attr) free( subprime_attr ); if (base_attr) free( base_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; subprime_attr->type = CKA_SUBPRIME; subprime_attr->ulValueLen = 0; subprime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DSA; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, subprime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // dsa_publ_validate_attributes() // CK_RV dsa_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_PRIME: { CK_ULONG size; if (mode != MODE_CREATE && mode != MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // must be between [512, 1024] bits, and a multiple of 64 bits // size = attr->ulValueLen; if (size < 64 || size > 128 || (size % 8 != 0)){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } p11_attribute_trim( attr ); return CKR_OK; } case CKA_SUBPRIME: { if (mode != MODE_CREATE && mode != MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // subprime must be 160 bits // if (attr->ulValueLen != 20){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } p11_attribute_trim( attr ); return CKR_OK; } case CKA_BASE: if (mode == MODE_CREATE || mode == MODE_KEYGEN) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_VALUE: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return publ_key_validate_attribute( tmpl, attr, mode ); } } // dsa_priv_check_required_attributes() // CK_RV dsa_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_SUBPRIME, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return priv_key_check_required_attributes( tmpl, mode ); } // dsa_priv_set_default_attributes() // CK_RV dsa_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *subprime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) prime_attr = NULL; priv_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); subprime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !prime_attr || !subprime_attr || !base_attr || !value_attr) { if (type_attr) free( type_attr ); if (prime_attr) free( prime_attr ); if (subprime_attr) free( subprime_attr ); if (base_attr) free( base_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; subprime_attr->type = CKA_SUBPRIME; subprime_attr->ulValueLen = 0; subprime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DSA; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, subprime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // dsa_priv_validate_attributes() // CK_RV dsa_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_PRIME: { CK_ULONG size; if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // must be between [512, 1024] bits, and a multiple of 64 bits // size = attr->ulValueLen; if (size < 64 || size > 128 || (size % 8 != 0)){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } p11_attribute_trim( attr ); return CKR_OK; } case CKA_SUBPRIME: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // subprime must be 160 bits // if (attr->ulValueLen != 20){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } p11_attribute_trim( attr ); return CKR_OK; } case CKA_BASE: case CKA_VALUE: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return priv_key_validate_attribute( tmpl, attr, mode ); } } // dsa_priv_check_exportability() // CK_BBOOL dsa_priv_check_exportability( CK_ATTRIBUTE_TYPE type ) { switch (type) { case CKA_VALUE: return FALSE; } return TRUE; } // create the ASN.1 encoding for the private key for wrapping as defined // in PKCS #8 // // ASN.1 type PrivateKeyInfo ::= SEQUENCE { // version Version // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier // privateKey PrivateKey // attributes OPTIONAL // } // // PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier // // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER // parameters ANY DEFINED BY algorithm OPTIONAL // } // // paramters ::= SEQUENCE { // p INTEGER // q INTEGER // g INTEGER // } // // privateKey ::= INTEGER // // CK_RV dsa_priv_wrap_get_data( TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ) { CK_ATTRIBUTE *prime = NULL; CK_ATTRIBUTE *subprime = NULL; CK_ATTRIBUTE *base = NULL; CK_ATTRIBUTE *value = NULL; CK_RV rc; // compute the total length of the BER-encoded data // if (template_attribute_find(tmpl, CKA_PRIME, &prime) == FALSE){ TRACE_ERROR("Could not find CKA_PRIME for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_SUBPRIME, &subprime) == FALSE){ TRACE_ERROR("Could not find CKA_SUBPRIME for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_BASE, &base) == FALSE){ TRACE_ERROR("Could not find CKA_BASE for the key.\n"); return CKR_FUNCTION_FAILED; } if (template_attribute_find(tmpl, CKA_VALUE, &value) == FALSE){ TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } rc = ber_encode_DSAPrivateKey( length_only, data, data_len, prime, subprime, base, value ); if (rc != CKR_OK) TRACE_DEVEL("ber_encode_DSAPrivateKe failed\n"); return rc; } // // CK_RV dsa_priv_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length ) { CK_ATTRIBUTE *prime = NULL; CK_ATTRIBUTE *subprime = NULL; CK_ATTRIBUTE *base = NULL; CK_ATTRIBUTE *value = NULL; CK_RV rc; rc = ber_decode_DSAPrivateKey( data, total_length, &prime, &subprime, &base, &value ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_DSAPrivateKey failed\n"); return rc; } p11_attribute_trim( prime ); p11_attribute_trim( subprime ); p11_attribute_trim( base ); p11_attribute_trim( value ); template_update_attribute( tmpl, prime ); template_update_attribute( tmpl, subprime ); template_update_attribute( tmpl, base ); template_update_attribute( tmpl, value ); return CKR_OK; } // ecdsa_publ_check_required_attributes() // CK_RV ecdsa_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_ECDSA_PARAMS, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_EC_POINT, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return publ_key_check_required_attributes( tmpl, mode ); } // ecdsa_publ_set_default_attributes() // CK_RV ecdsa_publ_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *params_attr = NULL; CK_ATTRIBUTE *ec_point_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) params_attr = NULL; publ_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); params_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); ec_point_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !params_attr || !ec_point_attr) { if (type_attr) free( type_attr ); if (params_attr) free( params_attr ); if (ec_point_attr) free( ec_point_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } params_attr->type = CKA_ECDSA_PARAMS; params_attr->ulValueLen = 0; params_attr->pValue = NULL; ec_point_attr->type = CKA_EC_POINT; ec_point_attr->ulValueLen = 0; ec_point_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_ECDSA; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, params_attr ); template_update_attribute( tmpl, ec_point_attr ); return CKR_OK; } // ecdsa_publ_validate_attributes() // CK_RV ecdsa_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_ECDSA_PARAMS: if (mode == MODE_CREATE || mode == MODE_KEYGEN) return CKR_OK; else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_EC_POINT: if (mode == MODE_CREATE) return CKR_OK; else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return publ_key_validate_attribute( tmpl, attr, mode ); } } // ecdsa_priv_check_required_attributes() // CK_RV ecdsa_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_ECDSA_PARAMS, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return priv_key_check_required_attributes( tmpl, mode ); } // ecdsa_priv_set_default_attributes() // CK_RV ecdsa_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *params_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) params_attr = NULL; priv_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); params_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !params_attr || !value_attr) { if (type_attr) free( type_attr ); if (params_attr) free( params_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } params_attr->type = CKA_ECDSA_PARAMS; params_attr->ulValueLen = 0; params_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_ECDSA; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, params_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // ecdsa_priv_validate_attributes() // CK_RV ecdsa_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_ECDSA_PARAMS: if (mode == MODE_CREATE) return CKR_OK; else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_VALUE: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return priv_key_validate_attribute( tmpl, attr, mode ); } } // ecdsa_priv_check_exportability() // CK_BBOOL ecdsa_priv_check_exportability( CK_ATTRIBUTE_TYPE type ) { switch (type) { case CKA_VALUE: return FALSE; } return TRUE; } // dh_publ_check_required_attributes() // CK_RV dh_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return publ_key_check_required_attributes( tmpl, mode ); } // dh_publ_set_default_attributes() // CK_RV dh_publ_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) prime_attr = NULL; publ_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !prime_attr || !base_attr || !value_attr) { if (type_attr) free( type_attr ); if (prime_attr) free( prime_attr ); if (base_attr) free( base_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DH; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // dh_publ_validate_attribute() // CK_RV dh_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_PRIME: case CKA_BASE: if (mode == MODE_CREATE || mode == MODE_KEYGEN) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_VALUE: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return publ_key_validate_attribute( tmpl, attr, mode ); } } // dh_priv_check_required_attributes() // CK_RV dh_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE_BITS, &attr ); if (found) { if (mode == MODE_CREATE || mode == MODE_UNWRAP){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } } return priv_key_check_required_attributes( tmpl, mode ); } // dh_priv_set_default_attributes() // CK_RV dh_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_bits_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ULONG bits = 0L; priv_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_bits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); if (!type_attr || !prime_attr || !base_attr || !value_attr || !value_bits_attr) { if (type_attr) free( type_attr ); if (prime_attr) free( prime_attr ); if (base_attr) free( base_attr ); if (value_attr) free( value_attr ); if (value_bits_attr) free( value_bits_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_bits_attr->type = CKA_VALUE_BITS; value_bits_attr->ulValueLen = sizeof(CK_ULONG); value_bits_attr->pValue = (CK_BYTE *)value_bits_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_bits_attr->pValue = bits; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DH; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, value_bits_attr ); return CKR_OK; } // dh_priv_validate_attribute() // CK_RV dh_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_PRIME: case CKA_BASE: case CKA_VALUE: if (mode == MODE_CREATE || mode == MODE_KEYGEN) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // I'm not sure what to do about VALUE_BITS...we don't really support // Diffie-Hellman keys other than for storage...when the object is // created, we're supposed to add CKA_VALUE_BITS outselves...which we // don't do at this time. (we'd need to add code in C_CreateObject to // call some sort of objecttype-specific callback) // // kapil 05/08/03 : Commented out error flagging, as CKA_VALUE_BITS is valid // attribute for creating DH priv object. The above is // an older comment. case CKA_VALUE_BITS: // TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); // return CKR_ATTRIBUTE_READ_ONLY; return CKR_OK ; break ; default: return priv_key_validate_attribute( tmpl, attr, mode ); } } // dh_priv_check_exportability() // CK_BBOOL dh_priv_check_exportability( CK_ATTRIBUTE_TYPE type ) { switch (type) { case CKA_VALUE: return FALSE; } return TRUE; } // kea_publ_check_required_attributes() // CK_RV kea_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_SUBPRIME, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { if (mode == MODE_CREATE || mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return publ_key_check_required_attributes( tmpl, mode ); } // kea_publ_set_default_attributes() // CK_RV kea_publ_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *subprime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) prime_attr = NULL; publ_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); subprime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !prime_attr || !subprime_attr || !base_attr || !value_attr) { if (type_attr) free( type_attr ); if (prime_attr) free( prime_attr ); if (subprime_attr) free( subprime_attr ); if (base_attr) free( base_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; subprime_attr->type = CKA_SUBPRIME; subprime_attr->ulValueLen = 0; subprime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_KEA; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, subprime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // kea_publ_validate_attribute() // CK_RV kea_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_PRIME: case CKA_SUBPRIME: case CKA_BASE: if (mode == MODE_CREATE || mode == MODE_KEYGEN) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_VALUE: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return publ_key_validate_attribute( tmpl, attr, mode ); } } // kea_priv_check_required_attributes() // CK_RV kea_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_SUBPRIME, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return priv_key_check_required_attributes( tmpl, mode ); } // kea_priv_set_default_attributes() // CK_RV kea_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *subprime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) prime_attr = NULL; priv_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); subprime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !prime_attr || !base_attr || !value_attr || !subprime_attr) { if (type_attr) free( type_attr ); if (prime_attr) free( prime_attr ); if (subprime_attr) free( subprime_attr ); if (base_attr) free( base_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; subprime_attr->type = CKA_SUBPRIME; subprime_attr->ulValueLen = 0; subprime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_KEA; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, subprime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // kea_priv_validate_attribute() // CK_RV kea_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_PRIME: case CKA_SUBPRIME: case CKA_BASE: case CKA_VALUE: if (mode == MODE_CREATE) { p11_attribute_trim( attr ); return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return priv_key_validate_attribute( tmpl, attr, mode ); } } // kea_priv_check_exportability() // CK_BBOOL kea_priv_check_exportability( CK_ATTRIBUTE_TYPE type ) { switch (type) { case CKA_VALUE: return FALSE; } return TRUE; } // generic_secret_check_required_attributes() // CK_RV generic_secret_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE_LEN, &attr ); if (!found) { // here's another place where PKCS #11 deviates from its own specification. // the spec states that VALUE_LEN must be present for KEYGEN but later // it's merely optional if the mechanism is CKM_SSL3_PRE_MASTER_KEY_GEN. // Unfortunately, we can't check the mechanism at this point // return CKR_OK; } else { // Another contradiction within the spec: When describing the key types // the spec says that VALUE_LEN must not be specified when unwrapping // a key. In the section describing the mechanisms, though, it's allowed for // most unwrapping mechanisms. Netscape DOES does specify this attribute // when unwrapping. // if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } } return secret_key_check_required_attributes( tmpl, mode ); } // generic_secret_set_default_attributes() // CK_RV generic_secret_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_len_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *sensitive_attr = NULL; CK_ATTRIBUTE *encrypt_attr = NULL; CK_ATTRIBUTE *decrypt_attr = NULL; CK_ATTRIBUTE *sign_attr = NULL; CK_ATTRIBUTE *verify_attr = NULL; CK_ATTRIBUTE *wrap_attr = NULL; CK_ATTRIBUTE *unwrap_attr = NULL; CK_ATTRIBUTE *extractable_attr = NULL; CK_ATTRIBUTE *never_extr_attr = NULL; CK_ATTRIBUTE *always_sens_attr = NULL; CK_ATTRIBUTE *id_attr = NULL; CK_ATTRIBUTE *sdate_attr = NULL; CK_ATTRIBUTE *edate_attr = NULL; CK_ATTRIBUTE *derive_attr = NULL; CK_ATTRIBUTE *local_attr = NULL; CK_ULONG len = 0L; if (mode) { value_attr = NULL; id_attr = NULL; } /* First set the Common Key Attributes's defaults for Generic Secret Keys. */ id_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE)); sdate_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE)); edate_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE)); derive_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); local_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); if (!id_attr || !sdate_attr || !edate_attr || !derive_attr || !local_attr) { if (id_attr) free(id_attr); if (sdate_attr) free(sdate_attr); if (edate_attr) free(edate_attr); if (derive_attr) free(derive_attr); if (local_attr) free(local_attr); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } id_attr->type = CKA_ID; id_attr->ulValueLen = 0; id_attr->pValue = NULL; sdate_attr->type = CKA_START_DATE; sdate_attr->ulValueLen = 0; sdate_attr->pValue = NULL; edate_attr->type = CKA_END_DATE; edate_attr->ulValueLen = 0; edate_attr->pValue = NULL; derive_attr->type = CKA_DERIVE; derive_attr->ulValueLen = sizeof(CK_BBOOL); derive_attr->pValue = (CK_BYTE *)derive_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)derive_attr->pValue = TRUE; /* should be safe to set CKA_LOCAL here... */ local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); if (mode == MODE_KEYGEN) *(CK_BBOOL *)local_attr->pValue = TRUE; else *(CK_BBOOL *)local_attr->pValue = FALSE; template_update_attribute(tmpl, id_attr); template_update_attribute(tmpl, sdate_attr); template_update_attribute(tmpl, edate_attr); template_update_attribute(tmpl, derive_attr); template_update_attribute(tmpl, local_attr); /* Next, set the Common Secret Key Attributes and defaults for * Generic Secret Keys. */ class_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS)); sensitive_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); encrypt_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); decrypt_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); sign_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); verify_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); wrap_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); unwrap_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); extractable_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); never_extr_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); always_sens_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); if (!class_attr || !sensitive_attr || !encrypt_attr || !decrypt_attr || !sign_attr || !verify_attr | !wrap_attr || !unwrap_attr || !extractable_attr || !never_extr_attr || !always_sens_attr) { if (class_attr) free(class_attr); if (sensitive_attr) free(sensitive_attr); if (encrypt_attr) free(encrypt_attr); if (decrypt_attr) free(decrypt_attr); if (sign_attr) free(sign_attr); if (verify_attr) free(verify_attr); if (wrap_attr) free(wrap_attr); if (unwrap_attr) free(unwrap_attr); if (extractable_attr) free(extractable_attr); if (never_extr_attr) free(never_extr_attr); if (always_sens_attr) free(always_sens_attr); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY; sensitive_attr->type = CKA_SENSITIVE; sensitive_attr->ulValueLen = sizeof(CK_BBOOL); sensitive_attr->pValue = (CK_BYTE *)sensitive_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)sensitive_attr->pValue = FALSE; encrypt_attr->type = CKA_ENCRYPT; encrypt_attr->ulValueLen = sizeof(CK_BBOOL); encrypt_attr->pValue = (CK_BYTE *)encrypt_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)encrypt_attr->pValue = FALSE; decrypt_attr->type = CKA_DECRYPT; decrypt_attr->ulValueLen = sizeof(CK_BBOOL); decrypt_attr->pValue = (CK_BYTE *)decrypt_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)decrypt_attr->pValue = FALSE; sign_attr->type = CKA_SIGN; sign_attr->ulValueLen = sizeof(CK_BBOOL); sign_attr->pValue = (CK_BYTE *)sign_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)sign_attr->pValue = TRUE; verify_attr->type = CKA_VERIFY; verify_attr->ulValueLen = sizeof(CK_BBOOL); verify_attr->pValue = (CK_BYTE *)verify_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)verify_attr->pValue = TRUE; wrap_attr->type = CKA_WRAP; wrap_attr->ulValueLen = sizeof(CK_BBOOL); wrap_attr->pValue = (CK_BYTE *)wrap_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)wrap_attr->pValue = FALSE; unwrap_attr->type = CKA_UNWRAP; unwrap_attr->ulValueLen = sizeof(CK_BBOOL); unwrap_attr->pValue = (CK_BYTE *)unwrap_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)unwrap_attr->pValue = FALSE; extractable_attr->type = CKA_EXTRACTABLE; extractable_attr->ulValueLen = sizeof(CK_BBOOL); extractable_attr->pValue = (CK_BYTE *)extractable_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)extractable_attr->pValue = TRUE; /* by default, we'll set NEVER_EXTRACTABLE == FALSE and * ALWAYS_SENSITIVE == FALSE * If the key is being created with KEYGEN, it will adjust as necessary. */ always_sens_attr->type = CKA_ALWAYS_SENSITIVE; always_sens_attr->ulValueLen = sizeof(CK_BBOOL); always_sens_attr->pValue = (CK_BYTE *)always_sens_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)always_sens_attr->pValue = FALSE; never_extr_attr->type = CKA_NEVER_EXTRACTABLE; never_extr_attr->ulValueLen = sizeof(CK_BBOOL); never_extr_attr->pValue = (CK_BYTE *)never_extr_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)never_extr_attr->pValue = FALSE; template_update_attribute(tmpl, class_attr); template_update_attribute(tmpl, sensitive_attr); template_update_attribute(tmpl, encrypt_attr); template_update_attribute(tmpl, decrypt_attr); template_update_attribute(tmpl, sign_attr); template_update_attribute(tmpl, verify_attr); template_update_attribute(tmpl, wrap_attr); template_update_attribute(tmpl, unwrap_attr); template_update_attribute(tmpl, extractable_attr); template_update_attribute(tmpl, never_extr_attr); template_update_attribute(tmpl, always_sens_attr); /* Now set the type, value and value_len */ type_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE)); value_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE)); value_len_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG)); if (!type_attr || !value_attr || !value_len_attr) { if (type_attr) free(type_attr); if (value_attr) free(value_attr); if (value_len_attr) free(value_len_attr); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof(CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = len; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_GENERIC_SECRET; template_update_attribute(tmpl, type_attr); template_update_attribute(tmpl, value_attr); template_update_attribute(tmpl, value_len_attr); return CKR_OK; } // generic_secret_validate_attribute() // CK_RV generic_secret_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_VALUE: if (mode == MODE_CREATE) return CKR_OK; else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // Another contradiction within the spec: When describing the key types // the spec says that VALUE_LEN must not be specified when unwrapping // a key. In the section describing the mechanisms, though, it's allowed for // most unwrapping mechanisms. Netscape DOES does specify this attribute // when unwrapping. // case CKA_VALUE_LEN: if (mode == MODE_KEYGEN || mode == MODE_DERIVE) return CKR_OK; else { if (mode == MODE_UNWRAP) { if (nv_token_data->tweak_vector.netscape_mods == TRUE) return CKR_OK; } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // generic_secret_check_exportability() // CK_BBOOL generic_secret_check_exportability( CK_ATTRIBUTE_TYPE type ) { switch (type) { case CKA_VALUE: return FALSE; } return TRUE; } // // CK_RV generic_secret_wrap_get_data( TEMPLATE * tmpl, CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len ) { CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_RV rc; if (!tmpl || !data_len){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = template_attribute_find( tmpl, CKA_IBM_OPAQUE, &attr ); if (rc == FALSE) { rc = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); return CKR_KEY_NOT_WRAPPABLE; } } *data_len = attr->ulValueLen; if (length_only == FALSE) { ptr = (CK_BYTE *)malloc( attr->ulValueLen ); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, attr->pValue, attr->ulValueLen ); *data = ptr; } return CKR_OK; } // // CK_RV generic_secret_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ) { CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * value_len_attr = NULL; CK_BYTE * ptr = NULL; CK_ULONG rc, len = 0; if (fromend == TRUE) ptr = data + data_len; else ptr = data; // it's possible that the user specified CKA_VALUE_LEN in the // template. if so, try to use it. by default, CKA_VALUE_LEN is 0 // rc = template_attribute_find( tmpl, CKA_VALUE_LEN, &attr ); if (rc) { len = *(CK_ULONG *)attr->pValue; if (len > data_len) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); rc = CKR_ATTRIBUTE_VALUE_INVALID; goto error; } if (len != 0) data_len = len; } if (fromend == TRUE) ptr -= data_len; if (isopaque) rc = build_attribute( CKA_IBM_OPAQUE, ptr, data_len, &value_attr ); else rc = build_attribute( CKA_VALUE, ptr, data_len, &value_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto error; } if (data_len != len) { rc = build_attribute( CKA_VALUE_LEN, (CK_BYTE *)&data_len, sizeof(CK_ULONG), &value_len_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto error; } } template_update_attribute( tmpl, value_attr ); if (data_len != len) template_update_attribute( tmpl, value_len_attr ); return CKR_OK; error: if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); return rc; } // rc2_check_required_attributes() // CK_RV rc2_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE_LEN, &attr ); if (!found) { if (mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // rc2_set_default_attributes() // CK_RV rc2_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_len_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ULONG len = 0L; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_len_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); if (!type_attr || !value_attr || !value_len_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof(CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = len; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_RC2; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, value_len_attr ); return CKR_OK; } // rc2_validate_attribute() // CK_RV rc2_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_VALUE: if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // rc2 key length <= 128 bytes // if (attr->ulValueLen > 128) return CKR_ATTRIBUTE_VALUE_INVALID; else return CKR_OK; case CKA_VALUE_LEN: { CK_ULONG len; if (mode != MODE_KEYGEN && mode != MODE_DERIVE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } len = *(CK_ULONG *)attr->pValue; if (len > 128){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // rc4_set_default_attributes() // CK_RV rc4_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_len_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ULONG len = 0L; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_len_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); if (!type_attr || !value_attr || !value_len_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof(CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = len; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_RC4; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, value_len_attr ); return CKR_OK; } // rc4_check_required_attributes() // CK_RV rc4_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE_LEN, &attr ); if (!found) { if (mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // rc4_validate_attribute() // CK_RV rc4_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // key length <= 256 bytes // if (attr->ulValueLen > 256){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } case CKA_VALUE_LEN: { CK_ULONG len; if (mode != MODE_KEYGEN && mode != MODE_DERIVE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } len = *(CK_ULONG *)attr->pValue; if (len > 255){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // rc5_check_required_attributes() // CK_RV rc5_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE_LEN, &attr ); if (!found) { if (mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // rc5_set_default_attributes() // CK_RV rc5_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_len_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ULONG len = 0L; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_len_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); if (!type_attr || !value_attr || !value_len_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof(CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = len; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_RC5; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, value_len_attr ); return CKR_OK; } // rc5_validate_attribute() // CK_RV rc5_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } // key length <= 256 bytes // if (attr->ulValueLen > 255){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } case CKA_VALUE_LEN: { CK_ULONG len; if (mode != MODE_KEYGEN && mode != MODE_DERIVE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } len = *(CK_ULONG *)attr->pValue; if (len > 255){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // // CK_RV des_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // // CK_BBOOL des_check_weak_key( CK_BYTE *key ) { CK_ULONG i; for (i=0; i < des_weak_count; i++) { if (memcmp(key, des_weak_keys[i], DES_KEY_SIZE) == 0) return TRUE; } for (i=0; i < des_semi_weak_count; i++) { if (memcmp(key, des_semi_weak_keys[i], DES_KEY_SIZE) == 0) return TRUE; } for (i=0; i < des_possibly_weak_count; i++) { if (memcmp(key, des_possibly_weak_keys[i], DES_KEY_SIZE) == 0) return TRUE; } return FALSE; } // // CK_RV des_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); if (!value_attr || !type_attr) { if (value_attr) free( value_attr ); if (type_attr) free( type_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DES; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // // CK_RV des_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ) { CK_ATTRIBUTE * value_attr = NULL; CK_BYTE * ptr = NULL; CK_ULONG i; if (data_len < DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID)); return CKR_WRAPPED_KEY_INVALID; } if (fromend == TRUE) { if (isopaque) ptr = data + data_len; else ptr = data + data_len - DES_BLOCK_SIZE; } else ptr = data; if (isopaque) value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + data_len ); else { if (nv_token_data->tweak_vector.check_des_parity == TRUE) { for (i=0; i < DES_KEY_SIZE; i++) { if (parity_is_odd(ptr[i]) == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } } value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + DES_BLOCK_SIZE ); } if (!value_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } if (isopaque) { value_attr->type = CKA_IBM_OPAQUE; value_attr->ulValueLen = data_len; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); memcpy( value_attr->pValue, ptr, data_len ); } else { value_attr->type = CKA_VALUE; value_attr->ulValueLen = DES_BLOCK_SIZE; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); memcpy( value_attr->pValue, ptr, DES_BLOCK_SIZE ); } template_update_attribute( tmpl, value_attr ); return CKR_OK; } // des_validate_attribute() // CK_RV des_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_BYTE * ptr = NULL; CK_ULONG i; switch (attr->type) { case CKA_VALUE: // key length always 8 bytes // if (mode == MODE_CREATE) { if (attr->ulValueLen != DES_KEY_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } if (nv_token_data->tweak_vector.check_des_parity == TRUE) { ptr = attr->pValue; for (i=0; i < DES_KEY_SIZE; i++) { if (parity_is_odd(ptr[i]) == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } } return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_VALUE_LEN: // Cryptoki doesn't allow this but Netscape tries uses it // if (nv_token_data->tweak_vector.netscape_mods == TRUE) { if (mode == MODE_CREATE || mode == MODE_DERIVE || mode == MODE_KEYGEN || mode == MODE_UNWRAP) { CK_ULONG len = *(CK_ULONG *)attr->pValue; if (len != DES_KEY_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } } else{ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // // CK_RV des_wrap_get_data( TEMPLATE * tmpl, CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len ) { CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_RV rc; if (!tmpl || !data_len){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = template_attribute_find( tmpl, CKA_IBM_OPAQUE, &attr ); if (rc == FALSE) { rc = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); return CKR_KEY_NOT_WRAPPABLE; } } *data_len = attr->ulValueLen; if (length_only == FALSE) { ptr = (CK_BYTE *)malloc( attr->ulValueLen ); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, attr->pValue, attr->ulValueLen ); *data = ptr; } return CKR_OK; } // des2_check_required_attributes() // CK_RV des2_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // des2_set_default_attributes() // CK_RV des2_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); if (!value_attr || !type_attr) { if (value_attr) free( value_attr ); if (type_attr) free( type_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DES2; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // des2_validate_attribute() // CK_RV des2_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_BYTE * ptr = NULL; CK_ULONG i; switch (attr->type) { case CKA_VALUE: // key length always 16 bytes // if (mode == MODE_CREATE) { if (attr->ulValueLen != (2 * DES_KEY_SIZE)){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } if (nv_token_data->tweak_vector.check_des_parity == TRUE) { ptr = attr->pValue; for (i=0; i < 2*DES_KEY_SIZE; i++) { if (parity_is_odd(ptr[i]) == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } } return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_VALUE_LEN: // Cryptoki doesn't allow this but Netscape tries uses it // if (nv_token_data->tweak_vector.netscape_mods == TRUE) { if (mode == MODE_CREATE || mode == MODE_DERIVE || mode == MODE_KEYGEN || mode == MODE_UNWRAP) { CK_ULONG len = *(CK_ULONG *)attr->pValue; if (len != (2 * DES_KEY_SIZE)){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } } else{ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // des3_check_required_attributes() // CK_RV des3_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // des3_set_default_attributes() // CK_RV des3_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); if (!value_attr || !type_attr) { if (value_attr) free( value_attr ); if (type_attr) free( type_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DES3; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // // CK_RV des3_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ) { CK_ATTRIBUTE * value_attr = NULL; CK_BYTE * ptr = NULL; CK_ULONG i; if (data_len < 3 * DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID)); return CKR_WRAPPED_KEY_INVALID; } if (fromend == TRUE) { if (isopaque) ptr = data + data_len; else ptr = data + data_len - (3*DES_BLOCK_SIZE); } else ptr = data; if (isopaque) value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + data_len ); else { if (nv_token_data->tweak_vector.check_des_parity == TRUE) { for (i=0; i < 3*DES_KEY_SIZE; i++) { if (parity_is_odd(ptr[i]) == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } } value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + (3 * DES_BLOCK_SIZE) ); } if (!value_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } if (isopaque) { value_attr->type = CKA_IBM_OPAQUE; value_attr->ulValueLen = data_len; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); memcpy( value_attr->pValue, ptr, data_len ); } else { value_attr->type = CKA_VALUE; value_attr->ulValueLen = 3 * DES_BLOCK_SIZE; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); memcpy( value_attr->pValue, ptr, 3 * DES_BLOCK_SIZE ); } template_update_attribute( tmpl, value_attr ); return CKR_OK; } // // CK_RV des3_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_BYTE * ptr = NULL; CK_ULONG i; switch (attr->type) { case CKA_VALUE: // key length always 24 bytes // if (mode == MODE_CREATE) { if (attr->ulValueLen != (3 * DES_KEY_SIZE)){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } if (nv_token_data->tweak_vector.check_des_parity == TRUE) { ptr = attr->pValue; for (i=0; i < 3*DES_KEY_SIZE; i++) { if (parity_is_odd(ptr[i]) == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } } return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_VALUE_LEN: // Cryptoki doesn't allow this but Netscape tries uses it // if (nv_token_data->tweak_vector.netscape_mods == TRUE) { if (mode == MODE_CREATE || mode == MODE_DERIVE || mode == MODE_KEYGEN || mode == MODE_UNWRAP) { return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } } else{ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // // CK_RV des3_wrap_get_data( TEMPLATE * tmpl, CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len ) { CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_RV rc; if (!tmpl || !data_len){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } // try secure key first, if not found then try clear key... rc = template_attribute_find( tmpl, CKA_IBM_OPAQUE, &attr ); if (rc == FALSE) { rc = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); return CKR_KEY_NOT_WRAPPABLE; } } *data_len = attr->ulValueLen; if (length_only == FALSE) { ptr = (CK_BYTE *)malloc( attr->ulValueLen ); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, attr->pValue, attr->ulValueLen ); *data = ptr; } return CKR_OK; } // cast_check_required_attributes() // CK_RV cast_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE_LEN, &attr ); if (!found) { if (mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // cast_set_default_attributes() // CK_RV cast_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_len_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ULONG len = 0L; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_len_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); if (!type_attr || !value_attr || !value_len_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof(CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = len; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_CAST; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, value_len_attr ); return CKR_OK; } // cast_validate_attribute() // CK_RV cast_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_ULONG len; switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (attr->ulValueLen > 8 || attr->ulValueLen < 1){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } case CKA_VALUE_LEN: { if (mode != MODE_KEYGEN && mode != MODE_DERIVE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } len = *(CK_ULONG *)attr->pValue; if (len > 8 || len < 1){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // cast3_check_required_attributes() // CK_RV cast3_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE_LEN, &attr ); if (!found) { if (mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // cast3_set_default_attributes() // CK_RV cast3_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_len_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ULONG len = 0L; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_len_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); if (!type_attr || !value_attr || !value_len_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof(CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = len; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_CAST3; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, value_len_attr ); return CKR_OK; } // cast3_validate_attribute() // CK_RV cast3_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_ULONG len; switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (attr->ulValueLen > 8 || attr->ulValueLen < 1){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } case CKA_VALUE_LEN: { if (mode != MODE_KEYGEN && mode != MODE_DERIVE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } len = *(CK_ULONG *)attr->pValue; if (len > 8 || len < 1){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // cast5_check_required_attributes() // CK_RV cast5_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } found = template_attribute_find( tmpl, CKA_VALUE_LEN, &attr ); if (!found) { if (mode == MODE_KEYGEN){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // cast5_set_default_attributes() // CK_RV cast5_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *value_len_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; CK_ULONG len = 0L; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_len_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); if (!type_attr || !value_attr || !value_len_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof(CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = len; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_CAST5; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, value_len_attr ); return CKR_OK; } // cast5_validate_attribute() // CK_RV cast5_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_ULONG len; switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (attr->ulValueLen > 16 || attr->ulValueLen < 1){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } case CKA_VALUE_LEN: { if (mode != MODE_KEYGEN && mode != MODE_DERIVE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } len = *(CK_ULONG *)attr->pValue; if (len < 1 || len > 16){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // idea_check_required_attributes() // CK_RV idea_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // idea_set_default_attributes() // CK_RV idea_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !value_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_IDEA; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // idea_validate_attribute() // CK_RV idea_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (attr->ulValueLen != 16){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // cdmf_check_required_attributes() // CK_RV cdmf_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } #if !(NOCDMF) // cdmf_set_default_attributes() // CK_RV cdmf_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !value_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_CDMF; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // cdmf_validate_attribute() // CK_RV cdmf_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_ULONG len; switch (attr->type) { case CKA_VALUE: { #if 0 CDMF_Transform_Args args; #endif CK_ULONG req_len, repl_len; CK_BYTE cdmf_key[DES_KEY_SIZE]; CK_RV rc; if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (attr->ulValueLen != DES_KEY_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } #if 0 req_len = sizeof(args); repl_len = DES_KEY_SIZE; memcpy( args.des_key, attr->pValue, DES_KEY_SIZE ); rc = communicate( PK_CDMF_TRANSFORM_KEY, &args, req_len, cdmf_key, &repl_len, NULL, 0, NULL, 0 ); if (rc != CKR_OK) return rc; if (rc == CKR_OK) { if (repl_len != DES_KEY_SIZE) return CKR_GENERAL_ERROR; memcpy( attr->pValue, cdmf_key, DES_KEY_SIZE ); } return CKR_OK; #else return tok_cdmf_transform(attr->pValue, DES_KEY_SIZE); #endif } case CKA_VALUE_LEN: { if (nv_token_data->tweak_vector.netscape_mods == TRUE) { if (mode == MODE_CREATE || mode == MODE_KEYGEN) { len = *(CK_ULONG *)attr->pValue; if (len != DES_KEY_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } } else{ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } #endif // skipjack_check_required_attributes() // CK_RV skipjack_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // skipjack_set_default_attributes() // CK_RV skipjack_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !value_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_SKIPJACK; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // skipjack_validate_attribute() // CK_RV skipjack_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (attr->ulValueLen != 20){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // baton_check_required_attributes() // CK_RV baton_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // baton_set_default_attributes() // CK_RV baton_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !value_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_BATON; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // baton_validate_attribute() // CK_RV baton_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (attr->ulValueLen != 40){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // juniper_check_required_attributes() // CK_RV juniper_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // juniper_set_default_attributes() // CK_RV juniper_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!type_attr || !value_attr) { if (type_attr) free( type_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_JUNIPER; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // juniper_validate_attribute() // CK_RV juniper_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_VALUE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (attr->ulValueLen != 40){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } else return CKR_OK; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // aes_set_default_attributes() // CK_RV aes_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * type_attr = NULL; if (mode) value_attr = NULL; secret_key_set_default_attributes( tmpl, mode ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); if (!value_attr || !type_attr) { if (value_attr) free( value_attr ); if (type_attr) free( type_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_AES; template_update_attribute( tmpl, type_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // aes_check_required_attributes() // CK_RV aes_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return secret_key_check_required_attributes( tmpl, mode ); } // // CK_RV aes_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_ULONG val; switch (attr->type) { case CKA_VALUE: // key length is either 16, 24 or 32 bytes // if (mode == MODE_CREATE) { if (attr->ulValueLen != AES_KEY_SIZE_128 && attr->ulValueLen != AES_KEY_SIZE_192 && attr->ulValueLen != AES_KEY_SIZE_256 ) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } return CKR_OK; } else { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_VALUE_LEN: if (mode == MODE_CREATE || mode == MODE_DERIVE || mode == MODE_KEYGEN || mode == MODE_UNWRAP) { val = *(CK_ULONG *)attr->pValue; if (val != AES_KEY_SIZE_128 && val != AES_KEY_SIZE_192 && val != AES_KEY_SIZE_256 ){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_TEMPLATE_INCONSISTENT; } return CKR_OK; } else{ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } default: return secret_key_validate_attribute( tmpl, attr, mode ); } } // // CK_RV aes_wrap_get_data( TEMPLATE * tmpl, CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len ) { CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_RV rc; if (!tmpl || !data_len){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = template_attribute_find( tmpl, CKA_IBM_OPAQUE, &attr ); if (rc == FALSE) { rc = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); return CKR_KEY_NOT_WRAPPABLE; } } *data_len = attr->ulValueLen; if (length_only == FALSE) { ptr = (CK_BYTE *)malloc( attr->ulValueLen ); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, attr->pValue, attr->ulValueLen ); *data = ptr; } return CKR_OK; } // // CK_RV aes_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * val_len_attr = NULL; CK_BYTE * ptr = NULL; CK_ULONG key_size; CK_BBOOL found = FALSE; /* accept CKA_VALUE_LEN. pkcs11v2.20 doesn't want this attribute when * unwrapping an AES key, but we need it for several reasons: * - because some mechanisms may have added padding * - AES keys come in several sizes * - secure key size depends on token specifics * If not a secure key, try datalen and see if matches an aes key size. * Otherwise, fail because we need to return CKA_VALUE_LEN and we cannot * unless user tells us what it is for secure key. * * Note: since cca token has secure key size of 64, which is a multiple of * aes blocksize, can assume datalen will always be 64. * However, a better solution is to create a token specific wrap and * unwrap and do this kind of stuff in the token. */ found = template_attribute_find( tmpl, CKA_VALUE_LEN, &val_len_attr ); if (found) key_size = *(CK_ULONG *)val_len_attr->pValue; else { if (isopaque) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } else key_size = data_len; } /* key_size should be one of AES's possible sizes */ if (key_size != AES_KEY_SIZE_128 && key_size != AES_KEY_SIZE_192 && key_size != AES_KEY_SIZE_256) { TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_LEN_RANGE)); return CKR_WRAPPED_KEY_LEN_RANGE; } if (fromend == TRUE) { if (isopaque) ptr = data + data_len; else ptr = data + data_len - key_size; } else ptr = data; /* reset key_size for secure key, assuming datalen is the token's secure key size */ if (isopaque) key_size = data_len; value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + key_size ); if (!value_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } if (isopaque) value_attr->type = CKA_IBM_OPAQUE; else value_attr->type = CKA_VALUE; value_attr->ulValueLen = key_size; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); memcpy( value_attr->pValue, ptr, key_size ); template_update_attribute( tmpl, value_attr ); /* pkcs11v2-20: CKA_VALUE and CKA_VALUE_LEN given for aes key object. */ if (!found) { val_len_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG)); if (!val_len_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } val_len_attr->type = CKA_VALUE_LEN; val_len_attr->ulValueLen = sizeof(CK_ULONG); val_len_attr->pValue = (CK_BYTE *)val_len_attr + sizeof(CK_ATTRIBUTE); *((CK_ULONG *)val_len_attr->pValue) = key_size; template_update_attribute(tmpl, val_len_attr); } return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/mech_dh.c0000644000175000017500000005302312630407154021006 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /************************************************************************ * * * Copyright: Corrent Corporation (c) 2000-2003 * * * * Filename: mech_dh.c * * Created By: Kapil Sood * * Created On: Jan 18, 2003 * * Description: This is the file implementing Diffie-Hellman * * key pair generation and shared key derivation * * operations. * * * ************************************************************************/ // File: mech_dh.c // // Mechanisms for DH // // Routines contained within: #include #include // for memcmp() et al #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" #ifndef NODH // // CK_RV dh_pkcs_derive( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle ) { CK_RV rc; CK_ULONG i, keyclass = 0, keytype = 0 ; CK_ATTRIBUTE *new_attr ; OBJECT *temp_obj = NULL; CK_BYTE secret_key_value[256] ; CK_ULONG secret_key_value_len = 256 ; // Prelim checking of sess, mech, pTemplate, and ulCount was // done in the calling function (key_mgr_derive_key). // Perform DH checking of parameters // Check the existance of the public-value in mechanism if ((!mech->pParameter) || ((mech->ulParameterLen != 64) && (mech->ulParameterLen != 96) && (mech->ulParameterLen != 128) && (mech->ulParameterLen != 192) && (mech->ulParameterLen != 256))) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return(CKR_MECHANISM_PARAM_INVALID) ; } // Check valid object handle pointer of derived key if (handle == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); return CKR_KEY_HANDLE_INVALID; } // Extract the object class and keytype from the supplied template. for (i=0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { keyclass = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; if (keyclass != CKO_SECRET_KEY) { TRACE_ERROR("This operation requires a secret key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } if (pTemplate[i].type == CKA_KEY_TYPE) keytype = *(CK_ULONG *)pTemplate[i].pValue; } // Extract public-key from mechanism parameters. base-key contains the // private key, prime, and base. The return value will be in the handle. rc = ckm_dh_pkcs_derive( mech->pParameter, mech->ulParameterLen, base_key, secret_key_value, &secret_key_value_len ); if (rc != CKR_OK) return rc; // Build the attribute from the vales that were returned back rc = build_attribute( CKA_VALUE, secret_key_value, secret_key_value_len, &new_attr ); if (rc != CKR_OK) { TRACE_DEVEL("Failed to build the new attribute.\n"); return rc ; } // Create the object that will be passed back as a handle. This will // contain the new (computed) value of the attribute. rc = object_mgr_create_skel( sess, pTemplate, ulCount, MODE_KEYGEN, keyclass, keytype, &temp_obj ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr create skeleton failed.\n"); return rc; } // Update the template in the object with the new attribute template_update_attribute( temp_obj->template, new_attr ); // at this point, the derived key is fully constructed...assign an // object handle and store the key // rc = object_mgr_create_final( sess, temp_obj, handle ); if (rc != CKR_OK) { TRACE_DEVEL("Object Mgr create final failed.\n"); object_free( temp_obj ); return rc; } return rc; } // // mechanisms // // // CK_RV ckm_dh_pkcs_derive( CK_VOID_PTR other_pubkey, CK_ULONG other_pubkey_len, CK_OBJECT_HANDLE base_key, CK_BYTE *secret_value, CK_ULONG *secret_value_len ) { CK_RV rc; CK_BYTE p[256] ; CK_ULONG p_len ; CK_BYTE x[256] ; CK_ULONG x_len ; CK_ATTRIBUTE *temp_attr ; OBJECT *base_key_obj = NULL ; CK_BYTE *p_other_pubkey ; rc = object_mgr_find_in_map1( base_key, &base_key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } // Extract secret (x) from base_key rc = template_attribute_find( base_key_obj->template, CKA_VALUE, &temp_attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else { memset(x, 0, sizeof(x)) ; x_len = temp_attr->ulValueLen ; memcpy(x, (CK_BYTE *)temp_attr->pValue, x_len) ; } // Extract prime (p) from base_key rc = template_attribute_find( base_key_obj->template, CKA_PRIME, &temp_attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_PRIME in the template\n"); return CKR_FUNCTION_FAILED; } else { memset(p, 0, sizeof(p)) ; p_len = temp_attr->ulValueLen ; memcpy(p, (CK_BYTE *)temp_attr->pValue, p_len) ; } p_other_pubkey = (CK_BYTE *) other_pubkey ; // Perform: z = other_pubkey^x mod p rc = token_specific.t_dh_pkcs_derive(secret_value, secret_value_len, p_other_pubkey, other_pubkey_len, x, x_len, p, p_len ); if (rc != CKR_OK) TRACE_DEVEL("Token specific dh pkcs derive failed.\n"); return rc; } // // CK_RV ckm_dh_pkcs_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_RV rc; rc = token_specific.t_dh_pkcs_key_pair_gen(publ_tmpl,priv_tmpl); if (rc != CKR_OK) TRACE_DEVEL("Token specific dh pkcs key pair gen failed.\n"); return rc; } #endif opencryptoki+dfsg/usr/lib/pkcs11/common/template.c0000755000175000017500000013602712630407154021243 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ /* File: template.c * * Attribute template management routines * * Functions contained in this file: * * template_add_attributes * template_add_default_attributes * template_attribute_find * template_check_required_attributes * template_check_required_base_attributes * template_free * template_set_default_common_attributes * template_update_attribute * template_validate_attribute * template_validate_attributes * template_validate_base_attribute */ #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "pkcs32.h" #include "p11util.h" #include "trace.h" /* template_add_attributes() * * blindly add the given attributes to the template. do no sanity checking * at this point. sanity checking will occur later. */ CK_RV template_add_attributes(TEMPLATE *tmpl, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) { CK_ATTRIBUTE *attr = NULL; CK_RV rc; unsigned int i; for (i = 0; i < ulCount; i++) { if (!is_attribute_defined(pTemplate[i].type)) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; } attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + pTemplate[i].ulValueLen); if (!attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } attr->type = pTemplate[i].type; attr->ulValueLen = pTemplate[i].ulValueLen; if (attr->ulValueLen != 0) { attr->pValue = (CK_BYTE *)attr + sizeof(CK_ATTRIBUTE); memcpy(attr->pValue, pTemplate[i].pValue, attr->ulValueLen); } else attr->pValue = NULL; rc = template_update_attribute(tmpl, attr); if (rc != CKR_OK) { free(attr); TRACE_DEVEL("template_update_attribute failed.\n"); return rc; } } return CKR_OK; } /* template_add_default_attributes() * Add default attributes to '*tmpl'. * '*basetmpl' may be used to derive values to the default attributes */ CK_RV template_add_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode) { CK_RV rc; /* first add the default common attributes */ rc = template_set_default_common_attributes(tmpl); if (rc != CKR_OK) { TRACE_DEVEL("template_set_default_common_attributes failed.\n"); return rc; } /* set the template class-specific default attributes */ switch (class) { case CKO_DATA: return data_object_set_default_attributes(tmpl, mode); case CKO_CERTIFICATE: if (subclass == CKC_X_509) return cert_x509_set_default_attributes(tmpl, mode); else return CKR_OK; case CKO_PUBLIC_KEY: switch (subclass) { case CKK_RSA: return rsa_publ_set_default_attributes(tmpl, basetmpl, mode); case CKK_DSA: return dsa_publ_set_default_attributes(tmpl, mode); case CKK_ECDSA: return ecdsa_publ_set_default_attributes(tmpl, mode); case CKK_DH: return dh_publ_set_default_attributes(tmpl, mode); case CKK_KEA: return kea_publ_set_default_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } case CKO_PRIVATE_KEY: switch (subclass) { case CKK_RSA: return rsa_priv_set_default_attributes(tmpl, mode); case CKK_DSA: return dsa_priv_set_default_attributes(tmpl, mode); case CKK_ECDSA: return ecdsa_priv_set_default_attributes(tmpl, mode); case CKK_DH: return dh_priv_set_default_attributes(tmpl, mode); case CKK_KEA: return kea_priv_set_default_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } case CKO_SECRET_KEY: switch (subclass) { case CKK_GENERIC_SECRET: return generic_secret_set_default_attributes(tmpl, mode); case CKK_RC2: return rc2_set_default_attributes(tmpl, mode); case CKK_RC4: return rc4_set_default_attributes(tmpl, mode); case CKK_RC5: return rc5_set_default_attributes(tmpl, mode); case CKK_DES: return des_set_default_attributes(tmpl, mode); case CKK_DES2: return des2_set_default_attributes(tmpl, mode); case CKK_DES3: return des3_set_default_attributes(tmpl, mode); case CKK_CAST: return cast_set_default_attributes(tmpl, mode); case CKK_CAST3: return cast3_set_default_attributes(tmpl, mode); case CKK_CAST5: return cast5_set_default_attributes(tmpl, mode); case CKK_IDEA: return idea_set_default_attributes(tmpl, mode); #if !(NOCDMF) case CKK_CDMF: return cdmf_set_default_attributes(tmpl, mode); #endif case CKK_SKIPJACK: return skipjack_set_default_attributes(tmpl, mode); case CKK_BATON: return baton_set_default_attributes(tmpl, mode); case CKK_JUNIPER: return juniper_set_default_attributes(tmpl, mode); case CKK_AES: return aes_set_default_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } case CKO_HW_FEATURE: switch (subclass) { case CKH_CLOCK: return clock_set_default_attributes(tmpl, mode); case CKH_MONOTONIC_COUNTER: return counter_set_default_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } case CKO_DOMAIN_PARAMETERS: switch (subclass) { case CKK_DSA: return dp_dsa_set_default_attributes(tmpl, mode); case CKK_DH: return dp_dh_set_default_attributes(tmpl, mode); case CKK_X9_42_DH: return dp_x9dh_set_default_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } /* template_attribute_find() * * find the attribute in the list and return its value */ CK_BBOOL template_attribute_find(TEMPLATE *tmpl, CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE **attr) { DL_NODE *node = NULL; CK_ATTRIBUTE *a = NULL; if (!tmpl || !attr) return FALSE; node = tmpl->attribute_list; while (node != NULL) { a = (CK_ATTRIBUTE *)node->data; if (type == a->type) { *attr = a; return TRUE; } node = node->next; } *attr = NULL; return FALSE; } /* template_attribute_find_multiple() * * find the attributes in the list and return their values */ void template_attribute_find_multiple(TEMPLATE *tmpl, ATTRIBUTE_PARSE_LIST *parselist, CK_ULONG plcount) { CK_ATTRIBUTE *attr = NULL; CK_ULONG i; for (i = 0; i < plcount; i++) { parselist[i].found = template_attribute_find(tmpl, parselist[i].type, &attr); if (parselist[i].found && parselist[i].ptr != NULL) memcpy(parselist[i].ptr, attr->pValue, parselist[i].len); } } /* template_check_required_attributes() */ CK_RV template_check_required_attributes(TEMPLATE *tmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode) { if (class == CKO_DATA) return data_object_check_required_attributes(tmpl, mode); else if (class == CKO_CERTIFICATE) { if (subclass == CKC_X_509) return cert_x509_check_required_attributes(tmpl, mode); else return cert_vendor_check_required_attributes(tmpl, mode); } else if (class == CKO_PUBLIC_KEY) { switch (subclass) { case CKK_RSA: return rsa_publ_check_required_attributes(tmpl, mode); case CKK_DSA: return dsa_publ_check_required_attributes(tmpl, mode); case CKK_ECDSA: return ecdsa_publ_check_required_attributes(tmpl, mode); case CKK_DH: return dh_publ_check_required_attributes(tmpl, mode); case CKK_KEA: return kea_publ_check_required_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown keytype } } else if (class == CKO_PRIVATE_KEY) { switch (subclass) { case CKK_RSA: return rsa_priv_check_required_attributes(tmpl, mode); case CKK_DSA: return dsa_priv_check_required_attributes(tmpl, mode); case CKK_ECDSA: return ecdsa_priv_check_required_attributes(tmpl, mode); case CKK_DH: return dh_priv_check_required_attributes(tmpl, mode); case CKK_KEA: return kea_priv_check_required_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } } else if (class == CKO_SECRET_KEY) { switch (subclass) { case CKK_GENERIC_SECRET: return generic_secret_check_required_attributes(tmpl, mode ); case CKK_RC2: return rc2_check_required_attributes(tmpl, mode); case CKK_RC4: return rc4_check_required_attributes(tmpl, mode); case CKK_RC5: return rc5_check_required_attributes(tmpl, mode); case CKK_DES: return des_check_required_attributes(tmpl, mode); case CKK_DES2: return des2_check_required_attributes(tmpl, mode); case CKK_DES3: return des3_check_required_attributes(tmpl, mode); case CKK_CAST: return cast_check_required_attributes(tmpl, mode); case CKK_CAST3: return cast3_check_required_attributes(tmpl, mode); case CKK_CAST5: return cast5_check_required_attributes(tmpl, mode); case CKK_IDEA: return idea_check_required_attributes(tmpl, mode); #if !(NOCDMF) case CKK_CDMF: return cdmf_check_required_attributes(tmpl, mode); #endif case CKK_SKIPJACK: return skipjack_check_required_attributes(tmpl, mode); case CKK_BATON: return baton_check_required_attributes(tmpl, mode); case CKK_JUNIPER: return juniper_check_required_attributes(tmpl, mode); case CKK_AES: return aes_check_required_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } } else if (class == CKO_HW_FEATURE) { switch (subclass) { case CKH_CLOCK: return clock_check_required_attributes(tmpl, mode); case CKH_MONOTONIC_COUNTER: return counter_check_required_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } else if (class == CKO_DOMAIN_PARAMETERS) { switch (subclass) { case CKK_DSA: return dp_dsa_check_required_attributes(tmpl, mode); case CKK_DH: return dp_dh_check_required_attributes(tmpl, mode); case CKK_X9_42_DH: return dp_x9dh_check_required_attributes(tmpl, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // default fallthru } /* template_check_required_base_attributes() * * check to make sure that attributes required by Cryptoki are * present. does not check to see if the attribute makes sense * for the particular object (that is done in the 'validate' routines) */ CK_RV template_check_required_base_attributes(TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr; CK_BBOOL found; found = template_attribute_find(tmpl, CKA_CLASS, &attr); if (mode == MODE_CREATE && found == FALSE) return CKR_TEMPLATE_INCOMPLETE; return CKR_OK; } /* template_compare() */ CK_BBOOL template_compare(CK_ATTRIBUTE *t1, CK_ULONG ulCount, TEMPLATE *t2) { CK_ATTRIBUTE *attr1 = NULL; CK_ATTRIBUTE *attr2 = NULL; CK_ULONG i; CK_RV rc; if (!t1 || !t2) return FALSE; attr1 = t1; for (i = 0; i < ulCount; i++) { rc = template_attribute_find(t2, attr1->type, &attr2); if (rc == FALSE) return FALSE; if (attr1->ulValueLen != attr2->ulValueLen) return FALSE; if (memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen) != 0) return FALSE; attr1++; } return TRUE; } /* template_copy() * * This doesn't copy the template items verbatim. The new template is in * the reverse order of the old one. This should not have any effect. * * This is very similar to template_merge(). template_merge() can also * be used to copy a list (of unique attributes) but is slower because for * each attribute, it must search through the list. */ CK_RV template_copy(TEMPLATE *dest, TEMPLATE *src) { DL_NODE *node; if (!dest || !src) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } node = src->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; CK_ATTRIBUTE *new_attr = NULL; CK_ULONG len; len = sizeof(CK_ATTRIBUTE) + attr->ulValueLen; new_attr = (CK_ATTRIBUTE *)malloc(len); if (!new_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy(new_attr, attr, len); new_attr->pValue = (CK_BYTE *)new_attr + sizeof(CK_ATTRIBUTE); dest->attribute_list = dlist_add_as_first(dest->attribute_list, new_attr); node = node->next; } return CKR_OK; } /* template_flatten() * this still gets used when saving token objects to disk */ CK_RV template_flatten(TEMPLATE *tmpl, CK_BYTE *dest) { DL_NODE *node = NULL; CK_BYTE *ptr = NULL; CK_ULONG_32 long_len; CK_ATTRIBUTE_32 *attr_32 = NULL; CK_ULONG Val; CK_ULONG_32 Val_32; CK_ULONG *pVal; long_len = sizeof(CK_ULONG); if (!tmpl || !dest) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } ptr = dest; node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; if (long_len == 4) { memcpy(ptr, attr, sizeof(CK_ATTRIBUTE) + attr->ulValueLen); ptr += sizeof(CK_ATTRIBUTE) + attr->ulValueLen; } else { attr_32 = malloc(sizeof(CK_ATTRIBUTE_32)); if (!attr_32) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } attr_32->type = attr->type; attr_32->pValue = 0x00; if ((attr->type == CKA_CLASS || attr->type == CKA_KEY_TYPE || attr->type == CKA_MODULUS_BITS || attr->type == CKA_VALUE_BITS || attr->type == CKA_CERTIFICATE_TYPE || attr->type == CKA_VALUE_LEN ) && attr->ulValueLen != 0) { attr_32->ulValueLen = sizeof(CK_ULONG_32); memcpy(ptr, attr_32, sizeof(CK_ATTRIBUTE_32)); ptr += sizeof(CK_ATTRIBUTE_32); pVal = (CK_ULONG *)attr->pValue; Val = *pVal; Val_32 = (CK_ULONG_32)Val; memcpy( ptr, &Val_32, sizeof(CK_ULONG_32)); ptr += sizeof(CK_ULONG_32); } else { attr_32->ulValueLen = attr->ulValueLen; memcpy(ptr, attr_32, sizeof(CK_ATTRIBUTE_32)); ptr += sizeof(CK_ATTRIBUTE_32); if (attr->ulValueLen != 0) { memcpy(ptr, attr->pValue, attr->ulValueLen); ptr += attr->ulValueLen; } } } node = node->next; } if (attr_32) free(attr_32); return CKR_OK; } CK_RV template_unflatten(TEMPLATE **new_tmpl, CK_BYTE *buf, CK_ULONG count) { return template_unflatten_withSize(new_tmpl, buf, count, -1); } /* Modified version of template_unflatten that checks * that buf isn't overread. buf_size=-1 turns off checking * (for backwards compatability) */ CK_RV template_unflatten_withSize(TEMPLATE **new_tmpl, CK_BYTE *buf, CK_ULONG count, int buf_size) { TEMPLATE *tmpl = NULL; CK_ATTRIBUTE *a2 = NULL; CK_BYTE *ptr = NULL; CK_ULONG i, len; CK_RV rc; CK_ULONG_32 long_len = sizeof(CK_ULONG); CK_ULONG_32 attr_ulong_32; CK_ULONG attr_ulong; CK_ATTRIBUTE *a1_64 = NULL; CK_ATTRIBUTE_32 *a1 = NULL; if (!new_tmpl || !buf) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } tmpl = (TEMPLATE *)malloc(sizeof(TEMPLATE)); if (!tmpl) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(tmpl, 0x0, sizeof(TEMPLATE)); ptr = buf; for (i=0; i < count; i++) { if (buf_size >= 0 && ((ptr + sizeof(CK_ATTRIBUTE)) > (buf + buf_size))) { template_free( tmpl ); return CKR_FUNCTION_FAILED; } if (long_len == 4) { a1_64 = (CK_ATTRIBUTE *)ptr; len = sizeof(CK_ATTRIBUTE) + a1_64->ulValueLen; a2 = (CK_ATTRIBUTE *)malloc(len); if (!a2) { template_free(tmpl); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } /* if a buffer size is given, make sure it * doesn't get overrun */ if (buf_size >= 0 && (((void*)a1_64 + len) > ((void*)buf + buf_size))) { free(a2); template_free(tmpl); return CKR_FUNCTION_FAILED; } memcpy(a2, a1_64, len); } else { a1 = (CK_ATTRIBUTE_32 *)ptr; if ((a1->type == CKA_CLASS || a1->type == CKA_KEY_TYPE || a1->type == CKA_MODULUS_BITS || a1->type == CKA_VALUE_BITS || a1->type == CKA_CERTIFICATE_TYPE || a1->type == CKA_VALUE_LEN) && a1->ulValueLen != 0) { len = sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG); } else { len = sizeof(CK_ATTRIBUTE) + a1->ulValueLen; } a2 = (CK_ATTRIBUTE *)malloc(len); if (!a2) { template_free(tmpl); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } a2->type = a1->type; if ((a1->type == CKA_CLASS || a1->type == CKA_KEY_TYPE || a1->type == CKA_MODULUS_BITS || a1->type == CKA_VALUE_BITS || a1->type == CKA_CERTIFICATE_TYPE || a1->type == CKA_VALUE_LEN) && a1->ulValueLen != 0) { a2->ulValueLen = sizeof(CK_ULONG); { CK_ULONG_32 *p32; CK_BYTE *pb2; pb2 = (CK_BYTE *)a1; pb2 += sizeof (CK_ATTRIBUTE_32); p32 = (CK_ULONG_32 *)pb2; attr_ulong_32 = *p32; } attr_ulong = attr_ulong_32; { CK_BYTE *pb2; pb2 = (CK_BYTE *)a2; pb2 += sizeof(CK_ATTRIBUTE); memcpy(pb2, (CK_BYTE *)&attr_ulong, sizeof(CK_ULONG)); } } else { CK_BYTE *pb2,*pb; a2->ulValueLen = a1->ulValueLen; pb2 = (CK_BYTE *)a2; pb2 += sizeof(CK_ATTRIBUTE); pb = (CK_BYTE *)a1; pb += sizeof(CK_ATTRIBUTE_32); /* if a buffer size is given, make sure it * doesn't get overrun */ if (buf_size >= 0 && (pb + a1->ulValueLen) > (buf + buf_size)) { free(a2); template_free(tmpl); return CKR_FUNCTION_FAILED; } memcpy(pb2, pb, a1->ulValueLen); } } if (a2->ulValueLen != 0) a2->pValue = (CK_BYTE *)a2 + sizeof(CK_ATTRIBUTE); else a2->pValue = NULL; rc = template_update_attribute(tmpl, a2); if (rc != CKR_OK) { free(a2); template_free(tmpl); return rc; } if (long_len == 4) ptr += len; else ptr += sizeof(CK_ATTRIBUTE_32) + a1->ulValueLen; } *new_tmpl = tmpl; return CKR_OK; } /* template_free() */ CK_RV template_free(TEMPLATE *tmpl) { if (!tmpl) return CKR_OK; while (tmpl->attribute_list) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)tmpl->attribute_list->data; if (attr) free(attr); tmpl->attribute_list = dlist_remove_node(tmpl->attribute_list, tmpl->attribute_list); } free(tmpl); return CKR_OK; } /* template_get_class */ CK_BBOOL template_get_class(TEMPLATE *tmpl, CK_ULONG *class, CK_ULONG *subclass) { DL_NODE *node; CK_BBOOL found; if (!tmpl || !class || !subclass) return FALSE; node = tmpl->attribute_list; /* have to iterate through all attributes. no early exits */ while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; if (attr->type == CKA_CLASS) { *class = *(CK_OBJECT_CLASS *)attr->pValue; found = TRUE; } /* underneath, these guys are both CK_ULONG so we * could combine this */ if (attr->type == CKA_CERTIFICATE_TYPE) *subclass = *(CK_CERTIFICATE_TYPE *)attr->pValue; if (attr->type == CKA_KEY_TYPE) *subclass = *(CK_KEY_TYPE *)attr->pValue; node = node->next; } return found; } CK_ULONG template_get_count(TEMPLATE *tmpl) { if (tmpl == NULL) return 0; return dlist_length(tmpl->attribute_list); } CK_ULONG template_get_size(TEMPLATE *tmpl) { DL_NODE *node; CK_ULONG size = 0; if (tmpl == NULL) return 0; node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; size += sizeof(CK_ATTRIBUTE) + attr->ulValueLen; node = node->next; } return size; } CK_ULONG template_get_compressed_size(TEMPLATE *tmpl) { DL_NODE *node; CK_ULONG size = 0; if (tmpl == NULL) return 0; node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; size += sizeof(CK_ATTRIBUTE_32); if ((attr->type == CKA_CLASS || attr->type == CKA_KEY_TYPE || attr->type == CKA_MODULUS_BITS || attr->type == CKA_VALUE_BITS || attr->type == CKA_CERTIFICATE_TYPE || attr->type == CKA_VALUE_LEN) && attr->ulValueLen != 0 ) { size += sizeof(CK_ULONG_32); } else { size += attr->ulValueLen; } node = node->next; } return size; } /* template_is_okay_to_reveal_attribute() * * determines whether the specified CK_ATTRIBUTE_TYPE is allowed to * be leave the card in the clear. note: the specified template doesn't need * to actually posess an attribute of type 'type'. The template is * provided mainly to determine the object class and subclass * * this routine is called by C_GetAttributeValue which exports the attributes * in the clear. this routine is NOT called when wrapping a key. */ CK_BBOOL template_check_exportability(TEMPLATE *tmpl, CK_ATTRIBUTE_TYPE type) { CK_ATTRIBUTE *sensitive = NULL; CK_ATTRIBUTE *extractable = NULL; CK_ULONG class; CK_ULONG subclass; CK_BBOOL sensitive_val; CK_BBOOL extractable_val; if (!tmpl) return FALSE; /* since 'tmpl' belongs to a validated object, it's safe * to assume that the following routine works */ template_get_class(tmpl, &class, &subclass); /* Early exits: * 1) CKA_SENSITIVE and CKA_EXTRACTABLE only apply to private key * and secret key objects. If object type is any other, then * by default the attribute is exportable. * * 2) If CKA_SENSITIVE = FALSE and CKA_EXTRACTABLE = TRUE then * all attributes are exportable */ if (class != CKO_PRIVATE_KEY && class != CKO_SECRET_KEY) return TRUE; sensitive_val = template_attribute_find(tmpl, CKA_SENSITIVE, &sensitive); extractable_val = template_attribute_find(tmpl, CKA_EXTRACTABLE, &extractable); if (sensitive_val && extractable_val) { sensitive_val = *(CK_BBOOL *)sensitive->pValue; extractable_val = *(CK_BBOOL *)extractable->pValue; if (sensitive_val == FALSE && extractable_val == TRUE) return TRUE; } else { /* technically, we should throw an error here... */ return FALSE; } /* at this point, we know the object must have CKA_SENSITIVE = TRUE * or CKA_EXTRACTABLE = FALSE (or both). * need to determine whether the particular attribute in question is * a "sensitive" attribute. */ if (class == CKO_PRIVATE_KEY) { switch (subclass) { case CKK_RSA: return rsa_priv_check_exportability(type); case CKK_DSA: return dsa_priv_check_exportability(type); case CKK_ECDSA: return ecdsa_priv_check_exportability(type); case CKK_X9_42_DH: case CKK_DH: return dh_priv_check_exportability(type); case CKK_KEA: return kea_priv_check_exportability(type); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return TRUE; } } else if (class == CKO_SECRET_KEY) { return secret_key_check_exportability(type); } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return TRUE; } /* template_merge() * * Merge two templates together: dest = dest U src * * src is destroyed in the process */ CK_RV template_merge(TEMPLATE *dest, TEMPLATE **src) { DL_NODE *node; CK_RV rc; if (!dest || !src) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } node = (*src)->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; rc = template_update_attribute(dest, attr); if (rc != CKR_OK) { TRACE_DEVEL("template_update_attribute failed.\n"); return rc; } /* we've assigned the node's data to a node in 'dest' */ node->data = NULL; node = node->next; } template_free(*src); *src = NULL; return CKR_OK; } /* template_set_default_common_attributes() * * Set the default attributes common to all objects: * * CKA_TOKEN: FALSE * CKA_PRIVATE: TRUE -- Cryptoki leaves this up to the token to decide * CKA_MODIFIABLE: TRUE * CKA_LABEL: empty string */ CK_RV template_set_default_common_attributes(TEMPLATE *tmpl) { CK_ATTRIBUTE *token_attr; CK_ATTRIBUTE *priv_attr; CK_ATTRIBUTE *mod_attr; CK_ATTRIBUTE *label_attr; /* add the default common attributes */ token_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); priv_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); mod_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); label_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + 0); if (!token_attr || !priv_attr || !mod_attr || !label_attr) { if (token_attr) free(token_attr); if (priv_attr) free(priv_attr); if (mod_attr) free(mod_attr); if (label_attr) free(label_attr); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } token_attr->type = CKA_TOKEN; token_attr->ulValueLen = sizeof(CK_BBOOL); token_attr->pValue = (CK_BYTE *)token_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)token_attr->pValue = FALSE; priv_attr->type = CKA_PRIVATE; priv_attr->ulValueLen = sizeof(CK_BBOOL); priv_attr->pValue = (CK_BYTE *)priv_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)priv_attr->pValue = FALSE; mod_attr->type = CKA_MODIFIABLE; mod_attr->ulValueLen = sizeof(CK_BBOOL); mod_attr->pValue = (CK_BYTE *)mod_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)mod_attr->pValue = TRUE; label_attr->type = CKA_LABEL; label_attr->ulValueLen = 0; // empty string label_attr->pValue = NULL; template_update_attribute(tmpl, token_attr); template_update_attribute(tmpl, priv_attr); template_update_attribute(tmpl, mod_attr); template_update_attribute(tmpl, label_attr); /* the TEMPLATE 'owns' the attributes now. * it is responsible for freeing them upon deletion... */ return CKR_OK; } /* template_update_attribute() * * modifies an existing attribute or adds a new attribute to the template * * Returns: TRUE on success, FALSE on failure */ CK_RV template_update_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *new_attr) { DL_NODE *node = NULL; CK_ATTRIBUTE *attr = NULL; if (!tmpl || !new_attr) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } node = tmpl->attribute_list; /* if the attribute already exists in the list, remove it. * this algorithm will limit an attribute to appearing at most * once in the list */ while (node != NULL) { attr = (CK_ATTRIBUTE *)node->data; if (new_attr->type == attr->type) { free(attr); tmpl->attribute_list = dlist_remove_node(tmpl->attribute_list, node); break; } node = node->next; } /* add the new attribute */ tmpl->attribute_list = dlist_add_as_first(tmpl->attribute_list, new_attr); return CKR_OK; } /* template_validate_attribute() * * essentially a group of if-then-else-switch clauses. separated from * template_validate_attributes() to make that routine more readable */ CK_RV template_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode) { if (class == CKO_DATA) return data_object_validate_attribute(tmpl, attr, mode); else if (class == CKO_CERTIFICATE) { if (subclass == CKC_X_509) return cert_x509_validate_attribute(tmpl, attr, mode); else return cert_vendor_validate_attribute(tmpl, attr, mode); } else if (class == CKO_PUBLIC_KEY) { switch (subclass) { case CKK_RSA: return rsa_publ_validate_attribute(tmpl, attr, mode); case CKK_DSA: return dsa_publ_validate_attribute(tmpl, attr, mode); case CKK_ECDSA: return ecdsa_publ_validate_attribute(tmpl, attr, mode); case CKK_DH: return dh_publ_validate_attribute(tmpl, attr, mode); case CKK_KEA: return kea_publ_validate_attribute(tmpl, attr, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } } else if (class == CKO_PRIVATE_KEY) { switch (subclass) { case CKK_RSA: return rsa_priv_validate_attribute(tmpl, attr, mode); case CKK_DSA: return dsa_priv_validate_attribute(tmpl, attr, mode); case CKK_ECDSA: return ecdsa_priv_validate_attribute(tmpl, attr, mode); case CKK_DH: return dh_priv_validate_attribute(tmpl, attr, mode); case CKK_KEA: return kea_priv_validate_attribute(tmpl, attr, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } } else if (class == CKO_SECRET_KEY) { switch (subclass) { case CKK_GENERIC_SECRET: return generic_secret_validate_attribute(tmpl, attr, mode); case CKK_RC2: return rc2_validate_attribute(tmpl, attr, mode); case CKK_RC4: return rc4_validate_attribute(tmpl, attr, mode); case CKK_RC5: return rc5_validate_attribute(tmpl, attr, mode); case CKK_DES: return des_validate_attribute(tmpl, attr, mode); case CKK_DES2: return des2_validate_attribute(tmpl, attr, mode); case CKK_DES3: return des3_validate_attribute(tmpl, attr, mode); case CKK_CAST: return cast_validate_attribute(tmpl, attr, mode); case CKK_CAST3: return cast3_validate_attribute(tmpl, attr, mode); case CKK_CAST5: return cast5_validate_attribute(tmpl, attr, mode); case CKK_IDEA: return idea_validate_attribute(tmpl, attr, mode); #if !(NOCDMF) case CKK_CDMF: return cdmf_validate_attribute(tmpl, attr, mode); #endif case CKK_SKIPJACK: return skipjack_validate_attribute(tmpl, attr, mode); case CKK_BATON: return baton_validate_attribute(tmpl, attr, mode); case CKK_JUNIPER: return juniper_validate_attribute(tmpl, attr, mode); case CKK_AES: return aes_validate_attribute(tmpl, attr, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type } } else if (class == CKO_HW_FEATURE) { switch (subclass) { case CKH_CLOCK: return clock_validate_attribute(tmpl, attr, mode); case CKH_MONOTONIC_COUNTER: return counter_validate_attribute(tmpl, attr, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } else if (class == CKO_DOMAIN_PARAMETERS) { switch (subclass) { case CKK_DSA: return dp_dsa_validate_attribute(tmpl, attr, mode); case CKK_DH: return dp_dh_validate_attribute(tmpl, attr, mode); case CKK_X9_42_DH: return dp_x9dh_validate_attribute(tmpl, attr, mode); default: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; // default fallthru } /* template_validate_attributes() * * walk through the list of attributes in the template validating each one */ CK_RV template_validate_attributes(TEMPLATE *tmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode) { DL_NODE *node; CK_RV rc = CKR_OK; node = tmpl->attribute_list; while (node) { CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data; rc = template_validate_attribute(tmpl, attr, class, subclass, mode); if (rc != CKR_OK) { TRACE_DEVEL("template_validate_attribute failed.\n"); return rc; } node = node->next; } return CKR_OK; } /* template_validate_base_attribute() */ CK_RV template_validate_base_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { if (!tmpl || !attr) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } switch (attr->type) { case CKA_CLASS: if ((mode & (MODE_CREATE|MODE_DERIVE|MODE_KEYGEN|MODE_UNWRAP)) != 0) return CKR_OK; break; case CKA_TOKEN: if ((mode & (MODE_CREATE|MODE_COPY|MODE_DERIVE|MODE_KEYGEN| MODE_UNWRAP)) != 0) return CKR_OK; break; case CKA_PRIVATE: if ((mode & (MODE_CREATE|MODE_COPY|MODE_DERIVE|MODE_KEYGEN| MODE_UNWRAP)) != 0) return CKR_OK; break; case CKA_LABEL: return CKR_OK; case CKA_IBM_OPAQUE: /* Allow this attribute to be modified in order to support * migratable keys on secure key tokens. */ if ((mode & (MODE_COPY|MODE_MODIFY)) != 0) return CKR_OK; break; case CKA_MODIFIABLE: if ((mode & (MODE_CREATE|MODE_COPY|MODE_DERIVE|MODE_KEYGEN| MODE_UNWRAP)) != 0) return CKR_OK; break; default: TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } opencryptoki+dfsg/usr/lib/pkcs11/common/cert.c0000755000175000017500000005056212630407154020364 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: cert.c // // Functions contained within: // // cert_check_required_attributes // cert_validate_attribute // cert_x509_check_required_attributes // cert_x509_set_default_attributes // cert_x509_validate_attribute // cert_vendor_check_required_attributes // cert_vendor_validate_attribute // #include #include #include // for memcmp() et al #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" // cert_check_required_attributes // // Checks for required attributes for generic CKO_CERTIFICATE objects // // CKA_CERTIFICATE_TYPE : must be present on MODE_CREATE. // CK_RV cert_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL found; if (!tmpl) return CKR_FUNCTION_FAILED; if (mode == MODE_CREATE) { found = template_attribute_find( tmpl, CKA_CERTIFICATE_TYPE, &attr ); if (found == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } // don't bother checking the value. it was checked in the 'validate' // routine. } return template_check_required_base_attributes( tmpl, mode ); } // cert_validate_attribute() // CK_RV cert_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { CK_CERTIFICATE_TYPE type; switch (attr->type) { case CKA_CERTIFICATE_TYPE: { if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } type = *(CK_CERTIFICATE_TYPE *)attr->pValue; if (type == CKC_X_509 || type >= CKC_VENDOR_DEFINED) return CKR_OK; else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } } break; default: return template_validate_base_attribute( tmpl, attr, mode ); } return template_validate_base_attribute( tmpl, attr, mode ); } // cert_x509_check_required_attributes() // CK_RV cert_x509_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_SUBJECT, &attr ); if (!found){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } return cert_check_required_attributes( tmpl, mode ); } // cert_x509_set_default_attributes() // // Set the default attributes for X.509 certificates // // CKA_ID : empty string // CKA_ISSUER : empty string // CKA_SERIAL_NUMBER : empty string // CK_RV cert_x509_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * id_attr = NULL; CK_ATTRIBUTE * issuer_attr = NULL; CK_ATTRIBUTE * serial_attr = NULL; // satisfy compiler warning.... // if (mode) id_attr = NULL; id_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); issuer_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); serial_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!id_attr || !issuer_attr || !serial_attr) { if (id_attr) free( id_attr ); if (issuer_attr) free( issuer_attr ); if (serial_attr) free( serial_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } id_attr->type = CKA_ID; id_attr->ulValueLen = 0; // empty string id_attr->pValue = NULL; issuer_attr->type = CKA_ISSUER; issuer_attr->ulValueLen = 0; // empty byte array issuer_attr->pValue = NULL; serial_attr->type = CKA_SERIAL_NUMBER; serial_attr->ulValueLen = 0; // empty byte array serial_attr->pValue = NULL; template_update_attribute( tmpl, id_attr ); template_update_attribute( tmpl, issuer_attr ); template_update_attribute( tmpl, serial_attr ); return CKR_OK; } // cert_x509_validate_attributes() // CK_RV cert_x509_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { switch (attr->type) { case CKA_SUBJECT: if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } else return CKR_OK; case CKA_ID: case CKA_ISSUER: case CKA_SERIAL_NUMBER: return CKR_OK; case CKA_VALUE: if (mode != MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } else return CKR_OK; default: return cert_validate_attribute( tmpl, attr, mode ); } } // cert_vendor_check_required_attributes() // CK_RV cert_vendor_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { // CKC_VENDOR has no required attributes // return cert_check_required_attributes( tmpl, mode ); } // cert_vendor_validate_attribute() // CK_RV cert_vendor_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { // cryptoki specifies no attributes for CKC_VENDOR certificates // return cert_validate_attribute( tmpl, attr, mode ); } opencryptoki+dfsg/usr/lib/pkcs11/common/shared_memory.c0000644000175000017500000002165612630407154022264 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token - Shared memory abstraction for OpenCryptoki * * (C) COPYRIGHT International Business Machines Corp. 2012 * * Author: Marcelo Cerri (mhcerri@br.ibm.com) * * Note: the functions in this files are implemented as an abstraction layer for * POSIX shared memory functions but they can be extended to support other * APIs of shared memory. */ #include #include #include #include #include #include #include #include #include #include #include /* For logging functions: */ #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" #include "shared_memory.h" /* * Helper macros for logging. */ #define SYS_ERROR(_errno, _msg, ...) \ do { \ char _sys_error[1024]; \ if (strerror_r(_errno, _sys_error, sizeof(_sys_error))) \ strcpy(_sys_error, "Unknown error"); \ syslog(LOG_ERR, "Error: " _msg " %s (errno=%d)", \ ##__VA_ARGS__, _sys_error, _errno); \ TRACE_ERROR("Error: " _msg " %s (errno=%d)", \ ##__VA_ARGS__, _sys_error, _errno); \ } while (0) /* * Shared context used to keep meta data into the shared memory. * * The address to data field is the address visible outside this file. * * See shm_open for more details. */ struct shm_context { /* * `ref` is a counter that is used to detect mismatching between * sm_open and sm_close calls. */ int ref; /* * `name` is the shared memory identifier and it is used to destroy * an allocated shared memory region. */ char name[SM_NAME_LEN + 1]; /* * `data_len` is the length of the variable length filed `data`. */ int data_len; /* * `data` points to the region that will actually be used by * `sm_open`s caller. */ char data[]; }; /* * Obtain the context pointer based on a data address. */ static inline struct shm_context * get_shm_context(void *addr) { struct shm_context *ctx = addr - offsetof(struct shm_context, data); return ctx; } /* * If a complete path is informed, convert it to a shared memory name. */ static char * convert_path_to_shm_name(const char *file_path) { char *name = NULL; size_t len = strlen(file_path) + 1; int i; char *it; /* Need a starting '/' */ if (file_path[0] != '/') len++; if (len > SM_NAME_LEN) { TRACE_ERROR("Error: path \"%s\" too long.\n", file_path); return NULL; } it = name = malloc(len + 1); if (name == NULL) { TRACE_ERROR("Error: failed to allocate memory for " "path \"%s\".\n", file_path); return NULL; } i = 0; *it++ = '/'; if (file_path[0] == '/') i++; for (; file_path[i]; i++, it++) { if (file_path[i] == '/') *it = '.'; else *it = file_path[i]; } *it = '\0'; TRACE_DEVEL("File path \"%s\" converted to \"%s\".\n", file_path, name); return name; } /* * Open a shared memory region identified by `sm_name` using permissions defined * by `mode` with length `len`. * * If the shared memory already exists and doesn't match the given length an * error is returned (if `force` is zero) or the shared memory is reinitialized * (if `force` is non zero). */ int sm_open(const char *sm_name, int mode, void **p_addr, size_t len, int force) { int rc; int fd = -1; void *addr = NULL; struct stat stat_buf; char *name = NULL; struct shm_context *ctx = NULL; size_t real_len = sizeof(*ctx) + len; int created = 0; /* * This is used for portability purpose. Please check `shm_open` * man page for more details. */ if ((name = convert_path_to_shm_name(sm_name)) == NULL) { rc = -EINVAL; goto done; } /* try and open first... */ fd = shm_open(name, O_RDWR, mode); if (fd < 0) { /* maybe it needs to be created ... */ fd = shm_open(name, O_RDWR | O_CREAT, mode); if (fd < 0) { rc = -errno; SYS_ERROR(errno, "Failed to open shared memory \"%s\".\n", name); goto done; } else { /* umask may have altered permissions if we created * the shared memory in above call, so set proper * permissions just in case. */ if (fchmod(fd, mode) == -1) { rc = -errno; SYS_ERROR(errno, "fchmod(%s): %s\n", name, strerror(errno)); goto done; } } } /* * fstat is used here to check if the shared memory region already * exists. When a shared memory region is first created, its size is * always zero. */ if (fstat(fd, &stat_buf)) { rc = -errno; SYS_ERROR(errno, "Cannot stat \"%s\".\n", name); goto done; } /* * The shared memory needs to be extended when created (when its length * is zero). When its length is not zero and is not equal to the * expected size, an error is returned if `force` is not set. If `force` * is set, the existing shared memory is truncated and any data on it is * lost. */ if (stat_buf.st_size == 0 || (force && stat_buf.st_size != real_len)) { /* * If the shared memory region was just created, it's necessary * to extend it to the expected size using ftruncate. * * It's important to notice that it is resized to a length * greater than the value requested (`len`). The extra space is * used to store additional information related to the shared * memory, such as its size and identifier. */ created = 1; TRACE_DEVEL("Truncating \"%s\".\n", name); if (ftruncate(fd, real_len) < 0) { rc = -errno; SYS_ERROR(errno, "Cannot truncate \"%s\".\n", name); goto done; } } else if (stat_buf.st_size != real_len) { rc = -1; TRACE_ERROR("Error: shared memory \"%s\" exists and does not " "match the expected size.\n", name); goto done; } addr = mmap(NULL, real_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == NULL) { rc = -errno; SYS_ERROR(errno, "Failed to map \"%s\" to memory.\n", name); goto done; } /* * `addr` points to the start of the shared memory region. The first * bytes of it are used to store the additional information about the * shared memory allocated. This info can be accessed using an pointer * to a `shm_context` structure. */ ctx = addr; if (created) { strcpy(ctx->name, name); ctx->data_len = len; memset(ctx->data, 0, ctx->data_len); } ctx->ref += 1; /* * The portion of the shared memory that will actually be used by the * called is pointed by `data`. * * The address returned (in this case `ctx->data`) is equal to * `addr + sizeof(struct shm_context)`, which means that the additional * data is skipped off. */ *p_addr = ctx->data; rc = created ? 0 : 1; if (sm_sync(ctx->data)) { rc = -errno; SYS_ERROR(errno, "Failed to sync shared memory \"%s\".\n", name); if (created) sm_close(addr, 1); goto done; } TRACE_DEVEL("open: ref = %d\n", ctx->ref); done: if (fd >= 0) close(fd); if (name) free(name); return rc; } /* * Close (unmap) a shared memory region. `destroy` indicates if the shared * memory should be destroyed if no other processes are using it. */ int sm_close(void *addr, int destroy) { int rc; int ref; char name[SM_NAME_LEN + 1] = { 0, }; struct shm_context *ctx = get_shm_context(addr); if (ctx->ref <= 0) { TRACE_ERROR("Error: invalid shared memory address %p " "(ref=%d).\n", addr, ctx->ref); return -EINVAL; } ref = --ctx->ref; TRACE_DEVEL("close: ref = %d\n", ref); if (ref == 0 && destroy) { strncpy(name, ctx->name, SM_NAME_LEN); name[SM_NAME_LEN] = '\0'; } if (munmap(ctx, sizeof(*ctx) + ctx->data_len)) { rc = -errno; SYS_ERROR(errno, "Failed to unmap \"%s\" (%p).\n", name, ctx); return rc; } if (ref == 0 && destroy) { TRACE_DEVEL("Deleting shared memory \"%s\".\n", name); if ((rc = sm_destroy(name)) != 0) return rc; } return 0; } /* * Destroy a shared memory region. */ int sm_destroy(const char *name) { int rc; if (shm_unlink(name)) { rc = -errno; SYS_ERROR(errno, "Failed to delete shared memory \"%s\".\n", name); return rc; } return 0; } /* * Force sync for a shared memory region. */ int sm_sync(void *addr) { struct shm_context *ctx = get_shm_context(addr); if (ctx->ref <= 0) { TRACE_ERROR("Error: invalid shared memory address %p " "(ref=%d).\n", addr, ctx->ref); return -EINVAL; } return msync(ctx, ctx->data_len, MS_SYNC); } /* * Get the name of the shared memory indicated by `addr` and copy it to the * given `buffer`. */ int sm_copy_name(void *addr, char *buffer, size_t len) { size_t name_len; struct shm_context *ctx = get_shm_context(addr); if (ctx->ref <= 0) { TRACE_ERROR("Error: invalid shared memory address %p " "(ref=%d).\n", addr, ctx->ref); return -EINVAL; } name_len = strlen(ctx->name); if (len <= name_len) return -ENOSPC; strcpy(buffer, ctx->name); return 0; } /* * Return the reference count for the given shared memory. */ int sm_get_count(void *addr) { struct shm_context *ctx = get_shm_context(addr); if (ctx->ref <= 0) { TRACE_ERROR("Error: invalid shared memory address %p " "(ref=%d).\n", addr, ctx->ref); return -EINVAL; } return ctx->ref; } opencryptoki+dfsg/usr/lib/pkcs11/common/list.h0000644000175000017500000000542212630407154020377 0ustar xnoxxnox/* * Very small linked list implementation. * * For simplicity and portability it doesn't use GCC extensions and sticks with * C89. That means there's no hidden variable declaration or type inference * inside the macros. */ #ifndef _LIST_H_ #define _LIST_H_ #include /* for offsetof */ /* * Typedefs for lists and list entries. * * List entry should be defined as a member in an application-specific * structure. */ typedef struct _list list_t; typedef struct _list_entry list_entry_t; struct _list { list_entry_t *head; list_entry_t *tail; }; struct _list_entry { list_entry_t *next; list_entry_t *prev; list_t *list; }; /* A helper macro */ #ifndef container_of #define container_of(_pt, _type, _field) \ ((_type *) (!(_pt) ? NULL : (((char *) (_pt)) - offsetof(_type, _field)))) #endif /* * Macro to iterate over a list. * * It can *NOT* be used to remove entries while iterating. * */ #define for_each_list_entry(_head, _type, _var, _field) \ for (_var = container_of((_head)->head, _type, _field); \ (_var) && &((_var)->_field); \ _var = container_of((_var)->_field.next, _type, _field)) /* * Similar to for_each_list_entry but it's possible to remove an entry while * iterating. * * It uses an additional list_entry_t* to hold the value of the next element. */ #define for_each_list_entry_safe(_head, _type, _var, _field, _next) \ for (_var = container_of((_head)->head, _type, _field); \ (_var) && &((_var)->_field) && \ ((_next = (_var)->_field.next) || 1); \ _var = container_of(_next, _type, _field)) /* * Assignment initialization macro. */ #define LIST_INIT() \ { NULL, NULL }; /* * Initialize a list. */ static inline void list_init(list_t *list) { list->head = list->tail = NULL; } static inline int list_is_empty(list_t *list) { return (list->head == NULL); } /* * Insert a element at the head. */ static inline void list_insert_head(list_t *list, list_entry_t *new) { if (!list->head) { new->next = new->prev = NULL; list->head = list->tail = new; } else { new->prev = NULL; new->next = list->head; list->head->prev = new; list->head = new; } new->list = list; } /* * Insert a element at the end. */ static inline void list_insert_tail(list_t *list, list_entry_t *new) { if (!list->tail) { new->next = new->prev = NULL; list->head = list->tail = new; } else { new->next = NULL; new->prev = list->tail; list->tail->next = new; list->tail = new; } new->list = list; } /* * Remove an element. */ static inline void list_remove(list_entry_t *entry) { list_t *list = entry->list; if (list->head == entry) list->head = entry->next; if (list->tail == entry) list->tail = entry->prev; if (entry->next) entry->next->prev = entry->prev; if (entry->prev) entry->prev->next = entry->next; } #endif opencryptoki+dfsg/usr/lib/pkcs11/common/mech_des.c0000755000175000017500000016077112630407154021202 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: mech_des.c // // Mechanisms for DES // #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV pk_des_ecb_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES_ECB requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_des_ecb_encrypt( in_data, in_data_len, out_data, out_data_len, key ); } // // CK_RV des_ecb_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES_ECB requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_des_ecb_decrypt(in_data, in_data_len, out_data, out_data_len, key ); } // // CK_RV pk_des_cbc_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES_CBC requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_des_cbc_encrypt(in_data, in_data_len, out_data, out_data_len, ctx->mech.pParameter, key); } // // CK_RV des_cbc_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES_CBC requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_des_cbc_decrypt(in_data, in_data_len, out_data, out_data_len, ctx->mech.pParameter, key); } // // CK_RV des_cbc_pad_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_BYTE *clear = NULL; CK_ULONG padded_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // DES-CBC-PAD has no input length requirements // rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // compute the output length, accounting for padding // padded_len = DES_BLOCK_SIZE * (in_data_len / DES_BLOCK_SIZE + 1); if (length_only == TRUE) { *out_data_len = padded_len; return CKR_OK; } if (*out_data_len < padded_len) { *out_data_len = padded_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } clear = (CK_BYTE *)malloc( padded_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( clear, in_data, in_data_len ); add_pkcs_padding( clear + in_data_len, DES_BLOCK_SIZE, in_data_len, padded_len ); rc = ckm_des_cbc_encrypt(clear, padded_len, out_data, out_data_len, ctx->mech.pParameter, key); free( clear ); return rc; } // // CK_RV des_cbc_pad_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_BYTE *clear = NULL; CK_ULONG padded_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // // no need to validate the input length since we'll pad as necessary // rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // we're decrypting so even with CBC-PAD, we should have an integral // number of block to decrypt // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } // the amount of cleartext after stripping the padding will actually be less // than the input bytes... // padded_len = in_data_len; if (length_only == TRUE) { *out_data_len = padded_len; return CKR_OK; } clear = (CK_BYTE *)malloc( padded_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = ckm_des_cbc_decrypt(in_data, in_data_len, clear, &padded_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { strip_pkcs_padding( clear, padded_len, out_data_len ); memcpy( out_data, clear, *out_data_len ); } free( clear ); return rc; } // // CK_RV des_ecb_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % DES_BLOCK_SIZE); out_len = (total - remain); // should always be at least 1 block if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); rc = ckm_des_ecb_encrypt(clear, out_len, out_data, out_data_len, key); if (rc == CKR_OK) { *out_data_len = out_len; // update the context buffer. we already used the buffer's current // contents so we completely overwrite it // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV des_ecb_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % DES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_des_ecb_decrypt(cipher, out_len, out_data, out_data_len, key); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV des_cbc_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % DES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); rc = ckm_des_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { *out_data_len = out_len; // the new init_v is the last encrypted data block // memcpy( ctx->mech.pParameter, out_data + (*out_data_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE ); // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV des_cbc_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = context->len + in_data_len; if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = total % DES_BLOCK_SIZE; out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_des_cbc_decrypt(cipher, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { *out_data_len = out_len; // the new init_v is the last decrypted data block // memcpy( ctx->mech.pParameter, cipher + (out_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE ); // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV des_cbc_pad_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); // note, this is subtly different from the other encrypt update routines // if (total <= DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block + 1 byte // remain = total % DES_BLOCK_SIZE; out_len = total - remain; if (remain == 0) { remain = DES_BLOCK_SIZE; out_len -= DES_BLOCK_SIZE; } if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } // at this point, we should have: // 1) remain != 0 // 2) out_len != 0 // rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); // // we don't do padding during the update // rc = ckm_des_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { // the new init_v is the last encrypted data block // memcpy( ctx->mech.pParameter, out_data + (*out_data_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE ); // copy the remaining 'new' input data to the temporary space // memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV des_cbc_pad_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); // note, this is subtly different from the other decrypt update routines // if (total <= DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block + 1 byte // remain = total % DES_BLOCK_SIZE; out_len = total - remain; if (remain == 0) { remain = DES_BLOCK_SIZE; out_len -= DES_BLOCK_SIZE; } if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } // at this point, we should have: // 1) remain != 0 // 2) out_len != 0 // rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_des_cbc_decrypt(cipher, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { // the new init_v is the last decrypted data block // memcpy( ctx->mech.pParameter, cipher + (out_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE ); // copy the remaining 'new' input data to the temporary space // memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV des_ecb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (DES_CONTEXT *)ctx->context; // DES-ECB does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV des_ecb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (DES_CONTEXT *)ctx->context; // DES-ECB does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV des_cbc_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (DES_CONTEXT *)ctx->context; // DES-CBC does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV des_cbc_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (DES_CONTEXT *)ctx->context; // DES-CBC does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV des_cbc_pad_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; OBJECT *key = NULL; CK_BYTE clear[2 * DES_BLOCK_SIZE]; CK_ULONG out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } context = (DES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate one block of output // if a full block is stored, we generate two blocks of output (one pad block) // if (context->len == DES_BLOCK_SIZE) out_len = 2 * DES_BLOCK_SIZE; else out_len = DES_BLOCK_SIZE; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } else { memcpy( clear, context->data, context->len ); add_pkcs_padding( clear + context->len, DES_BLOCK_SIZE, context->len, out_len ); rc = ckm_des_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); return rc; } } // // CK_RV des_cbc_pad_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; OBJECT *key = NULL; CK_BYTE clear[DES_BLOCK_SIZE]; CK_BYTE cipher[DES_BLOCK_SIZE]; CK_ULONG out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } context = (DES_CONTEXT *)ctx->context; // there had better be a full block in the context buffer // if (context->len != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } // we don't know a priori how much data we'll be returning. we won't // know until after we decrypt it and strip the padding. it's possible // that we'll return nothing (the final block might be a padding block). // out_len = DES_BLOCK_SIZE; // upper bound on what we'll return if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } else { memcpy( cipher, context->data, DES_BLOCK_SIZE ); rc = ckm_des_cbc_decrypt(cipher, DES_BLOCK_SIZE, clear, &out_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { strip_pkcs_padding( clear, DES_BLOCK_SIZE, &out_len ); if (out_len != 0) memcpy( out_data, clear, out_len ); *out_data_len = out_len; } return rc; } } // // mechanisms // // // CK_RV ckm_des_key_gen( TEMPLATE *tmpl ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * opaque_attr = NULL; CK_ATTRIBUTE * key_type_attr = NULL; CK_ATTRIBUTE * class_attr = NULL; CK_ATTRIBUTE * local_attr = NULL; CK_BYTE * des_key = NULL; CK_BYTE dummy_key[DES_KEY_SIZE] = { 0, }; CK_ULONG rc; CK_ULONG keysize; if (token_specific.t_des_key_gen == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (token_specific.token_keysize) keysize = token_specific.token_keysize; else keysize = DES_KEY_SIZE; if ((des_key = (CK_BYTE *)calloc(1,keysize)) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = token_specific.t_des_key_gen(des_key, keysize, DES_KEY_SIZE); if (rc != CKR_OK) goto err; /* For secure-key keys put in CKA_IBM_OPAQUE * and put dummy_key in CKA_VALUE. */ if (token_specific.token_keysize) { opaque_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + keysize); if (!opaque_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto err; } opaque_attr->type = CKA_IBM_OPAQUE; opaque_attr->ulValueLen = keysize; opaque_attr->pValue = (CK_BYTE *)opaque_attr + sizeof(CK_ATTRIBUTE); memcpy(opaque_attr->pValue, des_key, keysize); template_update_attribute(tmpl, opaque_attr); } value_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + DES_KEY_SIZE ); key_type_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); class_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); local_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!value_attr || !key_type_attr || !class_attr || !local_attr) { if (value_attr) free( value_attr ); if (key_type_attr) free( key_type_attr ); if (class_attr) free( class_attr ); if (local_attr) free( local_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto err; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = DES_KEY_SIZE; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); if (token_specific.token_keysize) memcpy( value_attr->pValue, dummy_key, DES_KEY_SIZE ); else memcpy( value_attr->pValue, des_key, DES_KEY_SIZE ); free(des_key); key_type_attr->type = CKA_KEY_TYPE; key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE); key_type_attr->pValue = (CK_BYTE *)key_type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)key_type_attr->pValue = CKK_DES; class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY; local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = TRUE; template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, key_type_attr ); template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, local_attr ); return CKR_OK; err: if (des_key) free(des_key); return rc; } #if !(NOCDMF) // // CK_RV ckm_cdmf_key_gen( TEMPLATE *tmpl ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * key_type_attr = NULL; CK_ATTRIBUTE * class_attr = NULL; CK_ATTRIBUTE * local_attr = NULL; CK_BYTE cdmf_key[DES_KEY_SIZE]; CK_ULONG repl_len, expected_repl_len; CK_ULONG rc; repl_len = expected_repl_len = DES_KEY_SIZE; rc = communicate( PK_CDMF_KEYGEN, NULL, 0, cdmf_key, &repl_len, NULL, 0, NULL, 0 ); if (rc == CKR_OK) { if (repl_len != expected_repl_len) return CKR_GENERAL_ERROR; } value_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + DES_KEY_SIZE ); key_type_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); class_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); local_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!value_attr || !key_type_attr || !class_attr || !local_attr) { if (value_attr) free( value_attr ); if (key_type_attr) free( key_type_attr ); if (class_attr) free( class_attr ); if (local_attr) free( local_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = DES_KEY_SIZE; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); memcpy( value_attr->pValue, cdmf_key, DES_KEY_SIZE ); key_type_attr->type = CKA_KEY_TYPE; key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE); key_type_attr->pValue = (CK_BYTE *)key_type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)key_type_attr->pValue = CKK_CDMF; class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY; local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = TRUE; template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, key_type_attr ); template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, local_attr ); return CKR_OK; } #endif // // CK_RV ckm_des_ecb_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_des_ecb == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_des_ecb(in_data, in_data_len, out_data, out_data_len, key, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific des_ecb encrypt failed.\n"); return rc; } // // CK_RV ckm_des_ecb_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_des_ecb == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_des_ecb(in_data, in_data_len, out_data, out_data_len, key, 0); if (rc != CKR_OK) TRACE_ERROR("Token specific des ecb decrypt failed.\n"); return rc; } // // CK_RV ckm_des_cbc_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_BYTE * init_v, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !init_v || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_des_cbc == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_des_cbc(in_data, in_data_len, out_data, out_data_len, key, init_v, 1); if (rc != CKR_OK) TRACE_ERROR("Token specific dec cbc encrypt failed.\n"); return rc; } // // CK_RV ckm_des_cbc_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_BYTE * init_v, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !init_v || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_des_cbc == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_des_cbc(in_data, in_data_len, out_data, out_data_len, key, init_v, 0); if (rc != CKR_OK) TRACE_ERROR("Token specific des cbc decrypt failed.\n"); return rc; } // we're preparing to wrap a key using DES. need to make sure the // data length is a integral multiple of the DES block size. // // PKCS #11 specifies that the padding shall be in the form of NULL // bytes appended to the data // // this routine works with either DES and 3DES as the wrapping mechanism // CK_RV ckm_des_wrap_format( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len ) { CK_BYTE * ptr = NULL; CK_ULONG len1, len2; len1 = *data_len; // if the input key data isn't a multiple of the blocksize, // we pad with NULLs to the next blocksize multiple. // if (len1 % DES_BLOCK_SIZE != 0) { len2 = DES_BLOCK_SIZE * ((len1 / DES_BLOCK_SIZE) + 1); if (length_only == FALSE) { ptr = (CK_BYTE *)realloc(*data, len2); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } else memset( ptr + len1, 0x0, (len2 - len1) ); *data = ptr; *data_len = len2; } } return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/globals.c0000755000175000017500000007317512630407154021057 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ #include #include #include "pkcs11types.h" #include "stdll.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" CK_SLOT_INFO slot_info; CK_BBOOL initialized = FALSE; // native_mutex is used to protect C_Initialize. It gets created when the DLL // is attached, it gets destroyed when the DLL is detached // pthread_mutex_t native_mutex ; MUTEX pkcs_mutex, obj_list_mutex, sess_list_mutex, login_mutex; struct btree sess_btree = { NULL, NULL, 0UL, 0UL }; struct btree sess_obj_btree = { NULL, NULL, 0UL, 0UL }; struct btree publ_token_obj_btree = { NULL, NULL, 0UL, 0UL }; struct btree priv_token_obj_btree = { NULL, NULL, 0UL, 0UL }; struct btree object_map_btree = { NULL, NULL, 0UL, 0UL }; CK_ULONG ro_session_count = 0; CK_STATE global_login_state = CKS_RO_PUBLIC_SESSION; LW_SHM_TYPE *global_shm; //CK_ULONG next_session_handle = 1; //CK_ULONG next_object_handle = 1; TOKEN_DATA *nv_token_data = NULL; struct ST_FCN_LIST function_list ; extern CK_RV LW_Initialize(); /* extern CK_RV SC_Initialize */ extern CK_RV SC_GetFunctionList(); /* extern CK_RV SC_GetFunctionList */ extern CK_RV SC_GetTokenInfo(); /* extern CK_RV SC_GetTokenInfo */ extern CK_RV SC_GetMechanismList(); /* extern CK_RV SC_GetMechanismList */ extern CK_RV SC_GetMechanismInfo(); /* extern CK_RV SC_GetMechanismInfo */ extern CK_RV SC_InitToken(); /* extern CK_RV SC_InitToken */ extern CK_RV SC_InitPIN(); /* extern CK_RV SC_InitPIN */ extern CK_RV SC_SetPIN(); /* extern CK_RV SC_SetPIN */ extern CK_RV SC_OpenSession(); /* extern CK_RV SC_OpenSession */ extern CK_RV SC_CloseSession(); /* extern CK_RV SC_CloseSession */ extern CK_RV SC_CloseAllSessions(); /* extern CK_RV SC_CloseAllSessions */ extern CK_RV SC_GetSessionInfo(); /* extern CK_RV SC_GetSessionInfo */ extern CK_RV SC_GetOperationState(); /* extern CK_RV SC_GetOperationState */ extern CK_RV SC_SetOperationState(); /* extern CK_RV SC_SetOperationState */ extern CK_RV SC_Login(); /* extern CK_RV SC_Login */ extern CK_RV SC_Logout(); /* extern CK_RV SC_Logout */ extern CK_RV SC_CreateObject(); /* extern CK_RV SC_CreateObject */ extern CK_RV SC_CopyObject(); /* extern CK_RV SC_CopyObject */ extern CK_RV SC_DestroyObject(); /* extern CK_RV SC_DestroyObject */ extern CK_RV SC_GetObjectSize(); /* extern CK_RV SC_GetObjectSize */ extern CK_RV SC_GetAttributeValue(); /* extern CK_RV SC_GetAttributeValue */ extern CK_RV SC_SetAttributeValue(); /* extern CK_RV SC_SetAttributeValue */ extern CK_RV SC_FindObjectsInit(); /* extern CK_RV SC_FindObjectsInit */ extern CK_RV SC_FindObjects(); /* extern CK_RV SC_FindObjects */ extern CK_RV SC_FindObjectsFinal(); /* extern CK_RV SC_FindObjectsFinal */ extern CK_RV SC_EncryptInit(); /* extern CK_RV SC_EncryptInit */ extern CK_RV SC_Encrypt(); /* extern CK_RV SC_Encrypt */ extern CK_RV SC_EncryptUpdate(); /* extern CK_RV SC_EncryptUpdate */ extern CK_RV SC_EncryptFinal(); /* extern CK_RV SC_EncryptFinal */ extern CK_RV SC_DecryptInit(); /* extern CK_RV SC_DecryptInit */ extern CK_RV SC_Decrypt(); /* extern CK_RV SC_Decrypt */ extern CK_RV SC_DecryptUpdate(); /* extern CK_RV SC_DecryptUpdate */ extern CK_RV SC_DecryptFinal(); /* extern CK_RV SC_DecryptFinal */ extern CK_RV SC_DigestInit(); /* extern CK_RV SC_DigestInit */ extern CK_RV SC_Digest(); /* extern CK_RV SC_Digest */ extern CK_RV SC_DigestUpdate(); /* extern CK_RV SC_DigestUpdate */ extern CK_RV SC_DigestKey(); /* extern CK_RV SC_DigestKey */ extern CK_RV SC_DigestFinal(); /* extern CK_RV SC_DigestFinal */ extern CK_RV SC_SignInit(); /* extern CK_RV SC_SignInit */ extern CK_RV SC_Sign(); /* extern CK_RV SC_Sign */ extern CK_RV SC_SignUpdate(); /* extern CK_RV SC_SignUpdate */ extern CK_RV SC_SignFinal(); /* extern CK_RV SC_SignFinal */ extern CK_RV SC_SignRecoverInit(); /* extern CK_RV SC_SignRecoverInit */ extern CK_RV SC_SignRecover(); /* extern CK_RV SC_SignRecover */ extern CK_RV SC_VerifyInit(); /* extern CK_RV SC_VerifyInit */ extern CK_RV SC_Verify(); /* extern CK_RV SC_Verify */ extern CK_RV SC_VerifyUpdate(); /* extern CK_RV SC_VerifyUpdate */ extern CK_RV SC_VerifyFinal(); /* extern CK_RV SC_VerifyFinal */ extern CK_RV SC_VerifyRecoverInit(); /* extern CK_RV SC_VerifyRecoverInit */ extern CK_RV SC_VerifyRecover(); /* extern CK_RV SC_VerifyRecover */ extern CK_RV SC_DigestEncryptUpdate(); /* extern CK_RV SC_DigestEncryptUpdate */ extern CK_RV SC_DecryptDigestUpdate(); /* extern CK_RV SC_DecryptDigestUpdate */ extern CK_RV SC_SignEncryptUpdate(); /* extern CK_RV SC_SignEncryptUpdate */ extern CK_RV SC_DecryptVerifyUpdate(); /* extern CK_RV SC_DecryptVerifyUpdate */ extern CK_RV SC_GenerateKey(); /* extern CK_RV SC_GenerateKey */ extern CK_RV SC_GenerateKeyPair(); /* extern CK_RV SC_GenerateKeyPair */ extern CK_RV SC_WrapKey(); /* extern CK_RV SC_WrapKey */ extern CK_RV SC_UnwrapKey(); /* extern CK_RV SC_UnwrapKey */ extern CK_RV SC_DeriveKey(); /* extern CK_RV SC_DeriveKey */ extern CK_RV SC_SeedRandom(); /* extern CK_RV SC_SeedRandom */ extern CK_RV SC_GenerateRandom(); /* extern CK_RV SC_GenerateRandom */ extern CK_RV SC_GetFunctionStatus(); /* extern CK_RV SC_GetFunctionStatus */ extern CK_RV SC_CancelFunction(); /* extern CK_RV SC_CancelFunction */ extern CK_RV SC_WaitForSlotEvent(); /* extern CK_RV SC_WaitForSlotEvent */ // OBJECT IDENTIFIERs // CK_BYTE ber_idDSA[] = { 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01 }; CK_BYTE ber_rsaEncryption[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }; CK_BYTE ber_md2WithRSAEncryption[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02 }; CK_BYTE ber_md4WithRSAEncryption[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x03 }; CK_BYTE ber_md5WithRSAEncryption[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04 }; CK_BYTE ber_sha1WithRSAEncryption[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 }; // Algorithm IDs. (Sequence of OID plus parms, usually NULL) // CK_BYTE ber_AlgMd2[] = { 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00 }; CK_BYTE ber_AlgMd5[] = { 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00 }; CK_BYTE ber_AlgSha1[] = { 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00 }; CK_BYTE ber_AlgSha256[] = { 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00 }; CK_BYTE ber_AlgSha384[] = { 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00 }; CK_BYTE ber_AlgSha512[] = { 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00 }; CK_BYTE ber_AlgIdRSAEncryption[] = { 0x30, 0x0D, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00 }; // ID Lengths // CK_ULONG ber_idDSALen = sizeof(ber_idDSA); CK_ULONG ber_rsaEncryptionLen = sizeof(ber_rsaEncryption); CK_ULONG ber_md2WithRSAEncryptionLen = sizeof(ber_md2WithRSAEncryption); CK_ULONG ber_md4WithRSAEncryptionLen = sizeof(ber_md4WithRSAEncryption); CK_ULONG ber_md5WithRSAEncryptionLen = sizeof(ber_md5WithRSAEncryption); CK_ULONG ber_sha1WithRSAEncryptionLen= sizeof(ber_sha1WithRSAEncryption); CK_ULONG ber_AlgMd2Len= sizeof(ber_AlgMd2); CK_ULONG ber_AlgMd5Len= sizeof(ber_AlgMd5); CK_ULONG ber_AlgSha1Len= sizeof(ber_AlgSha1); CK_ULONG ber_AlgSha256Len= sizeof(ber_AlgSha256); CK_ULONG ber_AlgSha384Len= sizeof(ber_AlgSha384); CK_ULONG ber_AlgSha512Len= sizeof(ber_AlgSha512); CK_ULONG ber_AlgIdRSAEncryptionLen = sizeof(ber_AlgIdRSAEncryption); CK_ULONG des_weak_count = 4; CK_ULONG des_semi_weak_count = 12; CK_ULONG des_possibly_weak_count = 48; CK_BYTE des_weak_keys[4][8] = { {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, {0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E}, {0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1}, {0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE} }; CK_BYTE des_semi_weak_keys[12][8] = { {0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE}, {0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01}, {0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1}, {0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E}, {0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1}, {0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01}, {0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE}, {0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E}, {0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E}, {0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01}, {0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE}, {0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1} }; CK_BYTE des_possibly_weak_keys[48][8] = { {0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E, 0x01, 0x01}, {0x01, 0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E, 0x01}, {0x1F, 0x01, 0x01, 0x1F, 0x0E, 0x01, 0x01, 0x0E}, {0x01, 0x01, 0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E}, {0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1, 0x01, 0x01}, {0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01}, {0xFE, 0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E, 0x01}, {0xE0, 0xFE, 0x1F, 0x01, 0xF1, 0xFE, 0x0E, 0x01}, {0xFE, 0xE0, 0x01, 0x1F, 0xFE, 0xF1, 0x01, 0x0E}, {0xE0, 0xFE, 0x01, 0x1F, 0xF1, 0xFE, 0x01, 0x0E}, {0xE0, 0xE0, 0x1F, 0x1F, 0xF1, 0xF1, 0x0E, 0x0E}, {0xFE, 0xFE, 0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E}, {0xFE, 0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1, 0x01}, {0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E, 0xFE, 0x01}, {0xFE, 0x01, 0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E}, {0xE0, 0x01, 0xFE, 0x1F, 0xF1, 0x01, 0xFE, 0x0E}, {0x01, 0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1, 0x01}, {0x1F, 0xFE, 0xE0, 0x01, 0x0E, 0xFE, 0xF0, 0x01}, {0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1, 0xFE, 0x01}, {0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01}, {0x1F, 0xE0, 0xE0, 0x1F, 0x0E, 0xF1, 0xF1, 0x0E}, {0x01, 0xFE, 0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E}, {0x01, 0xE0, 0xFE, 0x1F, 0x01, 0xF1, 0xFE, 0x0E}, {0x1F, 0xFE, 0xFE, 0x1F, 0x0E, 0xFE, 0xFE, 0x0E}, {0xE0, 0x01, 0x01, 0xE0, 0xF1, 0x01, 0x01, 0xF1}, {0xFE, 0x1F, 0x01, 0xE0, 0xFE, 0x0E, 0x01, 0xF1}, {0xFE, 0x01, 0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1}, {0xE0, 0x1F, 0x1F, 0xE0, 0xF1, 0x0E, 0x0E, 0xF1}, {0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE}, {0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E, 0x01, 0xFE}, {0xE0, 0x01, 0x1F, 0xFE, 0xF1, 0x01, 0x0E, 0xFE}, {0xFE, 0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E, 0xFE}, {0x1F, 0xFE, 0x01, 0xE0, 0x0E, 0xFE, 0x01, 0xF1}, {0x01, 0xFE, 0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1}, {0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1, 0x01, 0xFE}, {0x01, 0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E, 0xFE}, {0x01, 0x01, 0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1}, {0x1F, 0x1F, 0xE0, 0xE0, 0x0E, 0x0E, 0xF1, 0xF1}, {0x1F, 0x01, 0xFE, 0xE0, 0x0E, 0x01, 0xFE, 0xF1}, {0x01, 0x1F, 0xFE, 0xE0, 0x01, 0x0E, 0xFE, 0xF1}, {0x1F, 0x01, 0xE0, 0xFE, 0x0E, 0x01, 0xF1, 0xFE}, {0x01, 0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1, 0xFE}, {0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE}, {0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E, 0xFE, 0xFE}, {0xFE, 0xFE, 0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1}, {0xE0, 0xFE, 0xFE, 0xE0, 0xF1, 0xFE, 0xFE, 0xF1}, {0xFE, 0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1, 0xFE}, {0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1, 0xFE, 0xFE} }; // default SO pin hash values // // default SO pin = "87654321" // CK_BYTE default_so_pin_md5[MD5_HASH_SIZE] = { 0x5E, 0x86, 0x67, 0xA4, 0x39, 0xC6, 0x8F, 0x51, 0x45, 0xDD, 0x2F, 0xCB, 0xEC, 0xF0, 0x22, 0x09 }; CK_BYTE default_so_pin_sha[SHA1_HASH_SIZE] = { 0xA7, 0xD5, 0x79, 0xBA, 0x76, 0x39, 0x80, 0x70, 0xEA, 0xE6, 0x54, 0xC3, 0x0F, 0xF1, 0x53, 0xA4, 0xC2, 0x73, 0x27, 0x2A }; /* SHA-1 of "12345678" */ CK_BYTE default_user_pin_sha[SHA1_HASH_SIZE] = { 0x7c, 0x22, 0x2f, 0xb2, 0x92, 0x7d, 0x82, 0x8a, 0xf2, 0x2f, 0x59, 0x21, 0x34, 0xe8, 0x93, 0x24, 0x80, 0x63, 0x7c, 0x0d }; CK_BYTE user_pin_md5[MD5_HASH_SIZE]; CK_BYTE so_pin_md5[MD5_HASH_SIZE]; CK_BYTE master_key[MAX_KEY_SIZE]; opencryptoki+dfsg/usr/lib/pkcs11/common/mech_md5.c0000755000175000017500000013400612630407154021104 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "pkcs32.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // forward declaration // void ckm_md5_transform (); static CK_BYTE PADDING[64] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // // CK_RV md5_hash( SESSION * sess, CK_BBOOL length_only, DIGEST_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = MD5_HASH_SIZE; return CKR_OK; } rc = md5_hash_update( sess, ctx, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("md5_hash_update failed\n"); return rc; } return md5_hash_final( sess, FALSE, ctx, out_data, out_data_len ); } // // CK_RV md5_hash_update( SESSION * sess, DIGEST_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { if (!sess || !ctx || !in_data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } return ckm_md5_update( (MD5_CONTEXT *)ctx->context, in_data, in_data_len ); } // // CK_RV md5_hash_final( SESSION * sess, CK_BYTE length_only, DIGEST_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len ) { CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = MD5_HASH_SIZE; return CKR_OK; } rc = ckm_md5_final( (MD5_CONTEXT *)ctx->context, out_data, MD5_HASH_SIZE ); if (rc == CKR_OK) { *out_data_len = MD5_HASH_SIZE; return rc; } return rc; } // this routine gets called for two mechanisms actually: // CKM_MD5_HMAC // CKM_MD5_HMAC_GENERAL // CK_RV md5_hmac_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE hash[MD5_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[MD5_BLOCK_SIZE]; CK_BYTE k_opad[MD5_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_MD5_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return CKR_OK; } } else hmac_len = MD5_HASH_SIZE; if (length_only == TRUE) { *out_data_len = hmac_len; return CKR_OK; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK) return rc; rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else key_bytes = attr->ulValueLen; // build (K XOR ipad), (K XOR opad) // if (key_bytes > MD5_BLOCK_SIZE) { digest_mech.mechanism = CKM_MD5; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK) { return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest( sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len ); if (rc != CKR_OK) { return rc; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); for (i=0; i < hash_len; i++) { k_ipad[i] = hash[i] ^ 0x36; k_opad[i] = hash[i] ^ 0x5C; } memset( &k_ipad[i], 0x36, MD5_BLOCK_SIZE - i); memset( &k_opad[i], 0x5C, MD5_BLOCK_SIZE - i); } else { CK_BYTE *key = attr->pValue; for (i=0; i < key_bytes; i++) { k_ipad[i] = key[i] ^ 0x36; k_opad[i] = key[i] ^ 0x5C; } memset( &k_ipad[i], 0x36, MD5_BLOCK_SIZE - key_bytes ); memset( &k_opad[i], 0x5C, MD5_BLOCK_SIZE - key_bytes ); } digest_mech.mechanism = CKM_MD5; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, k_ipad, MD5_BLOCK_SIZE ); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, in_data, in_data_len ); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &hash_len ); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); // outer hash // rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, k_opad, MD5_BLOCK_SIZE ); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, hash, hash_len ); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &hash_len ); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memcpy( out_data, hash, hmac_len ); *out_data_len = hmac_len; return CKR_OK; } // // CK_RV md5_hmac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { CK_BYTE hmac[MD5_HASH_SIZE]; SIGN_VERIFY_CONTEXT hmac_ctx; CK_ULONG hmac_len, len; CK_RV rc; if (!sess || !ctx || !in_data || !signature){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_MD5_HMAC_GENERAL) hmac_len = *(CK_ULONG *)ctx->mech.pParameter; else hmac_len = MD5_HASH_SIZE; memset( &hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT) ); rc = sign_mgr_init( sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key ); if (rc != CKR_OK) { sign_mgr_cleanup( &hmac_ctx ); return rc; } len = sizeof(hmac); rc = sign_mgr_sign( sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len ); if (rc != CKR_OK) { sign_mgr_cleanup( &hmac_ctx ); return rc; } if ((len != hmac_len) || (len != sig_len)){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } if (memcmp(hmac, signature, hmac_len) != 0){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rc = CKR_SIGNATURE_INVALID; } sign_mgr_cleanup( &hmac_ctx ); return rc; } // // CKM routines // void ckm_md5_init( MD5_CONTEXT *context ) { context->i[0] = context->i[1] = 0; // Load magic initialization constants. // context->buf[0] = (CK_ULONG)0x67452301; context->buf[1] = (CK_ULONG)0xefcdab89; context->buf[2] = (CK_ULONG)0x98badcfe; context->buf[3] = (CK_ULONG)0x10325476; } // // CK_RV ckm_md5_update( MD5_CONTEXT * context, CK_BYTE * in_data, CK_ULONG in_data_len ) { CK_ULONG in[16]; int mdi; CK_ULONG i, ii; // compute number of bytes mod 64 // mdi = (int)((context->i[0] >> 3) & 0x3F); // update number of bits // if ((context->i[0] + (in_data_len << 3)) < context->i[0]) context->i[1]++; context->i[0] += (in_data_len << 3); context->i[1] += (in_data_len >> 29); while (in_data_len--) { // add new character to buffer, increment mdi // context->in[mdi++] = *in_data++; // transform if necessary // if (mdi == 0x40) { for (i = 0, ii = 0; i < 16; i++, ii += 4) in[i] = (((CK_ULONG)context->in[ii+3]) << 24) | (((CK_ULONG)context->in[ii+2]) << 16) | (((CK_ULONG)context->in[ii+1]) << 8) | ((CK_ULONG)context->in[ii]); ckm_md5_transform (context->buf, in); mdi = 0; } } return CKR_OK; } // // CK_RV ckm_md5_final( MD5_CONTEXT *context, CK_BYTE *out_data, CK_ULONG out_data_len ) { CK_ULONG in[16]; int mdi; CK_ULONG i, ii; CK_ULONG padLen; if (!out_data) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (out_data_len < MD5_HASH_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } // save number of bits // in[14] = context->i[0]; in[15] = context->i[1]; // compute number of bytes mod 64 // mdi = (int)((context->i[0] >> 3) & 0x3F); // pad out to 56 mod 64 // padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); ckm_md5_update( context, PADDING, padLen ); // append length in bits and transform // for (i = 0, ii = 0; i < 14; i++, ii += 4) in[i] = (((CK_ULONG)context->in[ii+3]) << 24) | (((CK_ULONG)context->in[ii+2]) << 16) | (((CK_ULONG)context->in[ii+1]) << 8) | ((CK_ULONG)context->in[ii]); ckm_md5_transform (context->buf, in); // store buffer in digest // for (i = 0, ii = 0; i < 4; i++, ii += 4) { context->digest[ii ] = (CK_BYTE) (context->buf[i] & 0xFF); context->digest[ii+1] = (CK_BYTE)((context->buf[i] >> 8) & 0xFF); context->digest[ii+2] = (CK_BYTE)((context->buf[i] >> 16) & 0xFF); context->digest[ii+3] = (CK_BYTE)((context->buf[i] >> 24) & 0xFF); } memcpy( out_data, context->digest, MD5_HASH_SIZE ); return CKR_OK; } // Stuff stolen from CCA (saf_md5.c) /******************************************************************************/ /* Rotate a word (32 bits) left by a specified number of bits. The 32-bit */ /* number invalue is circularly rotated left by num_bits bit positions. The */ /* result is returned as the function result. */ /*----------------------------------------------------------------------------*/ #define rotate_left(Data, bit_cnt) \ (Data = ( (Data << bit_cnt) | \ (Data >> (32 - bit_cnt)) ) ) /******************************************************************************/ /* Implement the MD5 algorithm's "F" function. This function performs a */ /* transform on three input words, designated x, y, and z, producing a */ /* single word output value. The transform is: */ /* */ /* output = ( x AND y ) OR ( (NOT x) AND z ) */ /*----------------------------------------------------------------------------*/ #define F( x, y, z) ( ( x & y ) | ( (~x) & z) ) /******************************************************************************/ /* Implement the MD5 algorithm's "G" function. This function performs a */ /* transform on three input words, designated x, y, and z, producing a */ /* single word output value. The transform is: */ /* */ /* output = ( x AND z ) OR ( y AND (NOT z) ) */ /*----------------------------------------------------------------------------*/ #define G( x, y, z) ( ( x & z ) | ( y & (~z) ) ) /******************************************************************************/ /* Implement the MD5 algorithm's "H" function. This function performs a */ /* transform on three input words, designated x, y, and z, producing a */ /* single word output value. The transform is: */ /* */ /* output = ( x XOR y XOR z ) */ /*----------------------------------------------------------------------------*/ #define H( x, y, z) ( x ^ y ^ z ) /******************************************************************************/ /* Implement the MD5 algorithm's "I" function. This function performs a */ /* transform on three input words, designated x, y, and z, producing a */ /* single word output value. The transform is: */ /* */ /* output = ( y XOR ( x OR (NOT z) ) ) */ /*----------------------------------------------------------------------------*/ #define I( x, y, z) ( y ^ ( x | (~z) ) ) /*----------------------------------------------------------------------------*/ /* */ /* Define the MD5 "T[]" table. This table consists of 64 4-byte (MD5_word) */ /* entries, designated T[1] through T[64]. (Note that this is different from */ /* the way C will index them, from 0..63 instead of 1..64.) */ /* */ /* If the index of each entry is i, where i ranges from 1 to 64, then the */ /* value in each entry is given by the following formula. */ /* */ /* T[i] = int ( 4294967296 * abs ( sin ( i ) ) ) */ /* */ /* where the function sin(i) expects i in radians, and the function int(x) */ /* returns the integer portion of a floating point number x. */ /* */ /*----------------------------------------------------------------------------*/ static CK_ULONG T[64] = { 0xD76AA478, /* T[01] */ 0xE8C7B756, /* T[02] */ 0x242070DB, /* T[03] */ 0xC1BDCEEE, /* T[04] */ 0xF57C0FAF, /* T[05] */ 0x4787C62A, /* T[06] */ 0xA8304613, /* T[07] */ 0xFD469501, /* T[08] */ 0x698098D8, /* T[09] */ 0x8B44F7AF, /* T[10] */ 0xFFFF5BB1, /* T[11] */ 0x895CD7BE, /* T[12] */ 0x6B901122, /* T[13] */ 0xFD987193, /* T[14] */ 0xA679438E, /* T[15] */ 0x49B40821, /* T[16] */ 0xF61E2562, /* T[17] */ 0xC040B340, /* T[18] */ 0x265E5A51, /* T[19] */ 0xE9B6C7AA, /* T[20] */ 0xD62F105D, /* T[21] */ 0x02441453, /* T[22] */ 0xD8A1E681, /* T[23] */ 0xE7D3FBC8, /* T[24] */ 0x21E1CDE6, /* T[25] */ 0xC33707D6, /* T[26] */ 0xF4D50D87, /* T[27] */ 0x455A14ED, /* T[28] */ 0xA9E3E905, /* T[29] */ 0xFCEFA3F8, /* T[30] */ 0x676F02D9, /* T[31] */ 0x8D2A4C8A, /* T[32] */ 0xFFFA3942, /* T[33] */ 0x8771F681, /* T[34] */ 0x6D9D6122, /* T[35] */ 0xFDE5380C, /* T[36] */ 0xA4BEEA44, /* T[37] */ 0x4BDECFA9, /* T[38] */ 0xF6BB4B60, /* T[39] */ 0xBEBFBC70, /* T[40] */ 0x289B7EC6, /* T[41] */ 0xEAA127FA, /* T[42] */ 0xD4EF3085, /* T[43] */ 0x04881D05, /* T[44] */ 0xD9D4D039, /* T[45] */ 0xE6DB99E5, /* T[46] */ 0x1FA27CF8, /* T[47] */ 0xC4AC5665, /* T[48] */ 0xF4292244, /* T[49] */ 0x432AFF97, /* T[50] */ 0xAB9423A7, /* T[51] */ 0xFC93A039, /* T[52] */ 0x655B59C3, /* T[53] */ 0x8F0CCC92, /* T[54] */ 0xFFEFF47D, /* T[55] */ 0x85845DD1, /* T[56] */ 0x6FA87E4F, /* T[57] */ 0xFE2CE6E0, /* T[58] */ 0xA3014314, /* T[59] */ 0x4E0811A1, /* T[60] */ 0xF7537E82, /* T[61] */ 0xBD3AF235, /* T[62] */ 0x2AD7D2BB, /* T[63] */ 0xEB86D391 }; /* T[64] */ // Basic MD5 step. Transform buf based on in. // void ckm_md5_transform( CK_ULONG *long_buf, CK_ULONG *long_in ) { /*-------------------------------------------------------------------------*/ /* The inputs to this function SHOULD be 4 4-byte elements of buf[] and */ /* 16 4-byte elements of in[]. There are architectures, however -- */ /* 64-bit Linux390 among them--in which CK_ULONG translates to an 8-byte */ /* number. Therefore this function must copy inputs to 4-byte temps and */ /* copy the temps back into the 8-byte arrays at the end. */ /*-------------------------------------------------------------------------*/ /* */ /* Macro ROUND_FCN defines the common function that is performed */ /* throughout the MD5 round. Parameters are: */ /* */ /* - The name of the function to be performed on the data for this */ /* round. There are four logical functions, F, G, H, and I, and they */ /* are each used throughout the algorithm. */ /* */ /* - a, b, c, and d are the four md5-word parameters to the functions */ /* F, G, H, and I. They are replaced with varying permutations of the */ /* accumulated hash values in A, B, C, and D. */ /* */ /* - x_index is an index into the in[] array, where in[] is the input */ /* block of message text. */ /* */ /* - t_index is an index into the T[] array, a set of constants. */ /* */ /* - rotate_cnt is the number of bits the result must be rotated. */ /* */ /*-------------------------------------------------------------------------*/ CK_ULONG AA = 0x00000000; /* Temp. save areas for A, B, C, D */ CK_ULONG BB = 0x00000000; /* Temp. save areas for A, B, C, D */ CK_ULONG CC = 0x00000000; /* Temp. save areas for A, B, C, D */ CK_ULONG DD = 0x00000000; /* Temp. save areas for A, B, C, D */ CK_ULONG_32 buf[4]; // temps for long_buf[i] CK_ULONG_32 in[16]; // temps for long_in[i] int i; // loop counter #define ROUND_FCN(FCN, a, b, c, d, x_index, rotate_cnt, t_index) \ { a += FCN(b,c,d) + in[x_index] + T[t_index-1]; \ rotate_left( a, rotate_cnt); \ a += b; \ } /* Save the MD buffer in the temporary locations AA-DD. */ AA = long_buf[0]; BB = long_buf[1]; CC = long_buf[2]; DD = long_buf[3]; // Copy the input long_buf elements into buf and long_in elements into in for (i=0;i<4;i++) { buf[i] = (CK_ULONG_32)long_buf[i]; in[i] = (CK_ULONG_32)long_in[i]; } for (i=4;i<16;i++) in[i] = (CK_ULONG_32)long_in[i]; /*==================================================================*/ /* */ /* Process the four rounds for each 16-word block. */ /* */ /* The function for each of these has the form: */ /* */ /* a = b + (( a + fcn( b, c, d ) + in[k] + T[i] ) <<< s ) */ /* */ /* for a function fcn() which can be F, G, H, or I, and for input */ /* values a, b, c, d, k, i, and s. Array T is the array of */ /* constants, computed from the sin() function. Array in is the */ /* current input block. Value s is the number of bits to rotate */ /* left, where <<< represents a 32-bit left rotation. */ /* */ /* The definitions of these functions are taken directly from the */ /* definition of MD5 in RFC 1321. */ /* */ /*==================================================================*/ /*------------------------------------------------------------------*/ /* */ /* Round 1 */ /* */ /*------------------------------------------------------------------*/ ROUND_FCN(F, buf[0], buf[1], buf[2], buf[3], 0, 7, 1); ROUND_FCN(F, buf[3], buf[0], buf[1], buf[2], 1, 12, 2); ROUND_FCN(F, buf[2], buf[3], buf[0], buf[1], 2, 17, 3); ROUND_FCN(F, buf[1], buf[2], buf[3], buf[0], 3, 22, 4); ROUND_FCN(F, buf[0], buf[1], buf[2], buf[3], 4, 7, 5); ROUND_FCN(F, buf[3], buf[0], buf[1], buf[2], 5, 12, 6); ROUND_FCN(F, buf[2], buf[3], buf[0], buf[1], 6, 17, 7); ROUND_FCN(F, buf[1], buf[2], buf[3], buf[0], 7, 22, 8); ROUND_FCN(F, buf[0], buf[1], buf[2], buf[3], 8, 7, 9); ROUND_FCN(F, buf[3], buf[0], buf[1], buf[2], 9, 12, 10); ROUND_FCN(F, buf[2], buf[3], buf[0], buf[1], 10, 17, 11); ROUND_FCN(F, buf[1], buf[2], buf[3], buf[0], 11, 22, 12); ROUND_FCN(F, buf[0], buf[1], buf[2], buf[3], 12, 7, 13); ROUND_FCN(F, buf[3], buf[0], buf[1], buf[2], 13, 12, 14); ROUND_FCN(F, buf[2], buf[3], buf[0], buf[1], 14, 17, 15); ROUND_FCN(F, buf[1], buf[2], buf[3], buf[0], 15, 22, 16); /*------------------------------------------------------------------*/ /* */ /* Round 2 */ /* */ /*------------------------------------------------------------------*/ ROUND_FCN(G, buf[0], buf[1], buf[2], buf[3], 1, 5, 17); ROUND_FCN(G, buf[3], buf[0], buf[1], buf[2], 6, 9, 18); ROUND_FCN(G, buf[2], buf[3], buf[0], buf[1], 11, 14, 19); ROUND_FCN(G, buf[1], buf[2], buf[3], buf[0], 0, 20, 20); ROUND_FCN(G, buf[0], buf[1], buf[2], buf[3], 5, 5, 21); ROUND_FCN(G, buf[3], buf[0], buf[1], buf[2], 10, 9, 22); ROUND_FCN(G, buf[2], buf[3], buf[0], buf[1], 15, 14, 23); ROUND_FCN(G, buf[1], buf[2], buf[3], buf[0], 4, 20, 24); ROUND_FCN(G, buf[0], buf[1], buf[2], buf[3], 9, 5, 25); ROUND_FCN(G, buf[3], buf[0], buf[1], buf[2], 14, 9, 26); ROUND_FCN(G, buf[2], buf[3], buf[0], buf[1], 3, 14, 27); ROUND_FCN(G, buf[1], buf[2], buf[3], buf[0], 8, 20, 28); ROUND_FCN(G, buf[0], buf[1], buf[2], buf[3], 13, 5, 29); ROUND_FCN(G, buf[3], buf[0], buf[1], buf[2], 2, 9, 30); ROUND_FCN(G, buf[2], buf[3], buf[0], buf[1], 7, 14, 31); ROUND_FCN(G, buf[1], buf[2], buf[3], buf[0], 12, 20, 32); /*------------------------------------------------------------------*/ /* */ /* Round 3 */ /* */ /*------------------------------------------------------------------*/ ROUND_FCN(H, buf[0], buf[1], buf[2], buf[3], 5, 4, 33); ROUND_FCN(H, buf[3], buf[0], buf[1], buf[2], 8, 11, 34); ROUND_FCN(H, buf[2], buf[3], buf[0], buf[1], 11, 16, 35); ROUND_FCN(H, buf[1], buf[2], buf[3], buf[0], 14, 23, 36); ROUND_FCN(H, buf[0], buf[1], buf[2], buf[3], 1, 4, 37); ROUND_FCN(H, buf[3], buf[0], buf[1], buf[2], 4, 11, 38); ROUND_FCN(H, buf[2], buf[3], buf[0], buf[1], 7, 16, 39); ROUND_FCN(H, buf[1], buf[2], buf[3], buf[0], 10, 23, 40); ROUND_FCN(H, buf[0], buf[1], buf[2], buf[3], 13, 4, 41); ROUND_FCN(H, buf[3], buf[0], buf[1], buf[2], 0, 11, 42); ROUND_FCN(H, buf[2], buf[3], buf[0], buf[1], 3, 16, 43); ROUND_FCN(H, buf[1], buf[2], buf[3], buf[0], 6, 23, 44); ROUND_FCN(H, buf[0], buf[1], buf[2], buf[3], 9, 4, 45); ROUND_FCN(H, buf[3], buf[0], buf[1], buf[2], 12, 11, 46); ROUND_FCN(H, buf[2], buf[3], buf[0], buf[1], 15, 16, 47); ROUND_FCN(H, buf[1], buf[2], buf[3], buf[0], 2, 23, 48); /*------------------------------------------------------------------*/ /* */ /* Round 4 */ /* */ /*------------------------------------------------------------------*/ ROUND_FCN(I, buf[0], buf[1], buf[2], buf[3], 0, 6, 49); ROUND_FCN(I, buf[3], buf[0], buf[1], buf[2], 7, 10, 50); ROUND_FCN(I, buf[2], buf[3], buf[0], buf[1], 14, 15, 51); ROUND_FCN(I, buf[1], buf[2], buf[3], buf[0], 5, 21, 52); ROUND_FCN(I, buf[0], buf[1], buf[2], buf[3], 12, 6, 53); ROUND_FCN(I, buf[3], buf[0], buf[1], buf[2], 3, 10, 54); ROUND_FCN(I, buf[2], buf[3], buf[0], buf[1], 10, 15, 55); ROUND_FCN(I, buf[1], buf[2], buf[3], buf[0], 1, 21, 56); ROUND_FCN(I, buf[0], buf[1], buf[2], buf[3], 8, 6, 57); ROUND_FCN(I, buf[3], buf[0], buf[1], buf[2], 15, 10, 58); ROUND_FCN(I, buf[2], buf[3], buf[0], buf[1], 6, 15, 59); ROUND_FCN(I, buf[1], buf[2], buf[3], buf[0], 13, 21, 60); ROUND_FCN(I, buf[0], buf[1], buf[2], buf[3], 4, 6, 61); ROUND_FCN(I, buf[3], buf[0], buf[1], buf[2], 11, 10, 62); ROUND_FCN(I, buf[2], buf[3], buf[0], buf[1], 2, 15, 63); ROUND_FCN(I, buf[1], buf[2], buf[3], buf[0], 9, 21, 64); // Copy the elements of buf into long_buf for (i=0;i<4;i++) long_buf[i] = (CK_ULONG) buf[i]; /* Add to each MD buffer variable the value it had before this block was */ /* started. */ long_buf[0] += AA; long_buf[1] += BB; long_buf[2] += CC; long_buf[3] += DD; /* Undefine the ROUND_FCN macro we used in this function. */ #undef ROUND_FCN } opencryptoki+dfsg/usr/lib/pkcs11/common/hwf_obj.c0000644000175000017500000005175712630407154021051 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: hwf_obj.c // // Hardware Feature Object functions #include #include #include // for memcmp() et al #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" #include "tok_spec_struct.h" // hwf_object_check_required_attributes() // // Check required common attributes for hardware feature objects // CK_RV hwf_object_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_HW_FEATURE_TYPE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return template_check_required_base_attributes( tmpl, mode ); } CK_RV clock_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; if (mode == MODE_CREATE){ found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return hwf_object_check_required_attributes( tmpl, mode ); } CK_RV counter_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; if (mode == MODE_CREATE){ found = template_attribute_find( tmpl, CKA_VALUE, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_HAS_RESET, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_RESET_ON_INIT, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return hwf_object_check_required_attributes( tmpl, mode ); } // hwf_object_set_default_attributes() // CK_RV hwf_object_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { #if 0 CK_ATTRIBUTE * local_attr = NULL; local_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!local_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = FALSE; template_update_attribute( tmpl, local_attr ); #endif return CKR_OK; } // hwf_object_validate_attribute() // CK_RV hwf_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_HW_FEATURE_TYPE: if (mode == MODE_CREATE) return CKR_OK; else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } default: return template_validate_base_attribute( tmpl, attr, mode ); } TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; } // // CK_RV clock_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_VALUE: return CKR_OK; default: return hwf_validate_attribute( tmpl, attr, mode ); } } // // CK_RV counter_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_VALUE: /* Fall Through */ case CKA_HAS_RESET: /* Fall Through */ case CKA_RESET_ON_INIT: TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; default: return hwf_validate_attribute( tmpl, attr, mode ); } } CK_RV clock_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_RV rc; CK_ATTRIBUTE *value_attr; rc = hwf_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK) return rc; value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!value_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; template_update_attribute( tmpl, value_attr ); return CKR_OK; } CK_RV counter_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_RV rc; CK_ATTRIBUTE *value_attr; CK_ATTRIBUTE *hasreset_attr; CK_ATTRIBUTE *resetoninit_attr; rc = hwf_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK) return rc; value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); hasreset_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); resetoninit_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL)); if (!value_attr || !hasreset_attr || !resetoninit_attr) { if (value_attr) free( value_attr ); if (hasreset_attr) free( hasreset_attr ); if (resetoninit_attr) free( resetoninit_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; value_attr->pValue = NULL; hasreset_attr->type = CKA_HAS_RESET; hasreset_attr->ulValueLen = sizeof(CK_BBOOL); hasreset_attr->pValue = (CK_BYTE *)hasreset_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)hasreset_attr->pValue = FALSE; /* Hmm... Not sure if we should be setting this here. */ resetoninit_attr->type = CKA_RESET_ON_INIT; resetoninit_attr->ulValueLen = sizeof(CK_BBOOL); resetoninit_attr->pValue = (CK_BYTE *)resetoninit_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)resetoninit_attr->pValue = FALSE; template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, hasreset_attr ); template_update_attribute( tmpl, resetoninit_attr ); return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/mech_des3.c0000755000175000017500000025020612630407154021256 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: mech_des3.c // // Mechanisms for DES3 // #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV des3_ecb_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES3_ECB requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_des3_ecb_encrypt(in_data, in_data_len, out_data, out_data_len, key); } // // CK_RV des3_ecb_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES3_ECB requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_des3_ecb_decrypt(in_data, in_data_len, out_data, out_data_len, key); } // // CK_RV des3_cbc_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES3_CBC requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_des3_cbc_encrypt(in_data, in_data_len, out_data, out_data_len, ctx->mech.pParameter, key); } // // CK_RV des3_cbc_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES3_CBC requires the input data to be an integral // multiple of the block size // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_des3_cbc_decrypt(in_data, in_data_len, out_data, out_data_len, ctx->mech.pParameter, key); } // // CK_RV des3_cbc_pad_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_BYTE *clear = NULL; CK_ULONG padded_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // DES3-CBC-PAD has no input length requirements // rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // compute the output length, accounting for padding // padded_len = DES_BLOCK_SIZE * (in_data_len / DES_BLOCK_SIZE + 1); if (length_only == TRUE) { *out_data_len = padded_len; return CKR_OK; } if (*out_data_len < padded_len) { *out_data_len = padded_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } clear = (CK_BYTE *)malloc( padded_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( clear, in_data, in_data_len ); add_pkcs_padding( clear + in_data_len, DES_BLOCK_SIZE, in_data_len, padded_len ); rc = ckm_des3_cbc_encrypt(clear, padded_len, out_data, out_data_len, ctx->mech.pParameter, key); free( clear ); return rc; } // // CK_RV des3_cbc_pad_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_BYTE *clear = NULL; CK_ULONG padded_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // // no need to validate the input length since we'll pad as necessary // rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // we're decrypting so even with CBC-PAD, we should have an integral // number of block to decrypt // if (in_data_len % DES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } // the amount of cleartext after stripping the padding will actually be less // than the input bytes... // padded_len = in_data_len; if (length_only == TRUE) { *out_data_len = padded_len; return CKR_OK; } clear = (CK_BYTE *)malloc( padded_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = ckm_des3_cbc_decrypt(in_data, in_data_len, clear, &padded_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { strip_pkcs_padding( clear, padded_len, out_data_len ); memcpy( out_data, clear, *out_data_len ); } free( clear ); return rc; } // // CK_RV des3_ecb_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % DES_BLOCK_SIZE); out_len = (total - remain); // should always be at least 1 block if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); rc = ckm_des3_ecb_encrypt(clear, out_len, out_data, out_data_len, key ); if (rc == CKR_OK) { *out_data_len = out_len; // update the context buffer. we already used the buffer's current // contents so we completely overwrite it // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV des3_ecb_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % DES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_des3_ecb_decrypt(cipher, out_len, out_data, out_data_len, key); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV des3_cbc_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % DES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); rc = ckm_des3_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { *out_data_len = out_len; // the new init_v is the last encrypted data block // memcpy( ctx->mech.pParameter, out_data + (*out_data_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE ); // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV des3_cbc_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = context->len + in_data_len; if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = total % DES_BLOCK_SIZE; out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_des3_cbc_decrypt(cipher, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { *out_data_len = out_len; // the new init_v is the last input data block // memcpy( ctx->mech.pParameter, cipher + (out_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE ); // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV des3_cbc_pad_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); // note, this is subtly different from the other encrypt update routines // if (total <= DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { remain = (total % DES_BLOCK_SIZE); out_len = total - remain; // out_len is a multiple of DES_BLOCK_SIZE if (remain == 0) { remain = DES_BLOCK_SIZE; out_len -= DES_BLOCK_SIZE; } if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } // at this point, we should have: // 1) remain != 0 // 2) out_len != 0 // rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); // // we don't do padding during the update // rc = ckm_des3_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { // the new init_v is the last encrypted data block // memcpy( ctx->mech.pParameter, out_data + (*out_data_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE ); // copy the remaining 'new' input data to the temporary space // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV des3_cbc_pad_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); // note, this is subtly different from the other decrypt update routines // if (total <= DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block + 1 byte // remain = total % DES_BLOCK_SIZE; out_len = total - remain; if (remain == 0) { remain = DES_BLOCK_SIZE; out_len -= DES_BLOCK_SIZE; } if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } // at this point, we should have: // 1) remain != 0 // 2) out_len != 0 // rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_des3_cbc_decrypt(cipher, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { // the new init_v is the last input data block // memcpy( ctx->mech.pParameter, cipher + (out_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE ); // copy the remaining 'new' input data to the temporary space // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV des3_ecb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (DES_CONTEXT *)ctx->context; // DES3-ECB does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV des3_ecb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (DES_CONTEXT *)ctx->context; // DES3-ECB does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV des3_cbc_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (DES_CONTEXT *)ctx->context; // DES3-CBC does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV des3_cbc_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (DES_CONTEXT *)ctx->context; // DES3-CBC does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV des3_cbc_pad_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; OBJECT *key = NULL; CK_BYTE clear[2*DES_BLOCK_SIZE]; CK_ULONG out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } context = (DES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate one block of output // if a full block is stored, we generate two blocks of output (one pad block) // if (context->len == DES_BLOCK_SIZE) out_len = 2 * DES_BLOCK_SIZE; else out_len = DES_BLOCK_SIZE; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } else { memcpy( clear, context->data, context->len ); add_pkcs_padding( clear + context->len, DES_BLOCK_SIZE, context->len, out_len ); rc = ckm_des3_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); return rc; } } // // CK_RV des3_cbc_pad_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { DES_CONTEXT *context = NULL; OBJECT *key = NULL; CK_BYTE clear[DES_BLOCK_SIZE]; CK_ULONG out_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } context = (DES_CONTEXT *)ctx->context; // there had better be a full block in the context buffer // if (context->len != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } // we don't know a priori how much data we'll be returning. we won't // know until after we decrypt it and strip the padding. it's possible // that we'll return nothing (the final block might be a padding block). // out_len = DES_BLOCK_SIZE; // upper bound on what we'll return if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } else { rc = ckm_des3_cbc_decrypt(context->data, DES_BLOCK_SIZE, clear, &out_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { strip_pkcs_padding( clear, out_len, &out_len ); if (out_len != 0) memcpy( out_data, clear, out_len ); *out_data_len = out_len; } return rc; } } CK_RV des3_ofb_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { CK_ULONG rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_ofb(in_data, out_data, in_data_len, key_obj, ctx->mech.pParameter, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 ofb encrypt failed.\n"); return rc; } CK_RV des3_ofb_encrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { DES_DATA_CONTEXT *context = NULL; CK_BYTE *cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_DATA_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block remain = (total % DES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } if (*out_data_len < out_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_tdes_ofb(cipher, out_data, out_len, key_obj, ctx->mech.pParameter, 1); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific des3 ofb encrypt failed.\n"); free( cipher ); return rc; } } CK_RV des3_ofb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; DES_CONTEXT *context = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate same length of output data // if no data stored, no data can be returned (length zero) if (length_only == TRUE) { *out_data_len = context->len; return CKR_OK; } else { if (context->len == 0) { *out_data_len = 0; return CKR_OK; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_ofb(context->data, out_data, context->len, key_obj, ctx->mech.pParameter, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 ofb encrypt failed.\n"); *out_data_len = context->len; return rc; } } CK_RV des3_ofb_decrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { CK_ULONG rc; OBJECT *key_obj = NULL; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_ofb(in_data, out_data, in_data_len, key_obj, ctx->mech.pParameter, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 ofb decrypt failed.\n"); return rc; } CK_RV des3_ofb_decrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { DES_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block remain = (total % DES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } if (*out_data_len < out_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_tdes_ofb(cipher, out_data, out_len, key_obj, ctx->mech.pParameter, 0); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific des3 ofb decrypt failed.\n"); free( cipher ); return rc; } } CK_RV des3_ofb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; DES_CONTEXT *context = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate same length of output data // if no data stored, no data can be returned (length zero) if (length_only == TRUE) { *out_data_len = context->len; return CKR_OK; } else { if (context->len == 0) { *out_data_len = 0; return CKR_OK; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_ofb(context->data, out_data, context->len, key_obj, ctx->mech.pParameter, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 ofb decrypt failed.\n"); *out_data_len = context->len; return rc; } } CK_RV des3_cfb_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len) { CK_ULONG rc; OBJECT *key_obj = NULL; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_cfb(in_data, out_data, in_data_len, key_obj, ctx->mech.pParameter, cfb_len, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 cfb encrypt failed.\n"); return rc; } CK_RV des3_cfb_encrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len) { DES_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < cfb_len) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block remain = (total % cfb_len); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } if (*out_data_len < out_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_tdes_cfb(cipher, out_data, out_len, key_obj, ctx->mech.pParameter, cfb_len, 1); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific des3 cfb encrypt failed.\n"); free( cipher ); return rc; } } CK_RV des3_cfb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG cfb_len) { OBJECT *key_obj = NULL; DES_CONTEXT *context = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate same length of output data // if no data stored, no data can be returned (length zero) if (context->len == 0) { *out_data_len = 0; return CKR_OK; } if (length_only == TRUE) { *out_data_len = context->len; return CKR_OK; } else { rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_cfb(context->data, out_data, context->len, key_obj, ctx->mech.pParameter, cfb_len, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 cfb encrypt failed.\n"); *out_data_len = context->len; return rc; } } CK_RV des3_cfb_decrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len) { CK_ULONG rc; OBJECT *key_obj = NULL; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_cfb(in_data, out_data, in_data_len, key_obj, ctx->mech.pParameter, cfb_len, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 cfd decrypt failed.\n"); return rc; } CK_RV des3_cfb_decrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len) { DES_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < cfb_len) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block remain = (total % cfb_len); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } if (*out_data_len < out_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_tdes_cfb(cipher, out_data, out_len, key_obj, ctx->mech.pParameter, cfb_len, 0); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific des3 cfb decrypt failed.\n"); free( cipher ); return rc; } } CK_RV des3_cfb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG cfb_len) { OBJECT *key_obj = NULL; DES_CONTEXT *context = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate same length of output data // if no data stored, no data can be returned (length zero) if (context->len == 0) { *out_data_len = 0; return CKR_OK; } if (length_only == TRUE) { *out_data_len = context->len; return CKR_OK; } else { rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_cfb(context->data, out_data, context->len, key_obj, ctx->mech.pParameter, cfb_len, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 cfb decrypt failed.\n"); *out_data_len = context->len; return rc; } } CK_RV des3_mac_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { CK_ULONG rc; OBJECT * key_obj = NULL; CK_ULONG mac_len; if (!sess || !ctx || !in_data || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.pParameter) mac_len = *(CK_MAC_GENERAL_PARAMS *)ctx->mech.pParameter; else mac_len = DES_BLOCK_SIZE / 2; if (length_only == TRUE) { *out_data_len = mac_len; return CKR_OK; } if ( (in_data_len % DES_BLOCK_SIZE) != 0) { rc = des3_mac_sign_update(sess, ctx, in_data, in_data_len); if (rc != CKR_OK) return rc; rc = des3_mac_sign_final(sess, length_only, ctx, out_data, out_data_len); return rc; } else { if (*out_data_len < mac_len) { *out_data_len = mac_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_mac(in_data, in_data_len, key_obj, ((DES_DATA_CONTEXT *)ctx->context)->iv); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 mac failed.\n"); memcpy(out_data, ((DES_DATA_CONTEXT *)ctx->context)->iv, mac_len); *out_data_len = mac_len; return rc; } } CK_RV des3_mac_sign_update ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { CK_ULONG rc; OBJECT * key_obj = NULL; DES_DATA_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_DATA_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; return CKR_OK; } else { // we have at least 1 block remain = (total % DES_BLOCK_SIZE); out_len = total - remain; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous signUpdate operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_tdes_mac(cipher, out_len, key_obj, context->iv); if (rc == CKR_OK) { // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific des3 mac failed.\n"); free( cipher ); return rc; } } CK_RV des3_mac_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len) { CK_ULONG rc = CKR_OK; OBJECT * key_obj = NULL; CK_ULONG mac_len; DES_DATA_CONTEXT * context = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_DATA_CONTEXT *)ctx->context; if (ctx->mech.pParameter) mac_len = *(CK_MAC_GENERAL_PARAMS *)ctx->mech.pParameter; else mac_len = DES_BLOCK_SIZE / 2; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate one block of output (with padding) // if no data stored, we are done (take the cipher from previous round) if (length_only == TRUE) { *out_data_len = mac_len; return CKR_OK; } if (context->len > 0) { if (*out_data_len < mac_len) { *out_data_len = mac_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* padding with '00' in case case we didn't reach block size */ memset(context->data + context->len, 0x0, DES_BLOCK_SIZE - context->len); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_mac(context->data, DES_BLOCK_SIZE, key_obj, context->iv); if (rc != CKR_OK) { TRACE_DEVEL("Token specific des3 mac failed.\n"); return rc; } } memcpy(out_data, context->iv, mac_len); *out_data_len = mac_len; return rc; } CK_RV des3_mac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len) { CK_ULONG rc; OBJECT * key_obj = NULL; CK_ULONG mac_len; if (!sess || !ctx || !in_data || !out_data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if ( (in_data_len % DES_BLOCK_SIZE) != 0) { rc = des3_mac_verify_update(sess, ctx, in_data, in_data_len); if (rc != CKR_OK) return rc; rc = des3_mac_verify_final(sess, ctx, out_data, out_data_len); return rc; } else { if (ctx->mech.pParameter) mac_len = *(CK_MAC_GENERAL_PARAMS *)ctx->mech.pParameter; else mac_len = DES_BLOCK_SIZE / 2; if (out_data_len != mac_len) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_mac(in_data, in_data_len, key_obj, ((DES_DATA_CONTEXT *)ctx->context)->iv); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 mac failed.\n"); if (memcmp( out_data, ((DES_DATA_CONTEXT *)ctx->context)->iv, out_data_len) == 0) { return CKR_OK; } else return CKR_SIGNATURE_INVALID; } } CK_RV des3_mac_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len) { CK_ULONG rc; OBJECT * key_obj = NULL; DES_DATA_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_DATA_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < DES_BLOCK_SIZE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; return CKR_OK; } else { // we have at least 1 block remain = (total % DES_BLOCK_SIZE); out_len = total - remain; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous signUpdate operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_tdes_mac(cipher, out_len, key_obj, context->iv); if (rc == CKR_OK) { // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific des3 mac failed.\n"); free( cipher ); return rc; } } CK_RV des3_mac_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG signature_len) { CK_ULONG rc; OBJECT * key_obj = NULL; CK_ULONG mac_len; DES_DATA_CONTEXT * context = NULL; if (!sess || !ctx || !signature){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (DES_DATA_CONTEXT *)ctx->context; if (ctx->mech.pParameter) mac_len = *(CK_MAC_GENERAL_PARAMS *)ctx->mech.pParameter; else mac_len = DES_BLOCK_SIZE / 2; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate one block of output (with padding) // if no data stored, we are done (take the cipher from previous round) if (context->len > 0) { if (signature_len != mac_len) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } /* padding with '00' in case case we didn't reach block size */ memset(context->data + context->len, 0x0, DES_BLOCK_SIZE - context->len); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_tdes_mac(context->data, DES_BLOCK_SIZE, key_obj, context->iv); if (rc != CKR_OK) { TRACE_DEVEL("Token specific des3 mac failed.\n"); return rc; } } if (memcmp(signature, context->iv, signature_len) == 0) { return CKR_OK; } else return CKR_SIGNATURE_INVALID; } // // mechanisms // // // CK_RV ckm_des3_key_gen( TEMPLATE *tmpl ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * opaque_attr = NULL; CK_ATTRIBUTE * key_type_attr = NULL; CK_ATTRIBUTE * class_attr = NULL; CK_ATTRIBUTE * local_attr = NULL; CK_BYTE * des_key = NULL; CK_BYTE dummy_key[3 * DES_KEY_SIZE] = { 0, }; CK_ULONG rc; CK_ULONG keysize; if (token_specific.t_des_key_gen == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (token_specific.token_keysize) keysize = token_specific.token_keysize; else keysize = (3 * DES_KEY_SIZE); if ((des_key = (CK_BYTE *)calloc(1,keysize)) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = token_specific.t_des_key_gen(des_key, keysize, 3 * DES_KEY_SIZE); if (rc != CKR_OK) goto err; /* For secure-key keys put in CKA_IBM_OPAQUE * and put dummy_key in CKA_VALUE. */ if (token_specific.token_keysize) { opaque_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + keysize); if (!opaque_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto err; } opaque_attr->type = CKA_IBM_OPAQUE; opaque_attr->ulValueLen = keysize; opaque_attr->pValue = (CK_BYTE *)opaque_attr + sizeof(CK_ATTRIBUTE); memcpy(opaque_attr->pValue, des_key, keysize); template_update_attribute(tmpl, opaque_attr); } value_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + 3*DES_KEY_SIZE ); key_type_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); class_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); local_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!value_attr || !key_type_attr || !class_attr || !local_attr) { if (value_attr) free( value_attr ); if (key_type_attr) free( key_type_attr ); if (class_attr) free( class_attr ); if (local_attr) free( local_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto err; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = 3 * DES_KEY_SIZE; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); if (token_specific.token_keysize) memcpy( value_attr->pValue, dummy_key, 3 * DES_KEY_SIZE ); else memcpy( value_attr->pValue, des_key, 3 * DES_KEY_SIZE ); free(des_key); key_type_attr->type = CKA_KEY_TYPE; key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE); key_type_attr->pValue = (CK_BYTE *)key_type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)key_type_attr->pValue = CKK_DES3; class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY; local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = TRUE; template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, key_type_attr ); template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, local_attr ); return CKR_OK; err: if (des_key) free(des_key); return rc; } // // CK_RV ckm_des3_ecb_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_tdes_ecb == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_tdes_ecb(in_data, in_data_len, out_data, out_data_len, key, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 ecb encrypt failed.\n"); return rc; } // // CK_RV ckm_des3_ecb_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_tdes_ecb == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_tdes_ecb(in_data, in_data_len, out_data, out_data_len, key, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 ecb decrypt failed.\n"); return rc; } // // CK_RV ckm_des3_cbc_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_BYTE * init_v, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !init_v || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_tdes_cbc == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_tdes_cbc(in_data, in_data_len, out_data, out_data_len, key, init_v, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 cbc encrypt failed.\n"); return rc; } // // CK_RV ckm_des3_cbc_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_BYTE * init_v, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !init_v || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_tdes_cbc == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_tdes_cbc(in_data, in_data_len, out_data, out_data_len, key, init_v, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific des3 cbc decrypt failed.\n"); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/common/mech_rsa.c0000755000175000017500000026104512630407154021210 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: mech_rsa.c // // Mechanisms for RSA // // Routines contained within: #include #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" CK_RV rsa_get_key_info(OBJECT *key_obj, CK_ULONG *mod_bytes, CK_OBJECT_CLASS *keyclass) { CK_RV rc; CK_ATTRIBUTE *attr; rc = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS in the template\n"); return CKR_FUNCTION_FAILED; } else *mod_bytes = attr->ulValueLen; rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_CLASS in the template\n"); return CKR_FUNCTION_FAILED; } else *keyclass = *(CK_OBJECT_CLASS *)attr->pValue; return CKR_OK; } /* * Format an encryption block according to PKCS #1: RSA Encryption, Version * 1.5. */ CK_RV rsa_format_block( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len, CK_ULONG type ) { CK_ULONG padding_len, i; CK_RV rc; if (!in_data || !in_data_len || !out_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (out_data_len < (in_data_len + 11)) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; return rc; } /* * The padding string PS shall consist of k-3-||D|| octets. */ padding_len = out_data_len - 3 - in_data_len; /* * For block types 01 and 02, the padding string is at least eight octets * long, which is a security condition for public-key operations that * prevents an attacker from recoving data by trying all possible * encryption blocks. */ if ((type == 1 || type == 2) && ((padding_len) < 8)) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); rc = CKR_DATA_LEN_RANGE; return rc; } /* * The leading 00 octet. */ out_data[0] = (CK_BYTE)0; /* * The block type. */ out_data[1] = (CK_BYTE)type; switch (type) { /* * For block type 00, the octets shall have value 00. * EB = 00 || 00 || 00 * i || D * Where D must begin with a nonzero octet. */ case 0: if (in_data[0] == (CK_BYTE)0) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_INVALID)); rc = CKR_DATA_INVALID; return rc; } for (i = 2; i < (padding_len + 2); i++) out_data[i] = (CK_BYTE)0; break; /* * For block type 01, they shall have value FF. * EB = 00 || 01 || FF * i || 00 || D */ case 1: for (i = 2; i < (padding_len + 2); i++) out_data[i] = (CK_BYTE)0xff; break; /* * For block type 02, they shall be pseudorandomly generated and * nonzero. * EB = 00 || 02 || ?? * i || 00 || D * Where ?? is nonzero. */ case 2: for (i = 2; i < (padding_len + 2); i++) { rc = rng_generate(&out_data[i], 1); if (rc != CKR_OK) { TRACE_DEVEL("rng_generate failed.\n"); return rc; } if (out_data[i] == (CK_BYTE)0) { /* avoid zeros by explicitly making them all 0xff - * won't hurt entropy that bad, and it's better than * looping over rng_generate */ out_data[i] = (CK_BYTE)0xff; } } break; default: TRACE_ERROR("%s\n", ock_err(ERR_DATA_INVALID)); rc = CKR_DATA_INVALID; return rc; } out_data[i] = (CK_BYTE)0; i++; memcpy(&out_data[i], in_data, in_data_len); rc = CKR_OK; return rc; } /* * Parse an encryption block according to PKCS #1: RSA Encryption, Version * 1.5. */ CK_RV rsa_parse_block( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG type ) { CK_ULONG i; CK_RV rc; if (!in_data || !out_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (in_data_len <= 11) { TRACE_DEVEL("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; return rc; } /* * Check for the leading 00 octet. */ if (in_data[0] != (CK_BYTE)0) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_INVALID)); rc = CKR_ENCRYPTED_DATA_INVALID; return rc; } /* * Check the block type. */ if (in_data[1] != (CK_BYTE)type) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_INVALID)); rc = CKR_ENCRYPTED_DATA_INVALID; return rc; } /* * The block type shall be a single octet indicating the structure of the * encryption block. It shall have value 00, 01, or 02. For a private-key * operation, the block type shall be 00 or 01. For a public-key * operation, it shall be 02. * * For block type 00, the octets shall have value 00; for block type 01, * they shall have value FF; and for block type 02, they shall be * pseudorandomly generated and nonzero. * * For block type 00, the data must begin with a nonzero octet or have * known length so that the encryption block can be parsed unambiguously. * For block types 01 and 02, the encryption block can be parsed * unambiguously since the padding string contains no octets with value 00 * and the padding string is separated from the data by an octet with * value 00. */ switch (type) { /* * For block type 00, the octets shall have value 00. * EB = 00 || 00 || 00 * i || D * Where D must begin with a nonzero octet. */ case 0: for (i = 2; i <= (in_data_len - 2); i++) { if (in_data[i] != (CK_BYTE)0) break; } break; /* * For block type 01, they shall have value FF. * EB = 00 || 01 || FF * i || 00 || D */ case 1: for (i = 2; i <= (in_data_len - 2); i++) { if (in_data[i] != (CK_BYTE)0xff) { if (in_data[i] == (CK_BYTE)0) { i++; break; } TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_INVALID)); rc = CKR_ENCRYPTED_DATA_INVALID; return rc; } } break; /* * For block type 02, they shall be pseudorandomly generated and * nonzero. * EB = 00 || 02 || ?? * i || 00 || D * Where ?? is nonzero. */ case 2: for (i = 2; i <= (in_data_len - 2); i++) { if (in_data[i] == (CK_BYTE)0) { i++; break; } } break; default: TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_INVALID)); rc = CKR_ENCRYPTED_DATA_INVALID; return rc; } /* * For block types 01 and 02, the padding string is at least eight octets * long, which is a security condition for public-key operations that * prevents an attacker from recoving data by trying all possible * encryption blocks. */ if ((type == 1 || type == 2) && ((i - 3) < 8)) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_INVALID)); rc = CKR_ENCRYPTED_DATA_INVALID; return rc; } if (in_data_len <= i) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_INVALID)); rc = CKR_ENCRYPTED_DATA_INVALID; return rc; } if (*out_data_len < (in_data_len - i)) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; return rc; } memcpy(out_data, &in_data[i], in_data_len - i); *out_data_len = in_data_len - i; rc = CKR_OK; return rc; } /* helper function for rsa-oaep */ CK_RV get_mgf_mech(CK_RSA_PKCS_MGF_TYPE mgf, CK_MECHANISM_TYPE *mech) { switch(mgf) { case CKG_MGF1_SHA1: *mech = CKM_SHA_1; break; case CKG_MGF1_SHA256: *mech = CKM_SHA256; break; case CKG_MGF1_SHA384: *mech = CKM_SHA384; break; case CKG_MGF1_SHA512: *mech = CKM_SHA512; break; default: return CKR_MECHANISM_INVALID; } return CKR_OK; } // // CK_RV rsa_pkcs_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; CK_ULONG modulus_bytes; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (in_data_len > (modulus_bytes - 11)){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return CKR_OK; } if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } // this had better be a public key if (keyclass != CKO_PUBLIC_KEY){ TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if ( token_specific.t_rsa_encrypt == NULL ) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_encrypt(in_data, in_data_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_DEVEL("Token Specific rsa encrypt failed.\n"); return rc; } // // CK_RV rsa_pkcs_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; CK_ULONG modulus_bytes; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (in_data_len != modulus_bytes){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } if (length_only == TRUE) { // this is not exact but it's the upper bound; otherwise we'll need // to do the RSA operation just to get the required length // *out_data_len = modulus_bytes - 11; return CKR_OK; } if (*out_data_len < (modulus_bytes - 11)) { *out_data_len = modulus_bytes - 11; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } // this had better be a private key if (keyclass != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if( token_specific.t_rsa_decrypt == NULL ) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_decrypt(in_data, in_data_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) { if (rc == CKR_DATA_LEN_RANGE) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } TRACE_DEVEL("Token Specific rsa decrypt failed.\n"); } return rc; } CK_RV rsa_oaep_crypt(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BBOOL encrypt) { OBJECT *key_obj = NULL; CK_ULONG hlen, modulus_bytes; CK_OBJECT_CLASS keyclass; CK_BYTE hash[MAX_SHA_HASH_SIZE]; CK_RV rc; CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return CKR_OK; } if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* * To help mitigate timing and fault attacks when decrypting, * check oaep parameters that are passed in right now and compute * the hash of the Label. * * PKCS#11v2.20, section 12.1.7, Step a: if "source" is empty, * then pSourceData and ulSourceDatalen must be NULL, and zero * respectively. */ oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR)ctx->mech.pParameter; if (!(oaepParms->source) && (oaepParms->pSourceData || oaepParms->ulSourceDataLen)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } /* verify hashAlg now as well as get hash size. */ hlen = 0; rc = get_sha_size(oaepParms->hashAlg, &hlen); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } /* modulus size should be >= 2*hashsize+2 */ if (modulus_bytes < (2 * hlen + 2)) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); return CKR_KEY_SIZE_RANGE; } /* hash the label now */ if (!(oaepParms->pSourceData) || !(oaepParms->ulSourceDataLen)) rc = compute_sha("", 0, hash, oaepParms->hashAlg); else rc = compute_sha(oaepParms->pSourceData, oaepParms->ulSourceDataLen, hash, oaepParms->hashAlg); if (encrypt) { if (in_data_len > (modulus_bytes - 2 * hlen - 2)) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } // this had better be a public key if (keyclass != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if (token_specific.t_rsa_oaep_encrypt == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_oaep_encrypt(ctx, in_data, in_data_len, out_data, out_data_len, hash, hlen); } else { // decrypt if (in_data_len != modulus_bytes) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } // this had better be a private key if (keyclass != CKO_PRIVATE_KEY) { TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if (token_specific.t_rsa_oaep_decrypt == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_oaep_decrypt(ctx, in_data, in_data_len, out_data, out_data_len, hash, hlen); } if (rc != CKR_OK) TRACE_DEVEL("Token Specific rsa oaep decrypt failed.\n"); return rc; } CK_RV rsa_pkcs_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; CK_ULONG modulus_bytes; CK_OBJECT_CLASS keyclass; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (in_data_len > (modulus_bytes - 11)){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return CKR_OK; } if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } // this had better be a private key // if (keyclass != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if(token_specific.t_rsa_sign == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_sign(in_data, in_data_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_DEVEL("Token Specific rsa sign failed.\n"); return rc; } // // CK_RV rsa_pkcs_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { OBJECT *key_obj = NULL; CK_ULONG modulus_bytes; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (sig_len != modulus_bytes){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } // verifying is a public key operation // if (keyclass != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if (token_specific.t_rsa_verify == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_verify(in_data, in_data_len, signature, sig_len, key_obj); if (rc != CKR_OK) TRACE_DEVEL("Token Specific rsa verify failed.\n"); return rc; } // // CK_RV rsa_pkcs_verify_recover( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT *key_obj = NULL; CK_OBJECT_CLASS keyclass; CK_ULONG modulus_bytes; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (sig_len != modulus_bytes){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } if (length_only == TRUE) { *out_data_len = modulus_bytes - 11; return CKR_OK; } /* this had better be a public key */ if (keyclass != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if (token_specific.t_rsa_verify_recover == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_verify_recover(signature, sig_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_DEVEL("Token Specific rsa verify failed.\n"); return rc; } // // CK_RV rsa_x509_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; CK_OBJECT_CLASS keyclass; CK_ULONG modulus_bytes; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // CKM_RSA_X_509 requires input data length to be no bigger than the modulus // if (in_data_len > modulus_bytes){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return CKR_OK; } if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* this had better be a public key */ if (keyclass != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if (token_specific.t_rsa_x509_encrypt == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_x509_encrypt(in_data, in_data_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_DEVEL("Token Specific rsa x509 encrypt failed.\n"); return rc; } // // CK_RV rsa_x509_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; CK_ULONG modulus_bytes; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (in_data_len != modulus_bytes){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return CKR_OK; } // Although X.509 prepads with zeros, we don't strip it after // decryption (PKCS #11 specifies that X.509 decryption is supposed // to produce K bytes of cleartext where K is the modulus length) // if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* this had better be a private key */ if (keyclass != CKO_PRIVATE_KEY) { TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if (token_specific.t_rsa_x509_encrypt == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_x509_decrypt(in_data, in_data_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_ERROR("Token Specific rsa x509 decrypt failed.\n"); // ckm_rsa_operation is used for all RSA operations so we need to adjust // the return code accordingly // if (rc == CKR_DATA_LEN_RANGE){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } return rc; } // // CK_RV rsa_x509_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; CK_ULONG modulus_bytes; CK_OBJECT_CLASS keyclass; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (in_data_len > modulus_bytes){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return CKR_OK; } if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* this had better be a private key */ if (keyclass != CKO_PRIVATE_KEY) { TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if (token_specific.t_rsa_x509_sign == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_x509_sign(in_data, in_data_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_DEVEL("Token Specific rsa x509 sign failed.\n"); return rc; } // // CK_RV rsa_x509_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { OBJECT *key_obj = NULL; CK_OBJECT_CLASS keyclass; CK_ULONG modulus_bytes; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (sig_len != modulus_bytes){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } /* this had better be a public key */ if (keyclass != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if (token_specific.t_rsa_x509_verify == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } // verify is a public key operation --> encrypt // rc = token_specific.t_rsa_x509_verify(in_data, in_data_len, signature, sig_len, key_obj); if (rc != CKR_OK) TRACE_ERROR("Token Specific rsa x509 verify failed.\n"); return rc; } // // CK_RV rsa_x509_verify_recover( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT *key_obj = NULL; CK_ULONG modulus_bytes; CK_OBJECT_CLASS keyclass; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } // check input data length restrictions // if (sig_len != modulus_bytes){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return CKR_OK; } // we perform no stripping of prepended zero bytes here // if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* this had better be a public key */ if (keyclass != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* check for token specific call first */ if (token_specific.t_rsa_x509_verify_recover == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } // verify is a public key operation --> encrypt // rc = token_specific.t_rsa_x509_verify_recover(signature, sig_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_ERROR("Token Specific rsa x509 verify recover.\n"); return rc; } CK_RV rsa_pss_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { CK_RV rc; OBJECT *key_obj = NULL; CK_ULONG modulus_bytes, hlen; CK_OBJECT_CLASS keyclass; CK_RSA_PKCS_PSS_PARAMS_PTR pssParms = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } /* get modulus and key class */ rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } if (length_only == TRUE) { *out_data_len = modulus_bytes; return CKR_OK; } /* verify hashAlg now as well as get hash size. */ pssParms = (CK_RSA_PKCS_PSS_PARAMS_PTR)ctx->mech.pParameter; hlen = 0; rc = get_sha_size(pssParms->hashAlg, &hlen); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } /* pkcs#11v2.2, 12.1.10 states that this mechanism does not * compute a hash value on the message to be signed. * It assumes the input data is the hashed message. */ if (in_data_len != hlen) { TRACE_ERROR("%s\n", ock_err(CKR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } if (*out_data_len < modulus_bytes) { *out_data_len = modulus_bytes; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* this had better be a private key */ if (keyclass != CKO_PRIVATE_KEY) { TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if (token_specific.t_rsa_pss_sign == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_pss_sign(ctx, in_data, in_data_len, out_data, out_data_len); if (rc != CKR_OK) TRACE_DEVEL("Token Specific rsa pss sign failed.\n"); return rc; } CK_RV rsa_pss_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_RV rc; OBJECT *key_obj = NULL; CK_ULONG modulus_bytes; CK_OBJECT_CLASS keyclass; rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } /* get modulus and key class */ rc = rsa_get_key_info(key_obj, &modulus_bytes, &keyclass); if (rc != CKR_OK) { TRACE_DEVEL("rsa_get_key_info failed.\n"); return rc; } /* check input data length restrictions */ if (sig_len != modulus_bytes) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } /* this had better be a public key */ if (keyclass != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if (token_specific.t_rsa_pss_verify == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_pss_verify(ctx, in_data, in_data_len, signature, sig_len); if (rc != CKR_OK) TRACE_ERROR("Token Specific rsa pss verify.\n"); return rc; } CK_RV rsa_hash_pss_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *sig, CK_ULONG *sig_len) { CK_ULONG hlen; CK_BYTE hash[MAX_SHA_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT sign_ctx; CK_MECHANISM digest_mech, sign_mech; CK_RV rc; if (!sess || !ctx || !in_data) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset(&digest_ctx, 0x0, sizeof(digest_ctx)); memset(&sign_ctx, 0x0, sizeof(sign_ctx)); switch (ctx->mech.mechanism) { case CKM_SHA1_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA_1; break; case CKM_SHA256_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA256; break; case CKM_SHA384_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA384; break; case CKM_SHA512_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA512; break; default: return CKR_MECHANISM_INVALID; } digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = get_sha_size(digest_mech.mechanism, &hlen); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest(sess, length_only, &digest_ctx, in_data, in_data_len, hash, &hlen); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } /* sign the hash */ sign_mech.mechanism = CKM_RSA_PKCS_PSS; sign_mech.ulParameterLen = ctx->mech.ulParameterLen; sign_mech.pParameter = ctx->mech.pParameter; rc = sign_mgr_init(sess, &sign_ctx, &sign_mech, FALSE, ctx->key); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } rc = sign_mgr_sign(sess, length_only, &sign_ctx, hash, hlen, sig, sig_len); if (rc != CKR_OK) TRACE_DEVEL("Sign Mgr Sign failed.\n"); done: sign_mgr_cleanup(&sign_ctx); return rc; } CK_RV rsa_hash_pss_update(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { DIGEST_CONTEXT *digest_ctx = NULL; CK_MECHANISM digest_mech; CK_RV rc; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } /* see if digest has already been through init */ digest_ctx = (DIGEST_CONTEXT *)ctx->context; if (digest_ctx->active == FALSE) { switch (ctx->mech.mechanism) { case CKM_SHA1_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA_1; break; case CKM_SHA256_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA256; break; case CKM_SHA384_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA384; break; case CKM_SHA512_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA512; break; default: return CKR_MECHANISM_INVALID; } digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } } rc = digest_mgr_digest_update(sess, digest_ctx, in_data, in_data_len); if (rc != CKR_OK) TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } CK_RV rsa_hash_pss_sign_final(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG *sig_len) { CK_ULONG hlen; CK_BYTE hash[MAX_SHA_HASH_SIZE]; DIGEST_CONTEXT *digest_ctx; SIGN_VERIFY_CONTEXT sign_ctx; CK_MECHANISM sign_mech; CK_RV rc; if (!sess || !ctx || !sig_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset(&sign_ctx, 0x0, sizeof(sign_ctx)); digest_ctx = (DIGEST_CONTEXT *)ctx->context; rc = get_sha_size(digest_ctx->mech.mechanism, &hlen); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = digest_mgr_digest_final(sess, length_only, digest_ctx, hash, &hlen); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } /* sign the hash */ sign_mech.mechanism = CKM_RSA_PKCS_PSS; sign_mech.ulParameterLen = ctx->mech.ulParameterLen; sign_mech.pParameter = ctx->mech.pParameter; rc = sign_mgr_init(sess, &sign_ctx, &sign_mech, FALSE, ctx->key); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } rc = sign_mgr_sign(sess, length_only, &sign_ctx, hash, hlen, signature, sig_len); if (rc != CKR_OK) TRACE_DEVEL("Sign Mgr Sign failed.\n"); done: sign_mgr_cleanup(&sign_ctx); return rc; } CK_RV rsa_hash_pss_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_ULONG hlen; CK_BYTE hash[MAX_SHA_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT verify_ctx; CK_MECHANISM digest_mech, verify_mech; CK_RV rc; if (!sess || !ctx || !in_data) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset(&digest_ctx, 0x0, sizeof(digest_ctx)); memset(&verify_ctx, 0x0, sizeof(verify_ctx)); switch (ctx->mech.mechanism) { case CKM_SHA1_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA_1; break; case CKM_SHA256_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA256; break; case CKM_SHA384_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA384; break; case CKM_SHA512_RSA_PKCS_PSS: digest_mech.mechanism = CKM_SHA512; break; default: return CKR_MECHANISM_INVALID; } digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = get_sha_size(digest_mech.mechanism, &hlen); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest(sess, FALSE, &digest_ctx, in_data, in_data_len, hash, &hlen); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } /* sign the hash */ verify_mech.mechanism = CKM_RSA_PKCS_PSS; verify_mech.ulParameterLen = ctx->mech.ulParameterLen; verify_mech.pParameter = ctx->mech.pParameter; rc = verify_mgr_init(sess, &verify_ctx, &verify_mech, FALSE, ctx->key); if (rc != CKR_OK) { TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; } rc = verify_mgr_verify(sess, &verify_ctx, hash, hlen, signature, sig_len); if (rc != CKR_OK) TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: verify_mgr_cleanup(&verify_ctx); return rc; } CK_RV rsa_hash_pss_verify_final(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG sig_len) { CK_ULONG hlen; CK_BYTE hash[MAX_SHA_HASH_SIZE]; DIGEST_CONTEXT *digest_ctx; SIGN_VERIFY_CONTEXT verify_ctx; CK_MECHANISM verify_mech; CK_RV rc; if (!sess || !ctx || !signature) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset(&verify_ctx, 0x0, sizeof(verify_ctx)); digest_ctx = (DIGEST_CONTEXT *)ctx->context; rc = get_sha_size(digest_ctx->mech.mechanism, &hlen); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = digest_mgr_digest_final(sess, FALSE, digest_ctx, hash, &hlen); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } /* sign the hash */ verify_mech.mechanism = CKM_RSA_PKCS_PSS; verify_mech.ulParameterLen = ctx->mech.ulParameterLen; verify_mech.pParameter = ctx->mech.pParameter; rc = verify_mgr_init(sess, &verify_ctx, &verify_mech, FALSE, ctx->key); if (rc != CKR_OK) { TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; } rc = verify_mgr_verify(sess, &verify_ctx, hash, hlen, signature, sig_len); if (rc != CKR_OK) TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: verify_mgr_cleanup(&verify_ctx); return rc; } // // CK_RV rsa_hash_pkcs_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len ) { CK_BYTE * ber_data = NULL; CK_BYTE * octet_str = NULL; CK_BYTE * oid = NULL; CK_BYTE * tmp = NULL; CK_ULONG buf1[16]; // 64 bytes is more than enough CK_BYTE hash[SHA5_HASH_SIZE]; // must be large enough for the largest hash DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT sign_ctx; CK_MECHANISM digest_mech; CK_MECHANISM sign_mech; CK_ULONG ber_data_len, hash_len, octet_str_len, oid_len; CK_RV rc; if (!sess || !ctx || !in_data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset( &digest_ctx, 0x0, sizeof(digest_ctx) ); memset( &sign_ctx, 0x0, sizeof(sign_ctx) ); if (ctx->mech.mechanism == CKM_MD2_RSA_PKCS) { digest_mech.mechanism = CKM_MD2; oid = ber_AlgMd2; oid_len = ber_AlgMd2Len; } else if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) { digest_mech.mechanism = CKM_MD5; oid = ber_AlgMd5; oid_len = ber_AlgMd5Len; } else if (ctx->mech.mechanism == CKM_SHA256_RSA_PKCS) { digest_mech.mechanism = CKM_SHA256; oid = ber_AlgSha256; oid_len = ber_AlgSha256Len; } else if (ctx->mech.mechanism == CKM_SHA384_RSA_PKCS) { digest_mech.mechanism = CKM_SHA384; oid = ber_AlgSha384; oid_len = ber_AlgSha384Len; } else if (ctx->mech.mechanism == CKM_SHA512_RSA_PKCS) { digest_mech.mechanism = CKM_SHA512; oid = ber_AlgSha512; oid_len = ber_AlgSha512Len; } else { digest_mech.mechanism = CKM_SHA_1; oid = ber_AlgSha1; oid_len = ber_AlgSha1Len; } digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest( sess, length_only, &digest_ctx, in_data, in_data_len, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } // build the BER-encodings rc = ber_encode_OCTET_STRING( FALSE, &octet_str, &octet_str_len, hash, hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_OCTET_STRING failed.\n"); goto error; } tmp = (CK_BYTE *)buf1; memcpy( tmp, oid, oid_len ); memcpy( tmp + oid_len, octet_str, octet_str_len); rc = ber_encode_SEQUENCE( FALSE, &ber_data, &ber_data_len, tmp, (oid_len + octet_str_len) ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_SEQUENCE failed.\n"); goto error; } // sign the BER-encoded data block sign_mech.mechanism = CKM_RSA_PKCS; sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; rc = sign_mgr_init( sess, &sign_ctx, &sign_mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Sign Mgr Init failed.\n"); goto error; } rc = sign_mgr_sign( sess, length_only, &sign_ctx, ber_data, ber_data_len, signature, sig_len ); if (rc != CKR_OK) TRACE_DEVEL("Sign Mgr Sign failed.\n"); error: if (octet_str) free( octet_str ); if (ber_data) free( ber_data ); sign_mgr_cleanup( &sign_ctx ); return rc; } // // CK_RV rsa_hash_pkcs_sign_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { RSA_DIGEST_CONTEXT * context = NULL; CK_MECHANISM digest_mech; CK_RV rc; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (RSA_DIGEST_CONTEXT *)ctx->context; if (context->flag == FALSE) { if (ctx->mech.mechanism == CKM_MD2_RSA_PKCS) digest_mech.mechanism = CKM_MD2; else if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) digest_mech.mechanism = CKM_MD5; else if (ctx->mech.mechanism == CKM_SHA256_RSA_PKCS) digest_mech.mechanism = CKM_SHA256; else if (ctx->mech.mechanism == CKM_SHA384_RSA_PKCS) digest_mech.mechanism = CKM_SHA384; else if (ctx->mech.mechanism == CKM_SHA512_RSA_PKCS) digest_mech.mechanism = CKM_SHA512; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &context->hash_context, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } context->flag = TRUE; } rc = digest_mgr_digest_update( sess, &context->hash_context, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } return CKR_OK; } // // CK_RV rsa_hash_pkcs_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { CK_BYTE * ber_data = NULL; CK_BYTE * octet_str = NULL; CK_BYTE * oid = NULL; CK_BYTE * tmp = NULL; CK_ULONG buf1[16]; // 64 bytes is more than enough CK_BYTE hash[SHA5_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT verify_ctx; CK_MECHANISM digest_mech; CK_MECHANISM verify_mech; CK_ULONG ber_data_len, hash_len, octet_str_len, oid_len; CK_RV rc; if (!sess || !ctx || !in_data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset( &digest_ctx, 0x0, sizeof(digest_ctx) ); memset( &verify_ctx, 0x0, sizeof(verify_ctx) ); if (ctx->mech.mechanism == CKM_MD2_RSA_PKCS) { digest_mech.mechanism = CKM_MD2; oid = ber_AlgMd2; oid_len = ber_AlgMd2Len; } else if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) { digest_mech.mechanism = CKM_MD5; oid = ber_AlgMd5; oid_len = ber_AlgMd5Len; } else if (ctx->mech.mechanism == CKM_SHA256_RSA_PKCS) { digest_mech.mechanism = CKM_SHA256; oid = ber_AlgSha256; oid_len = ber_AlgSha256Len; } else if (ctx->mech.mechanism == CKM_SHA384_RSA_PKCS) { digest_mech.mechanism = CKM_SHA384; oid = ber_AlgSha384; oid_len = ber_AlgSha384Len; } else if (ctx->mech.mechanism == CKM_SHA512_RSA_PKCS) { digest_mech.mechanism = CKM_SHA512; oid = ber_AlgSha512; oid_len = ber_AlgSha512Len; } else { digest_mech.mechanism = CKM_SHA_1; oid = ber_AlgSha1; oid_len = ber_AlgSha1Len; } digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest( sess, FALSE, &digest_ctx, in_data, in_data_len, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } // Build the BER encoding // rc = ber_encode_OCTET_STRING( FALSE, &octet_str, &octet_str_len, hash, hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_OCTET_STRING failed.\n"); goto done; } tmp = (CK_BYTE *)buf1; memcpy( tmp, oid, oid_len ); memcpy( tmp + oid_len, octet_str, octet_str_len ); rc = ber_encode_SEQUENCE( FALSE, &ber_data, &ber_data_len, tmp, (oid_len + octet_str_len) ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_SEQUENCE failed.\n"); goto done; } // Verify the Signed BER-encoded Data block // verify_mech.mechanism = CKM_RSA_PKCS; verify_mech.ulParameterLen = 0; verify_mech.pParameter = NULL; rc = verify_mgr_init( sess, &verify_ctx, &verify_mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; } rc = verify_mgr_verify( sess, &verify_ctx, ber_data, ber_data_len, signature, sig_len ); if (rc != CKR_OK) TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: if (octet_str) free( octet_str ); if (ber_data) free( ber_data ); sign_mgr_cleanup( &verify_ctx ); return rc; } // // CK_RV rsa_hash_pkcs_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { RSA_DIGEST_CONTEXT * context = NULL; CK_MECHANISM digest_mech; CK_RV rc; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (RSA_DIGEST_CONTEXT *)ctx->context; if (context->flag == FALSE) { if (ctx->mech.mechanism == CKM_MD2_RSA_PKCS) digest_mech.mechanism = CKM_MD2; else if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) digest_mech.mechanism = CKM_MD5; else if (ctx->mech.mechanism == CKM_SHA256_RSA_PKCS) digest_mech.mechanism = CKM_SHA256; else if (ctx->mech.mechanism == CKM_SHA384_RSA_PKCS) digest_mech.mechanism = CKM_SHA384; else if (ctx->mech.mechanism == CKM_SHA512_RSA_PKCS) digest_mech.mechanism = CKM_SHA512; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &context->hash_context, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } context->flag = TRUE; } rc = digest_mgr_digest_update( sess, &context->hash_context, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } return CKR_OK; } // // CK_RV rsa_hash_pkcs_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG * sig_len ) { CK_BYTE * ber_data = NULL; CK_BYTE * octet_str = NULL; CK_BYTE * oid = NULL; CK_BYTE * tmp = NULL; CK_ULONG buf1[16]; // 64 bytes is more than enough CK_BYTE hash[SHA5_HASH_SIZE]; RSA_DIGEST_CONTEXT * context = NULL; CK_ULONG ber_data_len, hash_len, octet_str_len, oid_len; CK_MECHANISM sign_mech; SIGN_VERIFY_CONTEXT sign_ctx; CK_RV rc; if (!sess || !ctx || !sig_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_MD2_RSA_PKCS) { oid = ber_AlgMd2; oid_len = ber_AlgMd2Len; } else if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) { oid = ber_AlgMd5; oid_len = ber_AlgMd5Len; } else if (ctx->mech.mechanism == CKM_SHA256_RSA_PKCS) { oid = ber_AlgSha256; oid_len = ber_AlgSha256Len; } else if (ctx->mech.mechanism == CKM_SHA384_RSA_PKCS) { oid = ber_AlgSha384; oid_len = ber_AlgSha384Len; } else if (ctx->mech.mechanism == CKM_SHA512_RSA_PKCS) { oid = ber_AlgSha512; oid_len = ber_AlgSha512Len; } else { oid = ber_AlgSha1; oid_len = ber_AlgSha1Len; } memset( &sign_ctx, 0x0, sizeof(sign_ctx)); context = (RSA_DIGEST_CONTEXT *)ctx->context; hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, length_only, &context->hash_context, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } // Build the BER Encoded Data block // rc = ber_encode_OCTET_STRING( FALSE, &octet_str, &octet_str_len, hash, hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_OCTET_STRING failed.\n"); return rc; } tmp = (CK_BYTE *)buf1; memcpy( tmp, oid, oid_len ); memcpy( tmp + oid_len, octet_str, octet_str_len ); rc = ber_encode_SEQUENCE( FALSE, &ber_data, &ber_data_len, tmp, (oid_len + octet_str_len) ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_SEQUENCE failed.\n"); goto done; } // sign the BER-encoded data block // sign_mech.mechanism = CKM_RSA_PKCS; sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; rc = sign_mgr_init( sess, &sign_ctx, &sign_mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } rc = sign_mgr_sign( sess, length_only, &sign_ctx, ber_data, ber_data_len, signature, sig_len ); if (rc != CKR_OK) TRACE_DEVEL("Sign Mgr Sign failed.\n"); if (length_only == TRUE || rc == CKR_BUFFER_TOO_SMALL) { sign_mgr_cleanup( &sign_ctx ); return rc; } done: if (octet_str) free( octet_str ); if (ber_data) free( ber_data ); sign_mgr_cleanup( &sign_ctx ); return rc; } // // CK_RV rsa_hash_pkcs_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len ) { CK_BYTE * ber_data = NULL; CK_BYTE * octet_str = NULL; CK_BYTE * oid = NULL; CK_BYTE * tmp = NULL; CK_ULONG buf1[16]; // 64 bytes is more than enough CK_BYTE hash[SHA5_HASH_SIZE]; RSA_DIGEST_CONTEXT * context = NULL; CK_ULONG ber_data_len, hash_len, octet_str_len, oid_len; CK_MECHANISM verify_mech; SIGN_VERIFY_CONTEXT verify_ctx; CK_RV rc; if (!sess || !ctx || !signature){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_MD2_RSA_PKCS) { oid = ber_AlgMd2; oid_len = ber_AlgMd2Len; } else if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) { oid = ber_AlgMd5; oid_len = ber_AlgMd5Len; } else if (ctx->mech.mechanism == CKM_SHA256_RSA_PKCS) { oid = ber_AlgSha256; oid_len = ber_AlgSha256Len; } else if (ctx->mech.mechanism == CKM_SHA384_RSA_PKCS) { oid = ber_AlgSha384; oid_len = ber_AlgSha384Len; } else if (ctx->mech.mechanism == CKM_SHA512_RSA_PKCS) { oid = ber_AlgSha512; oid_len = ber_AlgSha512Len; } else { oid = ber_AlgSha1; oid_len = ber_AlgSha1Len; } memset( &verify_ctx, 0x0, sizeof(verify_ctx)); context = (RSA_DIGEST_CONTEXT *)ctx->context; hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &context->hash_context, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } // Build the BER encoding // rc = ber_encode_OCTET_STRING( FALSE, &octet_str, &octet_str_len, hash, hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_OCTET_STRING failed.\n"); goto done; } tmp = (CK_BYTE *)buf1; memcpy( tmp, oid, oid_len ); memcpy( tmp + oid_len, octet_str, octet_str_len ); rc = ber_encode_SEQUENCE( FALSE, &ber_data, &ber_data_len, tmp, (oid_len + octet_str_len) ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_SEQUENCE failed.\n"); goto done; } // verify the signed BER-encoded data block // verify_mech.mechanism = CKM_RSA_PKCS; verify_mech.ulParameterLen = 0; verify_mech.pParameter = NULL; rc = verify_mgr_init( sess, &verify_ctx, &verify_mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; } rc = verify_mgr_verify( sess, &verify_ctx, ber_data, ber_data_len, signature, sig_len ); if (rc != CKR_OK) TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: if (octet_str) free( octet_str ); if (ber_data) free( ber_data ); verify_mgr_cleanup( &verify_ctx ); return rc; } // // mechanisms // // // CK_RV ckm_rsa_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_RV rc; /* check for token specific call first */ if (token_specific.t_rsa_generate_keypair == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_rsa_generate_keypair(publ_tmpl, priv_tmpl); if (rc != CKR_OK) TRACE_DEVEL("Token specific rsa generate keypair failed.\n"); return rc; } CK_RV mgf1(CK_BYTE *seed, CK_ULONG seedlen, CK_BYTE *mask, CK_ULONG maskLen, CK_RSA_PKCS_MGF_TYPE mgf) { int i, T_len = 0; char *seed_buffer; unsigned char counter[4]; CK_BYTE hash[MAX_SHA_HASH_SIZE]; CK_RV rc = CKR_OK; CK_MECHANISM_TYPE mech; CK_ULONG hlen; if (!mask || !seed) return CKR_FUNCTION_FAILED; rc = get_mgf_mech(mgf, &mech); if (rc != CKR_OK) return CKR_FUNCTION_FAILED; rc = get_sha_size(mech, &hlen); if (rc != CKR_OK) return CKR_FUNCTION_FAILED; /* do some preparations */ seed_buffer = malloc(seedlen + 4); if (seed_buffer == NULL) return CKR_HOST_MEMORY; T_len = maskLen; for (i = 0; T_len > 0; i++) { /* convert i to an octet string of length 4 octets. */ counter[0] = (unsigned char)((i >> 24) & 0xff); counter[1] = (unsigned char)((i >> 16) & 0xff); counter[2] = (unsigned char)((i >> 8) & 0xff); counter[3] = (unsigned char)(i & 0xff); /* concatenate seed and octet string */ memset(seed_buffer, 0, seedlen + 4); memcpy(seed_buffer, seed, seedlen); memcpy(seed_buffer + seedlen, counter, 4); /* compute hash of concatenated seed and octet string */ rc = compute_sha(seed_buffer, seedlen + 4, hash, mech); if (rc != CKR_OK) goto done; if (T_len >= hlen) memcpy(mask + (i * hlen), hash, hlen); else /* in the case masklen is not a multiple of the * of the hash length, only copy over remainder */ memcpy(mask + (i * hlen), hash, T_len); T_len -= hlen; } done: if (seed_buffer) free(seed_buffer); return rc; } // RSA mechanism - EME-OAEP encoding // CK_RV encode_eme_oaep(CK_BYTE *mData, CK_ULONG mLen, CK_BYTE *emData, CK_ULONG modLength, CK_RSA_PKCS_MGF_TYPE mgf, CK_BYTE *hash, CK_ULONG hlen) { int i, ps_len, dbMask_len; CK_BYTE *maskedSeed, *maskedDB, *dbMask; CK_BYTE seed[MAX_SHA_HASH_SIZE]; CK_RV rc = CKR_OK; if (!mData || !emData) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } /* pkcs1v2.2 Step i: * The encoded messages is a concatenated single octet, 0x00 with * maskedSeed and maskedDB to create encoded message EM. * So lets mark of the places in our output buffer. */ memset(emData, 0, modLength); maskedSeed = emData + 1; maskedDB = emData + hlen + 1; /* pkcs1v2.2, Step b: * Generate an octet string PS and concatenate to DB. */ ps_len = modLength - mLen - (2 * hlen) - 2; memcpy(maskedDB, hash, hlen); memset(maskedDB + hlen, 0, ps_len); /* pkcs1v2.2, Step c: * We have already concatenated hash and PS to maskedDB. * Now just concatenate 0x01 and message. */ maskedDB[hlen + ps_len] = 0x01; memcpy(maskedDB + (hlen + ps_len + 1), mData, mLen); /* pkcs1v2.2, Step d: * Generate a random seed. */ rc = rng_generate(seed, hlen); if (rc != CKR_OK) return rc; /* pkcs1v2.2, Step e: * Compute dbmask using MGF1. */ dbMask_len = modLength - hlen - 1; dbMask = malloc(sizeof(CK_BYTE) * dbMask_len); if (dbMask == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = mgf1(seed, hlen, dbMask, dbMask_len, mgf); if (rc != CKR_OK) goto done; /* pkcs1v2.2, Step f: * Compute maskedDB. */ for (i = 0; i < dbMask_len; i++) maskedDB[i] ^= dbMask[i]; /* pkcs1v2.2, Step g: * Compute seedMask using MGF1. */ memset(maskedSeed, 0, hlen); rc = mgf1(maskedDB, dbMask_len, maskedSeed, hlen, mgf); if (rc != CKR_OK) goto done; /* pkcs1v2.2, Step h: * Compute maskedSeed. */ for (i = 0; i < hlen; i++) maskedSeed[i] ^= seed[i]; done: if (dbMask) free(dbMask); return rc; } CK_RV decode_eme_oaep(CK_BYTE *emData, CK_ULONG emLen, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_RSA_PKCS_MGF_TYPE mgf, CK_BYTE *hash, CK_ULONG hlen) { int i, error = 0;; CK_RV rc = CKR_OK; CK_ULONG dbMask_len, ps_len; CK_BYTE *maskedSeed, *maskedDB, *dbMask, *seedMask; if (!emData || !out_data) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } /* allocate memory now for later use */ dbMask_len = *out_data_len - hlen - 1; dbMask = malloc(sizeof(CK_BYTE) * dbMask_len); seedMask = malloc(sizeof(CK_BYTE) * hlen); if ((seedMask == NULL) || (dbMask == NULL)) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } /* pkcs1v2.2, section 7.1.2, Step 3b: * Separate the encoded message EM and process the decrypted message. * * To mitigate fault and timing attacks, just flag errors and * keep going. */ maskedSeed = emData + 1; maskedDB = emData + hlen + 1; /* pkcs1v2.2, section 7.1.2, Step 3c: * Compute seedMask using MGF1. */ if (mgf1(maskedDB, dbMask_len, seedMask, hlen, mgf)) error++; /* pkcs1v2.2, section 7.1.2, Step 3d: * Compute seed using MGF1. */ for (i = 0; i < hlen; i++) seedMask[i] ^= maskedSeed[i]; /* pkcs1v2.2, section 7.1.2, Step 3e: * Compute dbMask using MGF1. */ if (mgf1(seedMask, hlen, dbMask, dbMask_len, mgf)) error++; /* pkcs1v2.2, section 7.1.2, Step 3f: * Compute db using MGF1. */ for (i = 0; i < dbMask_len; i++) dbMask[i] ^= maskedDB[i]; /* pkcs1v2.2, section 7.1.2, Step 3g: * DB = lHash’ || PS || 0x01 || M . * * If there is no octet with hexadecimal value 0x01 to separate * PS from M, if lHash does not equal lHash’, output “decryption * error” and stop. */ if (memcmp(dbMask, hash, hlen)) error++; ps_len = hlen; while ((dbMask[ps_len] == 0x00) && (ps_len < dbMask_len)) ps_len++; if ((ps_len == dbMask_len) || (dbMask[ps_len] != 0x01) || emData[0]) error++; if (error) { rc = CKR_FUNCTION_FAILED; goto done; } else { ps_len++; *out_data_len = dbMask_len - ps_len; memcpy(out_data, dbMask + ps_len, dbMask_len - ps_len); } done: if (seedMask) free(seedMask); if (dbMask) free(dbMask); return rc; } CK_RV emsa_pss_encode(CK_RSA_PKCS_PSS_PARAMS *pssParms, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *em, CK_ULONG *modbytes) { CK_BYTE *salt, *DB, *H, *buf = NULL; CK_ULONG emBits, emLen, buflen, hlen, PSlen; CK_RV rc = CKR_OK; int i; /* * Note: pkcs#11v2.20, Section 12.1.10: * in_data is the hashed message, mHash. * * Note: em is provided by the caller. It should be big enough to * hold k bytes of data, where k is the length in octets of the * modulus n. */ /* pkcs1v2.2 8.1.1 describes emBits as length in bits of the * modulus - 1. It also says, the octet length of EM will be * one less than k if modBits - 1 is divisible by 8 and equal * to k otherwise. k is the length in octets of the modulus n. */ emBits = (*modbytes * 8) - 1; if ((emBits % 8) == 0) emLen = *modbytes - 1; else emLen = *modbytes; /* get hash size based on hashAlg */ if (get_sha_size(pssParms->hashAlg, &hlen)) return CKR_MECHANISM_INVALID; /* allocate a helper buffer to be used for M' and dbmask */ buflen = emLen - hlen - 1; if (buflen < (8 + hlen + pssParms->sLen)) buflen = 8 + hlen + pssParms->sLen; buf = (CK_BYTE *)malloc(buflen); if (buf == NULL) return CKR_HOST_MEMORY; memset(em, 0, emLen); memset(buf, 0, buflen); /* set some pointers for EM */ DB = em; H = em + (emLen - hlen - 1); /* pkcs1v2.2, Step 3: Check length */ if (emLen < hlen + pssParms->sLen + 2) { rc = CKR_FUNCTION_FAILED; goto done; } /* pkcs1v2.2, Step 4: Generate salt */ salt = buf + (8 + in_data_len); rc = rng_generate(salt, pssParms->sLen); if (rc != CKR_OK) goto done; /* pkcs1v2.2, Step 5: set M' */ memcpy(buf + 8, in_data, in_data_len); /* pkcs1v2.2, Step 6: Compute Hash(M') */ rc = compute_sha(buf, 8 + hlen + pssParms->sLen, H, pssParms->hashAlg); if (rc != CKR_OK) goto done; /* pkcs1v2.2, Step 7 & 8: Generate DB */ PSlen = emLen - pssParms->sLen - hlen - 2; DB[PSlen] = 0x01; memcpy(DB + (PSlen + 1), salt, pssParms->sLen); /* pkcs1v2.2, Step 9: Generate dbMask * Note: reuse "buf" for dbMask. */ memset(buf, 0, buflen); rc = mgf1(H, hlen, buf, emLen - hlen - 1, pssParms->mgf); if (rc != CKR_OK) goto done; /* pkcs1v2.2, Step 10: Compute maskedDB */ for (i = 0; i < (emLen - hlen - 1); i++) em[i] ^= buf[i]; /* pkcs1v2.2, Step 11: Set leftmost bits to zero. */ em[0] &= 0xFF >> (8 * emLen - emBits); /* pkcs1v2.2, Step 12: EM = maskedDB || H || 0xbc */ em[emLen - 1] = 0xbc; *modbytes = emLen; done: if (buf) free(buf); return rc; } CK_RV emsa_pss_verify(CK_RSA_PKCS_PSS_PARAMS *pssParms, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *sig, CK_ULONG modbytes) { int i; CK_ULONG buflen, hlen, emBits, emLen, plen; CK_BYTE *salt, *H, *M, *buf = NULL; CK_BYTE hash[MAX_SHA_HASH_SIZE]; CK_RV rc = CKR_OK; /* pkcs1v2.2 8.1.1 describes emBits as length in bits of the * modulus - 1. It also says, the octet length of EM will be * one less than k if modBits - 1 is divisible by 8 and equal * to k otherwise. k is the length in octets of the modulus n. */ emBits = (modbytes * 8) - 1; if ((emBits % 8) == 0) emLen = modbytes - 1; else emLen = modbytes; /* get hash size based on hashAlg */ if (get_sha_size(pssParms->hashAlg, &hlen)) return CKR_MECHANISM_INVALID; /* set up a big enough helper buffer to be used for M' and DB. */ buflen = (emLen - hlen - 1) + (8 + hlen + pssParms->sLen); buf = (CK_BYTE *)malloc(buflen); if (buf == NULL) return CKR_HOST_MEMORY; memset(buf, 0, buflen); /* pkcs1v2.2, Step 4: Check rightmost octet. */ if (sig[emLen - 1] != 0xbc) { rc = CKR_SIGNATURE_INVALID; goto done; } /* pkcs1v2.2, Step 5: Extract maskedDB and H */ H = sig + (emLen - hlen - 1); /* pkcs1v2.2, Step 6: Check leftmost bits */ if (sig[0] & ~(0xFF >> (8 * emLen - emBits))) { rc = CKR_SIGNATURE_INVALID; goto done; } /* pkcs1v2.2, Step 7: Compute mgf. */ rc = mgf1(H, hlen, buf, emLen - hlen - 1, pssParms->mgf); if (rc != CKR_OK) goto done; /* pkcs1v2.2, Step 8: DB = maskedDB ^ dbMask. */ for (i = 0; i < emLen - hlen - 1; i++) buf[i] ^= sig[i]; /* pkcs1v2.2, Step 9: Set leftmost bits in DB to zero. */ buf[0] &= 0xFF >> (8 * emLen - emBits); /* pkcs1v2.2, Step 10: check DB. */ i = 0; plen = emLen - hlen - pssParms->sLen - 2; while ((buf[i] == 0) && ( i < plen)) i++; if ((i != plen) || (buf[i++] != 0x01)) { rc = CKR_SIGNATURE_INVALID; goto done; } /* pkcs1v2.2, Step 11: Get the salt from DB. */ salt = buf + i; /* pkcs1v2.2, Step 12: Set M'. Note: Use end of buf. */ M = buf + (i + pssParms->sLen); memset(M, 0, 8); memcpy(M + 8, in_data, in_data_len); // in_data is mHash. memcpy(M + (8 + in_data_len), salt, pssParms->sLen); /* pkcs1v2.2, Step 13: Compute Hash(M'). */ rc = compute_sha(M, 8 + hlen + pssParms->sLen, hash, pssParms->hashAlg); if (rc != CKR_OK) goto done; /* pkcs1v2.2, Step 14: H == H'. */ if (memcmp(hash, H, hlen)) rc = CKR_SIGNATURE_INVALID; else rc = CKR_OK; done: if (buf) free(buf); return rc; } CK_RV check_pss_params(CK_MECHANISM *mech, CK_ULONG modlen) { CK_RSA_PKCS_PSS_PARAMS *pssParams; CK_MECHANISM_TYPE mgf_mech; CK_ULONG hlen; CK_RV rc; pssParams = (CK_RSA_PKCS_PSS_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } /* * If the signature mechanism includes hashing, make sure * pssParams->hashAlg matches. * * Note: pkcs#1v2.2, Section 8.1, It is recommended that the * hash algorithm used to hash the message be the same as the * one used in mgf. */ rc = get_mgf_mech(pssParams->mgf, &mgf_mech); if (rc != CKR_OK) { TRACE_DEVEL("MGF mechanism is invalid.\n"); return rc; } switch (mech->mechanism) { case CKM_SHA1_RSA_PKCS_PSS: if ((pssParams->hashAlg != CKM_SHA_1) && (pssParams->hashAlg != mgf_mech)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } break; case CKM_SHA256_RSA_PKCS_PSS: if ((pssParams->hashAlg != CKM_SHA256) && (pssParams->hashAlg != mgf_mech)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } break; case CKM_SHA384_RSA_PKCS_PSS: if ((pssParams->hashAlg != CKM_SHA384) && (pssParams->hashAlg != mgf_mech)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } break; case CKM_SHA512_RSA_PKCS_PSS: if ((pssParams->hashAlg != CKM_SHA512) && (pssParams->hashAlg != mgf_mech)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } break; case CKM_RSA_PKCS_PSS: if (pssParams->hashAlg != mgf_mech) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } /* check the salt length, pkcs11v2.2 Section 12.1.14 */ rc = get_sha_size(pssParams->hashAlg, &hlen); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if (!((pssParams->sLen >= 0) && (pssParams->sLen <= modlen - 2 - hlen))) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/attributes.h0000644000175000017500000000135012630407154021606 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token - LDAP functions * * (C) COPYRIGHT International Business Machines Corp. 2012 * * Author: Marcelo Cerri (mhcerri@br.ibm.com) * */ #ifndef _ATTRIBUTES_H_ #define _ATTRIBUTES_H_ #include "pkcs11types.h" void free_attribute_array(CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len); CK_RV dup_attribute_array(CK_ATTRIBUTE_PTR orig, CK_ULONG orig_len, CK_ATTRIBUTE_PTR *p_dest, CK_ULONG *p_dest_len); CK_ATTRIBUTE_PTR get_attribute_by_type(CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_ULONG type); CK_RV add_to_attribute_array(CK_ATTRIBUTE_PTR *p_attrs, CK_ULONG_PTR p_attrs_len, CK_ULONG type, CK_BYTE_PTR value, CK_ULONG value_len); #endif opencryptoki+dfsg/usr/lib/pkcs11/common/dp_obj.c0000644000175000017500000007207312630407154020662 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: dp_obj.c // // Domain Parameter Object functions #include #include #include // for memcmp() et al #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" #include "tok_spec_struct.h" // dp_object_check_required_attributes() // // Check required common attributes for domain parameter objects // CK_RV dp_object_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL found; found = template_attribute_find( tmpl, CKA_KEY_TYPE, &attr ); if (!found) { if (mode == MODE_CREATE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return template_check_required_base_attributes( tmpl, mode ); } CK_RV dp_dsa_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; if (mode == MODE_CREATE){ found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_SUBPRIME, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } else if (mode == MODE_KEYGEN) { found = template_attribute_find( tmpl, CKA_PRIME_BITS, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return dp_object_check_required_attributes( tmpl, mode ); } CK_RV dp_dh_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; if (mode == MODE_CREATE){ found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } else if (mode == MODE_KEYGEN) { found = template_attribute_find( tmpl, CKA_PRIME_BITS, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return dp_object_check_required_attributes( tmpl, mode ); } CK_RV dp_x9dh_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL found; if (mode == MODE_CREATE){ found = template_attribute_find( tmpl, CKA_PRIME, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_SUBPRIME, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_BASE, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } else if (mode == MODE_KEYGEN) { found = template_attribute_find( tmpl, CKA_PRIME_BITS, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } found = template_attribute_find( tmpl, CKA_SUBPRIME_BITS, &attr ); if (!found) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } } return dp_object_check_required_attributes( tmpl, mode ); } // dp_object_set_default_attributes() // CK_RV dp_object_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE * local_attr = NULL; local_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!local_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = FALSE; template_update_attribute( tmpl, local_attr ); return CKR_OK; } // dp_object_validate_attribute() // CK_RV dp_object_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_KEY_TYPE: if (mode == MODE_CREATE) return CKR_OK; else{ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } case CKA_LOCAL: if (mode == MODE_CREATE || mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; } return CKR_OK; default: return template_validate_base_attribute( tmpl, attr, mode ); } } // // CK_RV dp_dsa_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_PRIME: if (mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_PRIME_BITS: if (mode == MODE_CREATE) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_BASE: if (mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_SUBPRIME: if (mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; default: return dp_object_validate_attribute( tmpl, attr, mode ); } } // // CK_RV dp_dh_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_PRIME: if (mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_PRIME_BITS: if (mode == MODE_CREATE) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_BASE: if (mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; default: return dp_object_validate_attribute( tmpl, attr, mode ); } } // // CK_RV dp_x9dh_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode) { switch (attr->type) { case CKA_PRIME: if (mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_PRIME_BITS: if (mode == MODE_CREATE) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_BASE: if (mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_SUBPRIME: if (mode == MODE_KEYGEN) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; case CKA_SUBPRIME_BITS: if (mode == MODE_CREATE) { TRACE_ERROR("%s\n", ock_err(ERR_DOMAIN_PARAMS_INVALID)); return CKR_DOMAIN_PARAMS_INVALID; } return CKR_OK; default: return dp_object_validate_attribute( tmpl, attr, mode ); } } CK_RV dp_dsa_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_RV rc; CK_ATTRIBUTE *prime_attr; CK_ATTRIBUTE *subprime_attr; CK_ATTRIBUTE *base_attr; CK_ATTRIBUTE *primebits_attr; CK_ATTRIBUTE *type_attr; rc = dp_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK) return rc; prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); subprime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); primebits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); if (!prime_attr || !subprime_attr || !base_attr || !primebits_attr || !type_attr) { if (prime_attr) free( prime_attr ); if (subprime_attr) free( subprime_attr ); if (base_attr) free( base_attr ); if (primebits_attr) free( primebits_attr ); if (type_attr) free( type_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; subprime_attr->type = CKA_SUBPRIME; subprime_attr->ulValueLen = 0; subprime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; primebits_attr->type = CKA_PRIME_BITS; primebits_attr->ulValueLen = 0; primebits_attr->pValue = NULL; #if 0 primebits_attr->ulValueLen = sizeof(CK_ULONG); primebits_attr->pValue = (CK_ULONG *)primebits_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)primebits_attr->pValue = 0; #endif type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DSA; template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, subprime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, primebits_attr ); template_update_attribute( tmpl, type_attr ); return CKR_OK; } CK_RV dp_dh_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_RV rc; CK_ATTRIBUTE *prime_attr; CK_ATTRIBUTE *base_attr; CK_ATTRIBUTE *primebits_attr; CK_ATTRIBUTE *type_attr; rc = dp_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK) return rc; prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); primebits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); if (!prime_attr || !base_attr || !primebits_attr || !type_attr) { if (prime_attr) free( prime_attr ); if (base_attr) free( base_attr ); if (primebits_attr) free( primebits_attr ); if (type_attr) free( type_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; primebits_attr->type = CKA_PRIME_BITS; primebits_attr->ulValueLen = 0; primebits_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DH; template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, primebits_attr ); template_update_attribute( tmpl, type_attr ); return CKR_OK; } CK_RV dp_x9dh_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_RV rc; CK_ATTRIBUTE *prime_attr; CK_ATTRIBUTE *subprime_attr; CK_ATTRIBUTE *base_attr; CK_ATTRIBUTE *primebits_attr; CK_ATTRIBUTE *subprimebits_attr; CK_ATTRIBUTE *type_attr; rc = dp_object_set_default_attributes( tmpl, mode ); if (rc != CKR_OK) return rc; prime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); subprime_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); base_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); primebits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); subprimebits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); type_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); if (!prime_attr || !subprime_attr || !base_attr || !primebits_attr || !subprimebits_attr || !type_attr) { if (prime_attr) free( prime_attr ); if (subprime_attr) free( subprime_attr ); if (base_attr) free( base_attr ); if (primebits_attr) free( primebits_attr ); if (subprimebits_attr) free( subprimebits_attr ); if (type_attr) free( type_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } prime_attr->type = CKA_PRIME; prime_attr->ulValueLen = 0; prime_attr->pValue = NULL; subprime_attr->type = CKA_SUBPRIME; subprime_attr->ulValueLen = 0; subprime_attr->pValue = NULL; base_attr->type = CKA_BASE; base_attr->ulValueLen = 0; base_attr->pValue = NULL; primebits_attr->type = CKA_PRIME_BITS; primebits_attr->ulValueLen = 0; primebits_attr->pValue = NULL; subprimebits_attr->type = CKA_SUBPRIME_BITS; subprimebits_attr->ulValueLen = 0; subprimebits_attr->pValue = NULL; type_attr->type = CKA_KEY_TYPE; type_attr->ulValueLen = sizeof(CK_KEY_TYPE); type_attr->pValue = (CK_BYTE *)type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)type_attr->pValue = CKK_DSA; template_update_attribute( tmpl, prime_attr ); template_update_attribute( tmpl, subprime_attr ); template_update_attribute( tmpl, base_attr ); template_update_attribute( tmpl, primebits_attr ); template_update_attribute( tmpl, subprimebits_attr ); template_update_attribute( tmpl, type_attr ); return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/encr_mgr.c0000755000175000017500000015015112630407154021216 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: encr_mgr.c // // Encryption manager routines // #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV encr_mgr_init( SESSION * sess, ENCR_DECR_CONTEXT * ctx, CK_ULONG operation, CK_MECHANISM * mech, CK_OBJECT_HANDLE key_handle ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; if (!sess || !ctx || !mech){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active != FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } // key usage restrictions // if (operation == OP_ENCRYPT_INIT) { rc = object_mgr_find_in_map1( key_handle, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle.\n"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } // is key allowed to do general encryption? // rc = template_attribute_find( key_obj->template, CKA_ENCRYPT, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_ENCRYPT for the key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } else { flag = *(CK_BBOOL *)attr->pValue; if (flag != TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_FUNCTION_NOT_PERMITTED)); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } } else if (operation == OP_WRAP) { rc = object_mgr_find_in_map1( key_handle, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle.\n"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_WRAPPING_KEY_HANDLE_INVALID; else return rc; } // is key allowed to wrap other keys? // rc = template_attribute_find( key_obj->template, CKA_WRAP, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_WRAP for the key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } else { flag = *(CK_BBOOL *)attr->pValue; if (flag == FALSE){ TRACE_ERROR("CKA_WRAP is set to FALSE.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } } else{ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // is the mechanism supported? is the key type correct? is a // parameter present if required? is the key size allowed? // does the key support encryption? // // Will the FCV allow the operation? // switch (mech->mechanism) { case CKM_DES_ECB: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_56_BIT_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_CDMF_ECB: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_CDMF){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_DES_CBC: case CKM_DES_CBC_PAD: { if (mech->ulParameterLen != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_56_BIT_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_DES_CFB8: case CKM_DES_CFB64: case CKM_DES_OFB64: { if (mech->ulParameterLen != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if ((keytype != CKK_DES3) ) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_CDMF_CBC: case CKM_CDMF_CBC_PAD: { if (mech->ulParameterLen != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_CDMF){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_DES3_ECB: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DES3 && keytype != CKK_DES2){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_TRIPLE_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_DES3_CBC: case CKM_DES3_CBC_PAD: { if (mech->ulParameterLen != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DES3 && keytype != CKK_DES2){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_TRIPLE_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_RSA_PKCS_OAEP: if (mech->ulParameterLen == 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } // RSA cannot be used for multi-part operations // ctx->context_len = 0; ctx->context = NULL; break; case CKM_RSA_X_509: case CKM_RSA_PKCS: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // RSA cannot be used for multi-part operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_AES_ECB: { // XXX Copied in from DES3, should be verified - KEY if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_AES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_CONTEXT) ); } break; case CKM_AES_CBC: case CKM_AES_CBC_PAD: { // XXX Copied in from DES3, should be verified - KEY if (mech->ulParameterLen != AES_INIT_VECTOR_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_AES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_CONTEXT) ); } break; case CKM_AES_CTR: { if (mech->ulParameterLen != sizeof(CK_AES_CTR_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_AES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_CONTEXT) ); } break; case CKM_AES_GCM: { if (mech->ulParameterLen != sizeof(CK_GCM_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_AES) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_GCM_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_GCM_CONTEXT)); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(ctx->context, 0x0, sizeof(AES_GCM_CONTEXT)); rc = aes_gcm_init(sess, ctx, mech, key_handle, 1); if (rc != CKR_OK) { TRACE_ERROR("Could not initialize AES_GCM parms.\n"); return CKR_FUNCTION_FAILED; } } break; case CKM_AES_OFB: case CKM_AES_CFB8: case CKM_AES_CFB64: case CKM_AES_CFB128: { if (mech->ulParameterLen != AES_INIT_VECTOR_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if ( keytype != CKK_AES ){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_CONTEXT) ); } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_INVALID; } if ((mech->ulParameterLen > 0) || (mech->mechanism == CKM_AES_CTR) || (mech->mechanism == CKM_AES_GCM)) { ptr = (CK_BYTE *)malloc (mech->ulParameterLen); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, mech->pParameter, mech->ulParameterLen ); } else if (mech->ulParameterLen > 0){ ptr = (CK_BYTE *)malloc(mech->ulParameterLen); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, mech->pParameter, mech->ulParameterLen ); } ctx->key = key_handle; ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = ptr; ctx->multi = FALSE; ctx->active = TRUE; return CKR_OK; } // // CK_RV encr_mgr_cleanup( ENCR_DECR_CONTEXT *ctx ) { if (!ctx){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->context_len = 0; if (ctx->mech.pParameter) { free( ctx->mech.pParameter ); ctx->mech.pParameter = NULL; } if (ctx->context) { free( ctx->context ); ctx->context = NULL; } return CKR_OK; } // // CK_RV encr_mgr_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { CK_KEY_TYPE keytype; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } // if the caller just wants the encrypted length, there is no reason to // specify the input data. I just need the data length // if ((length_only == FALSE) && (!in_data || !out_data)){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->multi == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_CDMF_ECB: case CKM_DES_ECB: return pk_des_ecb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_CDMF_CBC: case CKM_DES_CBC: return pk_des_cbc_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES_CBC_PAD: case CKM_CDMF_CBC_PAD: return des_cbc_pad_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES_OFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_ofb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB8: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x01); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x08); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES3_ECB: return des3_ecb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_CBC: return des3_cbc_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_CBC_PAD: return des3_cbc_pad_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_RSA_PKCS: return rsa_pkcs_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_RSA_PKCS_OAEP: return rsa_oaep_crypt(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, ENCRYPT); case CKM_RSA_X_509: return rsa_x509_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); #ifndef NOAES case CKM_AES_CBC: return aes_cbc_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_ECB: return aes_ecb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CBC_PAD: return aes_cbc_pad_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CTR: return aes_ctr_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_GCM: return aes_gcm_encrypt(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); case CKM_AES_OFB: return aes_ofb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CFB8: return aes_cfb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x01); case CKM_AES_CFB64: return aes_cfb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x08); case CKM_AES_CFB128: return aes_cfb_encrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x10); #endif default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV encr_mgr_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { CK_KEY_TYPE keytype; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (!out_data && !length_only){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } ctx->multi = TRUE; switch (ctx->mech.mechanism) { case CKM_CDMF_ECB: case CKM_DES_ECB: return des_ecb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_CDMF_CBC: case CKM_DES_CBC: return des_cbc_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES_CBC_PAD: case CKM_CDMF_CBC_PAD: return des_cbc_pad_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES_OFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_ofb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB8: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x01); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x08); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES3_ECB: return des3_ecb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_CBC: return des3_cbc_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_CBC_PAD: return des3_cbc_pad_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); #ifndef NOAES case CKM_AES_ECB: return aes_ecb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CBC: return aes_cbc_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CBC_PAD: return aes_cbc_pad_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CTR: return aes_ctr_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_GCM: return aes_gcm_encrypt_update(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); case CKM_AES_OFB: return aes_ofb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CFB8: return aes_cfb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x01); case CKM_AES_CFB64: return aes_cfb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x08); case CKM_AES_CFB128: return aes_cfb_encrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x10); #endif default: return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV encr_mgr_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { CK_KEY_TYPE keytype; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } switch (ctx->mech.mechanism) { case CKM_CDMF_ECB: case CKM_DES_ECB: return des_ecb_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_CDMF_CBC: case CKM_DES_CBC: return des_cbc_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_DES_CBC_PAD: case CKM_CDMF_CBC_PAD: return des_cbc_pad_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_DES_OFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_ofb_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB8: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_encrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x01); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_encrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x08); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES3_ECB: return des3_ecb_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_DES3_CBC: return des3_cbc_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_DES3_CBC_PAD: return des3_cbc_pad_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); #ifndef NOAES case CKM_AES_ECB: return aes_ecb_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_CBC: return aes_cbc_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_CBC_PAD: return aes_cbc_pad_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_CTR: return aes_ctr_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_GCM: return aes_gcm_encrypt_final(sess, length_only, ctx, out_data, out_data_len); case CKM_AES_OFB: return aes_ofb_encrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_CFB8: return aes_cfb_encrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x01); case CKM_AES_CFB64: return aes_cfb_encrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x08); case CKM_AES_CFB128: return aes_cfb_encrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x10); #endif default: return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } opencryptoki+dfsg/usr/lib/pkcs11/common/sw_crypt.h0000644000175000017500000003657012630407154021306 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ #ifndef __SW_CRYPT_H__ #define __SW_CRYPT_H__ #define sw_des3_cbc_encrypt(clear, len, cipher, len2, iv, key) \ sw_des3_cbc(clear, len, cipher, len2, iv, key, 1) #define sw_des3_cbc_decrypt(clear, len, cipher, len2, iv, key) \ sw_des3_cbc(clear, len, cipher, len2, iv, key, 0) CK_RV sw_des3_cbc(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *init_v, CK_BYTE *key_value, CK_BYTE encrypt); #endif opencryptoki+dfsg/usr/lib/pkcs11/common/mech_list.c0000644000175000017500000004355012630407154021372 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* COPYRIGHT (c) International Business Machines Corp. 2005 */ #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" void mech_array_to_list(struct mech_list_item *head, MECH_LIST_ELEMENT mech_list_arr[], int list_len) { int i; struct mech_list_item *current; current = head; for (i = 0; i < list_len; i++) { current->next = malloc(sizeof(struct mech_list_item)); current = current->next; memcpy(¤t->element, &mech_list_arr[i], sizeof(MECH_LIST_ELEMENT)); } } struct mech_list_item * find_mech_list_item_for_type(CK_MECHANISM_TYPE type, struct mech_list_item *head) { struct mech_list_item *res; res = head->next; while (res) { if (res->element.mech_type == type) { goto out; } res = res->next; } out: return res; } void free_mech_list(struct mech_list_item *head) { struct mech_list_item *walker; walker = head->next; while (walker) { struct mech_list_item *next; next = walker->next; free(walker); walker = next; } } /** * If a type exists in the source that is not in the target, copy it * over. If a type exists in both the source and the target, overwrite * the target. */ void merge_mech_lists(struct mech_list_item *head_of_target, struct mech_list_item *head_of_source) { } CK_RV ock_generic_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { int rc = CKR_OK; unsigned int i; if (pMechanismList == NULL) { (*pulCount) = mech_list_len; goto out; } if ((*pulCount) < mech_list_len) { (*pulCount) = mech_list_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; goto out; } for (i=0; i < mech_list_len; i++) pMechanismList[i] = mech_list[i].mech_type; (*pulCount) = mech_list_len; out: return rc; } CK_RV ock_generic_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { int rc = CKR_OK; unsigned int i; for (i=0; i < mech_list_len; i++) { if (mech_list[i].mech_type == type) { memcpy(pInfo, &mech_list[i].mech_info, sizeof(CK_MECHANISM_INFO)); goto out; } } TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; out: return rc; } /* * For Netscape we want to not support the SSL3 mechs since the native * ones perform much better. Force those slots to be RSA... it's ugly * but it works. */ static void netscape_hack(CK_MECHANISM_TYPE_PTR mech_arr_ptr, CK_ULONG count) { char *envrn; CK_ULONG i; if ((envrn = getenv("NS_SERVER_HOME")) != NULL) { for (i = 0; i < count; i++) { switch (mech_arr_ptr[i]) { case CKM_SSL3_PRE_MASTER_KEY_GEN: case CKM_SSL3_MASTER_KEY_DERIVE: case CKM_SSL3_KEY_AND_MAC_DERIVE: case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: mech_arr_ptr[i] = CKM_RSA_PKCS; break; } } } } void mechanism_list_transformations(CK_MECHANISM_TYPE_PTR mech_arr_ptr, CK_ULONG_PTR count_ptr) { netscape_hack(mech_arr_ptr, (*count_ptr)); } opencryptoki+dfsg/usr/lib/pkcs11/common/defs.h0000755000175000017500000004462612630407154020361 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/lib/pkcs11/common/defs.h,v 1.5 2008/07/16 22:27:48 mhalcrow Exp $ */ // /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: defs.h // // Contains various definitions needed by both the host-side // and coprocessor-side code. // #ifndef _DEFS_H #define _DEFS_H #define MAX_SESSION_COUNT 64 #define MAX_PIN_LEN 8 #define MIN_PIN_LEN 4 #define MAX_SLOT_ID 10 #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif // the following constants are used for sccSignOn // #define PKCS_11_PRG_ID "pkcs11 2.01" #define PKCS_11_DEVELOPER_ID 0xE #define PKCS_11_VERSION 1 #define PKCS_11_INSTANCE 0 #define PKCS_11_QUEUE 0 // the following are "boolean" attributes // #define CKA_IBM_TWEAK_ALLOW_KEYMOD 0x80000001 #define CKA_IBM_TWEAK_ALLOW_WEAK_DES 0x80000002 #define CKA_IBM_TWEAK_DES_PARITY_CHK 0x80000003 #define CKA_IBM_TWEAK_NETSCAPE 0x80000004 #define MODE_COPY (1 << 0) #define MODE_CREATE (1 << 1) #define MODE_KEYGEN (1 << 2) #define MODE_MODIFY (1 << 3) #define MODE_DERIVE (1 << 4) #define MODE_UNWRAP (1 << 5) // RSA block formatting types // #define PKCS_BT_1 1 #define PKCS_BT_2 2 #define OP_ENCRYPT_INIT 1 #define OP_DECRYPT_INIT 2 #define OP_WRAP 3 #define OP_UNWRAP 4 #define OP_SIGN_INIT 5 #define OP_VERIFY_INIT 6 // saved-state identifiers // enum { STATE_INVALID = 0, STATE_ENCR, STATE_DECR, STATE_DIGEST, STATE_SIGN, STATE_VERIFY }; #define ENCRYPT 1 #define DECRYPT 0 #define MAX_RSA_KEYLEN 512 #define MAX_AES_KEY_SIZE 64 /* encompasses CCA key size */ #define AES_KEY_SIZE_256 32 #define AES_KEY_SIZE_192 24 #define AES_KEY_SIZE_128 16 #define AES_BLOCK_SIZE 16 #define AES_INIT_VECTOR_SIZE AES_BLOCK_SIZE #define AES_COUNTER_SIZE 16 #define MAX_DES_KEY_SIZE 64 /* encompasses CCA key size */ #define DES_KEY_SIZE 8 #define DES_BLOCK_SIZE 8 /* * It should be able to keep any kind of key (AES, 3DES, etc) and also * a PBKDF key */ #define MAX_KEY_SIZE 96 #define SHA1_HASH_SIZE 20 #define SHA1_BLOCK_SIZE 64 #define SHA1_BLOCK_SIZE_MASK (SHA1_BLOCK_SIZE - 1) #define SHA2_HASH_SIZE 32 #define SHA2_BLOCK_SIZE 64 #define SHA2_BLOCK_SIZE_MASK (SHA2_BLOCK_SIZE - 1) #define SHA3_HASH_SIZE 48 #define SHA3_BLOCK_SIZE 128 #define SHA3_BLOCK_SIZE_MASK (SHA3_BLOCK_SIZE - 1) #define SHA5_HASH_SIZE 64 #define SHA5_BLOCK_SIZE 128 #define SHA5_BLOCK_SIZE_MASK (SHA5_BLOCK_SIZE - 1) #define MAX_SHA_HASH_SIZE SHA5_HASH_SIZE #define MAX_SHA_BLOCK_SIZE SHA5_BLOCK_SIZE #ifndef PATH_MAX #define PATH_MAX 4096 #endif struct oc_sha_ctx { unsigned char hash[MAX_SHA_HASH_SIZE + 1]; unsigned int hash_len; unsigned int hash_blksize; unsigned int tail_len; int message_part; unsigned char tail[MAX_SHA_BLOCK_SIZE]; void *dev_ctx; }; #define MD2_HASH_SIZE 16 #define MD2_BLOCK_SIZE 48 #define MD5_HASH_SIZE 16 #define MD5_BLOCK_SIZE 64 #define DSA_SIGNATURE_SIZE 40 #define DEFAULT_SO_PIN "87654321" #define MAX_TOK_OBJS 2048 typedef enum { ALL = 1, PRIVATE, PUBLIC } SESS_OBJ_TYPE; typedef struct _DL_NODE { struct _DL_NODE *next; struct _DL_NODE *prev; void *data; } DL_NODE; // Token local // #define PK_LITE_DIR token_specific.token_directory #define PK_DIR PK_LITE_DIR #define SUB_DIR token_specific.token_subdir #define DBGTAG token_specific.token_debug_tag #define PK_LITE_NV "NVTOK.DAT" #define PK_LITE_OBJ_DIR "TOK_OBJ" #define PK_LITE_OBJ_IDX "OBJ.IDX" #define DEL_CMD "/bin/rm -f" #endif opencryptoki+dfsg/usr/lib/pkcs11/common/mech_rng.c0000755000175000017500000004002712630407154021204 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: mech_rng.c // // Mechanisms for Random Numbers // // PKCS #11 doesn't consider random number generator to be a "mechanism" // #include // for memcmp() et al #include #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "tok_specific.h" #include "trace.h" // // CK_RV local_rng(CK_BYTE *output, CK_ULONG bytes) { int ranfd; int rlen; unsigned int totallen=0; ranfd = open("/dev/urandom",O_RDONLY); if (ranfd >= 0 ) { do { rlen = read(ranfd, output+totallen, bytes-totallen); totallen += rlen; } while( totallen < bytes); close(ranfd); return CKR_OK; } else { return CKR_FUNCTION_FAILED; } } // // CK_RV rng_generate( CK_BYTE *output, CK_ULONG bytes ) { CK_RV rc; /* Do token specific rng if it exists. */ if (token_specific.t_rng != NULL) rc = token_specific.t_rng(output, bytes); else rc = local_rng(output, bytes); if (rc != CKR_OK) TRACE_DEVEL("Token specific rng failed.\n"); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/common/mech_ec.c0000644000175000017500000003717312630407154021012 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * openCryptoki CCA token * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2006 * */ // File: mech_ec.c // // Mechanisms for Elliptic Curve (EC) // #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" #include "tok_specific.h" #include "ec_defs.h" CK_BYTE brainpoolP160r1[] = { 0x06,0x09,0x2B,0x24,0x03,0x03,0x02,0x08, 0x01,0x01,0x01 }; CK_BYTE brainpoolP192r1[] = { 0x06,0x09,0x2B,0x24,0x03,0x03,0x02,0x08, 0x01,0x01,0x03 }; CK_BYTE brainpoolP224r1[] = { 0x06,0x09,0x2B,0x24,0x03,0x03,0x02,0x08, 0x01,0x01,0x05 }; CK_BYTE brainpoolP256r1[] = { 0x06,0x09,0x2B,0x24,0x03,0x03,0x02,0x08, 0x01,0x01,0x07 }; CK_BYTE brainpoolP320r1[] = { 0x06,0x09,0x2B,0x24,0x03,0x03,0x02,0x08, 0x01,0x01,0x09 }; CK_BYTE brainpoolP384r1[] = { 0x06,0x09,0x2B,0x24,0x03,0x03,0x02,0x08, 0x01,0x01,0x0B }; CK_BYTE brainpoolP512r1[] = { 0x06,0x09,0x2B,0x24,0x03,0x03,0x02,0x08, 0x01,0x01,0x0D }; CK_BYTE prime192[] = { 0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01 }; CK_BYTE secp224[] = { 0x06,0x05,0x2B,0x81,0x04,0x00,0x21 }; CK_BYTE prime256[] = { 0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07 }; CK_BYTE secp384[] = { 0x06,0x05,0x2B,0x81,0x04,0x00,0x22 }; CK_BYTE secp521[] = { 0x06,0x05,0x2B,0x81,0x04,0x00,0x23 }; struct _ec der_ec_supported[NUMEC] = { {BRAINPOOL_CURVE, CURVE160, sizeof(brainpoolP160r1), &brainpoolP160r1}, {BRAINPOOL_CURVE, CURVE192, sizeof(brainpoolP192r1), &brainpoolP192r1}, {BRAINPOOL_CURVE, CURVE224, sizeof(brainpoolP224r1), &brainpoolP224r1}, {BRAINPOOL_CURVE, CURVE256, sizeof(brainpoolP256r1), &brainpoolP256r1}, {BRAINPOOL_CURVE, CURVE320, sizeof(brainpoolP320r1), &brainpoolP320r1}, {BRAINPOOL_CURVE, CURVE384, sizeof(brainpoolP384r1), &brainpoolP384r1}, {BRAINPOOL_CURVE, CURVE512, sizeof(brainpoolP512r1), &brainpoolP512r1}, {PRIME_CURVE, CURVE192, sizeof(prime192), &prime192}, {PRIME_CURVE, CURVE224, sizeof(secp224), &secp224}, {PRIME_CURVE, CURVE256, sizeof(prime256), &prime256}, {PRIME_CURVE, CURVE384, sizeof(secp384), &secp384}, {PRIME_CURVE, CURVE521, sizeof(secp521), &secp521}, }; CK_RV get_ecsiglen(OBJECT *key_obj, CK_ULONG *size) { CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; int i; flag = template_attribute_find(key_obj->template, CKA_ECDSA_PARAMS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_ECDSA_PARAMS for the key.\n"); return CKR_FUNCTION_FAILED; } /* loop thru supported curves to find the size. * both pkcs#11v2.20 and CCA expect the signature length to be * twice the length of p. * (See EC Signatures in pkcs#11v2.20 and docs for CSNDDSG.) */ for (i = 0; i < NUMEC; i++) { if ((memcmp(attr->pValue, der_ec_supported[i].data, attr->ulValueLen) == 0)) { *size = der_ec_supported[i].len_bits; /* round up if necessary */ if ((*size % 8) == 0) *size = (*size / 8) * 2; else *size = ((*size / 8) + 1) * 2; TRACE_DEVEL("getlen, curve = %d, size = %lu\n", der_ec_supported[i].len_bits, *size); return CKR_OK; } } TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } CK_RV ckm_ec_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_RV rc; rc = token_specific.t_ec_generate_keypair(publ_tmpl, priv_tmpl); if (rc != CKR_OK) TRACE_ERROR("Key Generation failed\n"); return rc; } CK_RV ckm_ec_sign( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj ) { CK_ATTRIBUTE * attr = NULL; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_CLASS in the template\n"); return CKR_FUNCTION_FAILED; } else keyclass = *(CK_OBJECT_CLASS *)attr->pValue; // this had better be a private key // if (keyclass != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } rc = token_specific.t_ec_sign(in_data, in_data_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_DEVEL("EC Sign failed.\n"); return rc; } CK_RV ec_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; CK_ULONG plen; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = get_ecsiglen(key_obj, &plen); if (rc != CKR_OK) { TRACE_DEVEL("get_ecsiglen failed.\n"); return rc; } if (length_only == TRUE) { *out_data_len = plen; return CKR_OK; } if (*out_data_len < plen) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = ckm_ec_sign( in_data, in_data_len, out_data, out_data_len, key_obj ); return rc; } CK_RV ckm_ec_verify( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG out_data_len, OBJECT *key_obj ) { CK_ATTRIBUTE *attr = NULL; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_CLASS in the template\n"); return CKR_FUNCTION_FAILED; } else keyclass = *(CK_OBJECT_CLASS *)attr->pValue; // this had better be a public key // if (keyclass != CKO_PUBLIC_KEY){ TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } rc = token_specific.t_ec_verify(in_data, in_data_len, out_data, out_data_len, key_obj); if (rc != CKR_OK) TRACE_ERROR("Token specific ec verify failed.\n"); return rc; } CK_RV ec_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len ) { OBJECT *key_obj = NULL; CK_ULONG plen; CK_RV rc; rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = get_ecsiglen(key_obj, &plen); if (rc != CKR_OK) { TRACE_DEVEL("get_ecsiglen failed.\n"); return rc; } // check input data length restrictions // if (sig_len > plen){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } rc = ckm_ec_verify(in_data, in_data_len, signature, sig_len, key_obj); return rc; } CK_RV ec_hash_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len ) { CK_BYTE hash[SHA1_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT sign_ctx; CK_MECHANISM digest_mech; CK_MECHANISM sign_mech; CK_ULONG hash_len; CK_RV rc; if (!sess || !ctx || !in_data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset( &digest_ctx, 0x0, sizeof(digest_ctx) ); memset( &sign_ctx, 0x0, sizeof(sign_ctx) ); digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest( sess, length_only, &digest_ctx, in_data, in_data_len, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } sign_mech.mechanism = CKM_ECDSA; sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; rc = sign_mgr_init( sess, &sign_ctx, &sign_mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Sign Mgr Init failed.\n"); goto error; } rc = sign_mgr_sign( sess, length_only, &sign_ctx, hash, hash_len, signature, sig_len ); if (rc != CKR_OK) TRACE_DEVEL("Sign Mgr Sign failed.\n"); error: sign_mgr_cleanup( &sign_ctx ); return rc; } CK_RV ec_hash_sign_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { RSA_DIGEST_CONTEXT * context = NULL; CK_MECHANISM digest_mech; CK_RV rc; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (RSA_DIGEST_CONTEXT *)ctx->context; if (context->flag == FALSE) { digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &context->hash_context, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } context->flag = TRUE; } rc = digest_mgr_digest_update( sess, &context->hash_context, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } return CKR_OK; } CK_RV ec_hash_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG * sig_len ) { CK_BYTE hash[SHA1_HASH_SIZE]; RSA_DIGEST_CONTEXT * context = NULL; CK_ULONG hash_len; CK_MECHANISM sign_mech; SIGN_VERIFY_CONTEXT sign_ctx; CK_RV rc; if (!sess || !ctx || !sig_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset( &sign_ctx, 0x0, sizeof(sign_ctx)); context = (RSA_DIGEST_CONTEXT *)ctx->context; hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, length_only, &context->hash_context, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } sign_mech.mechanism = CKM_ECDSA; sign_mech.ulParameterLen = 0; sign_mech.pParameter = NULL; rc = sign_mgr_init( sess, &sign_ctx, &sign_mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } //rc = sign_mgr_sign( sess, length_only, &sign_ctx, ber_data, ber_data_len, signature, sig_len ); rc = sign_mgr_sign( sess, length_only, &sign_ctx, hash, hash_len, signature, sig_len ); if (rc != CKR_OK) TRACE_DEVEL("Sign Mgr Sign failed.\n"); if (length_only == TRUE || rc == CKR_BUFFER_TOO_SMALL) { sign_mgr_cleanup( &sign_ctx ); return rc; } done: sign_mgr_cleanup( &sign_ctx ); return rc; } CK_RV ec_hash_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { CK_BYTE hash[SHA1_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT verify_ctx; CK_MECHANISM digest_mech; CK_MECHANISM verify_mech; CK_ULONG hash_len; CK_RV rc; if (!sess || !ctx || !in_data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset( &digest_ctx, 0x0, sizeof(digest_ctx) ); memset( &verify_ctx, 0x0, sizeof(verify_ctx) ); digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest( sess, FALSE, &digest_ctx, in_data, in_data_len, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } // Verify the Signed BER-encoded Data block // verify_mech.mechanism = CKM_ECDSA; verify_mech.ulParameterLen = 0; verify_mech.pParameter = NULL; rc = verify_mgr_init( sess, &verify_ctx, &verify_mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; } //rc = verify_mgr_verify( sess, &verify_ctx, ber_data, ber_data_len, signature, sig_len ); rc = verify_mgr_verify( sess, &verify_ctx, hash, hash_len, signature, sig_len ); if (rc != CKR_OK) TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: sign_mgr_cleanup( &verify_ctx ); return rc; } CK_RV ec_hash_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { RSA_DIGEST_CONTEXT * context = NULL; CK_MECHANISM digest_mech; CK_RV rc; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (RSA_DIGEST_CONTEXT *)ctx->context; if (context->flag == FALSE) { digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &context->hash_context, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } context->flag = TRUE; } rc = digest_mgr_digest_update( sess, &context->hash_context, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } return CKR_OK; } CK_RV ec_hash_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len ) { CK_BYTE hash[SHA1_HASH_SIZE]; RSA_DIGEST_CONTEXT * context = NULL; CK_ULONG hash_len; CK_MECHANISM verify_mech; SIGN_VERIFY_CONTEXT verify_ctx; CK_RV rc; if (!sess || !ctx || !signature){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } memset( &verify_ctx, 0x0, sizeof(verify_ctx)); context = (RSA_DIGEST_CONTEXT *)ctx->context; hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &context->hash_context, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } verify_mech.mechanism = CKM_ECDSA; verify_mech.ulParameterLen = 0; verify_mech.pParameter = NULL; rc = verify_mgr_init( sess, &verify_ctx, &verify_mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Verify Mgr Init failed.\n"); goto done; } rc = verify_mgr_verify( sess, &verify_ctx, hash, hash_len, signature, sig_len ); if (rc != CKR_OK) TRACE_DEVEL("Verify Mgr Verify failed.\n"); done: verify_mgr_cleanup( &verify_ctx ); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/common/mech_md2.c0000755000175000017500000007036412630407154021107 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // Permutation of 0..255 constructed from the digits of pi. It gives a // "random" nonlinear byte substitution operation. // static CK_BYTE S[256] = { 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 }; static CK_BYTE *padding[] = { (CK_BYTE *)"", (CK_BYTE *)"\x01", (CK_BYTE *)"\x02\x02", (CK_BYTE *)"\x03\x03\x03", (CK_BYTE *)"\x04\x04\x04\x04", (CK_BYTE *)"\x05\x05\x05\x05\x05", (CK_BYTE *)"\x06\x06\x06\x06\x06\x06", (CK_BYTE *)"\x07\x07\x07\x07\x07\x07\x07", (CK_BYTE *)"\x08\x08\x08\x08\x08\x08\x08\x08", (CK_BYTE *)"\x09\x09\x09\x09\x09\x09\x09\x09\x09", (CK_BYTE *)"\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a", (CK_BYTE *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", (CK_BYTE *)"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", (CK_BYTE *)"\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d", (CK_BYTE *)"\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e", (CK_BYTE *)"\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f", (CK_BYTE *)"\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10" }; // // CK_RV md2_hash( SESSION * sess, CK_BBOOL length_only, DIGEST_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = MD2_HASH_SIZE; return CKR_OK; } rc = md2_hash_update( sess, ctx, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("md2_hash_update failed.\n"); return CKR_FUNCTION_FAILED; } return md2_hash_final( sess, FALSE, ctx, out_data, out_data_len ); } // // CK_RV md2_hash_update( SESSION * sess, DIGEST_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { if (!sess || !ctx || !in_data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } return ckm_md2_update( (MD2_CONTEXT *)ctx->context, in_data, in_data_len ); } // // CK_RV md2_hash_final( SESSION * sess, CK_BYTE length_only, DIGEST_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len ) { CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = MD2_HASH_SIZE; return CKR_OK; } rc = ckm_md2_final( (MD2_CONTEXT *)ctx->context, out_data, MD2_HASH_SIZE ); if (rc == CKR_OK) { *out_data_len = MD2_HASH_SIZE; return rc; } return rc; } // this routine gets called for two mechanisms actually: // CKM_MD2_HMAC // CKM_MD2_HMAC_GENERAL // CK_RV md2_hmac_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE hash[MD2_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[MD2_BLOCK_SIZE]; CK_BYTE k_opad[MD2_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_MD2_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return CKR_OK; } } else hmac_len = MD2_HASH_SIZE; if (length_only == TRUE) { *out_data_len = hmac_len; return CKR_OK; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else key_bytes = attr->ulValueLen; // build (K XOR ipad), (K XOR opad) // if (key_bytes > MD2_BLOCK_SIZE) { digest_mech.mechanism = CKM_MD2; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest( sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); for (i = 0; i < hash_len; i++) { k_ipad[i] = hash[i] ^ 0x36; k_opad[i] = hash[i] ^ 0x5C; } memset( &k_ipad[i], 0x36, MD2_BLOCK_SIZE - i); memset( &k_opad[i], 0x5C, MD2_BLOCK_SIZE - i); } else { CK_BYTE *key = (CK_BYTE *)attr + sizeof(CK_ATTRIBUTE); for (i = 0; i < key_bytes; i++) { k_ipad[i] = key[i] ^ 0x36; k_opad[i] = key[i] ^ 0x5C; } memset( &k_ipad[i], 0x36, MD2_BLOCK_SIZE - key_bytes ); memset( &k_opad[i], 0x5C, MD2_BLOCK_SIZE - key_bytes ); } digest_mech.mechanism = CKM_MD2; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, k_ipad, MD2_BLOCK_SIZE ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); // outer hash // rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, k_opad, MD2_BLOCK_SIZE ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, hash, hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memcpy( out_data, hash, hmac_len ); *out_data_len = hmac_len; return CKR_OK; } // // CK_RV md2_hmac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { CK_BYTE hmac[MD2_HASH_SIZE]; SIGN_VERIFY_CONTEXT hmac_ctx; CK_ULONG hmac_len, len; CK_RV rc; if (!sess || !ctx || !in_data || !signature){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_MD2_HMAC_GENERAL) hmac_len = *(CK_ULONG *)ctx->mech.pParameter; else hmac_len = MD2_HASH_SIZE; memset( &hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT) ); rc = sign_mgr_init( sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Sign Mgr Init failed.\n"); return rc; } len = sizeof(hmac); rc = sign_mgr_sign( sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len ); if (rc != CKR_OK){ TRACE_DEVEL("Sign Mgr Sign failed.\n"); return rc; } if ((len != hmac_len) || (len != sig_len)){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } if (memcmp(hmac, signature, hmac_len) != 0){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } return CKR_OK; } // // CKM routines // // MD2 block update operation. Continues an MD2 message-digest // operation, processing another message block, and updating the // context. // CK_RV ckm_md2_update( MD2_CONTEXT * context, CK_BYTE * input, CK_ULONG inputLen ) { CK_ULONG i, index, partLen; // Update number of bytes mod 16 // index = context->count; context->count = (index + inputLen) & 0xf; partLen = 16 - index; // Process any complete 16-byte blocks // if (inputLen >= partLen) { memcpy( (CK_BYTE *)&context->buffer[index], (CK_BYTE *)input, partLen ); ckm_md2_transform( context->state, context->checksum, context->buffer ); for (i = partLen; i + 15 < inputLen; i += 16) ckm_md2_transform( context->state, context->checksum, &input[i] ); index = 0; } else i = 0; // Buffer remaining input // memcpy( (CK_BYTE *)&context->buffer[index], (CK_BYTE *)&input[i], inputLen-i ); return CKR_OK; } // MD2 finalization. Ends an MD2 message-digest operation, writing the // message digest and zeroizing the context. // CK_RV ckm_md2_final( MD2_CONTEXT * context, CK_BYTE * out_data, CK_ULONG out_data_len ) { CK_ULONG index, padLen; if (!context || !out_data || (out_data_len < MD2_HASH_SIZE)){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // Pad input to 16-byte multiple (1 - 16 pad bytes) // index = context->count; padLen = 16 - index; ckm_md2_update( context, padding[padLen], padLen ); // Add checksum // ckm_md2_update( context, context->checksum, 16 ); // Store state in digest // memcpy( (CK_BYTE *)out_data, (CK_BYTE *)context->state, 16 ); return CKR_OK; } // MD2 basic transformation. Transforms state and updates checksum // based on block. // void ckm_md2_transform( CK_BYTE * state, CK_BYTE * checksum, CK_BYTE * block ) { CK_ULONG i, j, t; CK_BYTE x[48]; // Form encryption block from state, block, state ^ block. // memcpy( (CK_BYTE *)x, (CK_BYTE *)state, 16 ); memcpy( (CK_BYTE *)x+16, (CK_BYTE *)block, 16 ); for (i = 0; i < 16; i++) x[i+32] = state[i] ^ block[i]; // Encrypt block (18 rounds). // t = 0; for (i = 0; i < 18; i++) { for (j = 0; j < 48; j++) t = x[j] ^= S[t]; t = (t + i) & 0xff; } // Save new state // memcpy( (CK_BYTE *)state, (CK_BYTE *)x, 16 ); // Update checksum. // t = checksum[15]; for (i = 0; i < 16; i++) t = checksum[i] ^= S[block[i] ^ t]; } opencryptoki+dfsg/usr/lib/pkcs11/common/btree.c0000644000175000017500000001533712630407154020526 0ustar xnoxxnox /* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 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 * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ /* * btree.c * Author: Kent Yoder * * v1 Binary tree functions 4/5/2011 * */ #include #include #include "pkcs11types.h" #include "local_types.h" #include "trace.h" #define GET_NODE_HANDLE(n) get_node_handle(n, 1) #define TREE_DUMP(t) tree_dump((t)->top, 0) /* * bt_get_node * * Return a node of the tree @t with position @node_num. If the node has been freed * or doesn't exist, return NULL */ struct btnode * bt_get_node(struct btree *t, unsigned long node_num) { struct btnode *temp = t->top; unsigned long i; if (!node_num || node_num > t->size) return NULL; if (node_num == 1) { temp = t->top; goto done; } i = node_num; while (i != 1) { if (i & 1) { temp = temp->right; // If the bit is a 1, traverse right } else { temp = temp->left; // If the bit is a zero, traverse left } i >>= 1; } done: return ((temp->flags & BT_FLAG_FREE) ? NULL : temp); } void * bt_get_node_value(struct btree *t, unsigned long node_num) { struct btnode *n = bt_get_node(t, node_num); return ((n) ? n->value : NULL); } /* create a new node and set @parent_ptr to its location */ static struct btnode * node_create(struct btnode **child_ptr, struct btnode *parent_ptr, void *value) { struct btnode *node = malloc(sizeof(struct btnode)); if (!node) { TRACE_ERROR("malloc of %lu bytes failed", sizeof(struct btnode)); return NULL; } node->left = node->right = NULL; node->flags = 0; node->value = value; *child_ptr = node; node->parent = parent_ptr; return node; } /* * get_node_handle * * Recursively construct a node's handle by tracing its path back to the root node */ static unsigned long get_node_handle(struct btnode *node, unsigned long handle_so_far) { if (!node->parent) return handle_so_far; else if (node->parent->left == node) return get_node_handle(node->parent, handle_so_far << 1); else return get_node_handle(node->parent, (handle_so_far << 1) + 1); } /* return node number (handle) of newly created node, or 0 for failure */ unsigned long bt_node_add(struct btree *t, void *value) { struct btnode *temp = t->top; unsigned long new_node_index; if (!temp) { /* no root node yet exists, create it */ t->size = 1; if (!node_create(&t->top, NULL, value)) { TRACE_ERROR("Error creating node"); return 0; } return 1; } else if (t->free_list) { /* there's a node on the free list, use it instead of mallocing new */ temp = t->free_list; t->free_list = temp->value; temp->value = value; temp->flags &= (~BT_FLAG_FREE); t->free_nodes--; new_node_index = GET_NODE_HANDLE(temp); return new_node_index; } new_node_index = t->size + 1; while (new_node_index != 1) { if (new_node_index & 1) { if (!temp->right) { if (!(node_create(&temp->right, temp, value))) { TRACE_ERROR("node_create failed"); return 0; } break; } else { temp = temp->right; // If the bit is a 1, traverse right } } else { if (!temp->left) { if (!(node_create(&temp->left, temp, value))) { TRACE_ERROR("node_create failed"); return 0; } break; } else { temp = temp->left; // If the bit is a zero, traverse left } } new_node_index >>= 1; } t->size++; return t->size; } void tree_dump(struct btnode *n, int depth) { int i; if (!n) return; for (i = 0; i < depth; i++) printf(" "); if (n->flags & BT_FLAG_FREE) printf("`- (deleted node)\n"); else printf("`- %p\n", n->value); tree_dump(n->left, depth+1); tree_dump(n->right, depth+1); } /* * bt_node_free * * Move @node_num in tree @t to the free list, calling @delete_func on its value first. * * Note that bt_get_node will return NULL if the node is already on the free list, so * no double freeing can occur */ struct btnode * bt_node_free(struct btree *t, unsigned long node_num, void (*delete_func)(void *)) { struct btnode *node = bt_get_node(t, node_num); if (node) { if (delete_func) (*delete_func)(node->value); node->flags |= BT_FLAG_FREE; /* add node to the free list, which is chained by using the value pointer */ node->value = t->free_list; t->free_list = node; t->free_nodes++; } return node; } /* bt_is_empty * * return 0 if binary tree has at least 1 node in use, !0 otherwise */ int bt_is_empty(struct btree *t) { return (t->free_nodes == t->size); } /* bt_nodes_in_use * * return the number of nodes in the binary tree that are not free'd */ unsigned long bt_nodes_in_use(struct btree *t) { return (t->size - t->free_nodes); } /* bt_for_each_node * * For each non-free'd node in the tree, run @func on it * * @func: * p1 is the node's value * p2 is the node's handle * p3 is passed through this function for the caller */ void bt_for_each_node(struct btree *t, void (*func)(void *p1, unsigned long p2, void *p3), void *p3) { unsigned int i; struct btnode *node; for (i = 1; i < t->size+1; i++) { node = bt_get_node(t, i); if (node) { (*func)(node->value, i, p3); } } } /* bt_destroy * * Walk a binary tree backwards (largest index to smallest), deleting nodes along the way. * Call @func on node->value before freeing the node. */ void bt_destroy(struct btree *t, void (*func)(void *)) { unsigned long i; struct btnode *temp; while (t->size) { temp = t->top; i = t->size; while (i != 1) { if (i & 1) { temp = temp->right; // If the bit is a 1, traverse right } else { temp = temp->left; // If the bit is a zero, traverse left } i >>= 1; } /* * The value pointed by value in a node marked as freed points * to the next node element in free_list and it shouldn't be * freed here because the loop will iterate through each node, * freed or not. */ if (func && !(temp->flags & BT_FLAG_FREE)) (*func)(temp->value); free(temp); t->size--; } /* the tree is gone now, clear all the other variables */ t->top = NULL; t->free_list = NULL; t->free_nodes = 0; } opencryptoki+dfsg/usr/lib/pkcs11/common/key_mgr.c0000755000175000017500000013741312630407154021065 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ // File: key_mgr.c // #include #include #include // for memcmp() et al #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" static CK_BBOOL true = TRUE, false = FALSE; // // CK_RV key_mgr_generate_key( SESSION * sess, CK_MECHANISM * mech, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * new_attr = NULL; CK_ULONG i, keyclass, subclass = 0; CK_BBOOL flag; CK_RV rc; if (!sess || !mech || !handle){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (!pTemplate && (ulCount != 0)){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // it's silly but Cryptoki allows the user to specify the CKA_CLASS // in the template. so we have to iterate through the provided template // and make sure that if CKA_CLASS is CKO_SECRET_KEY, if it is present. // // it would have been more logical for Cryptoki to forbid specifying // the CKA_CLASS attribute when generating a key // for (i=0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { keyclass = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; if (keyclass != CKO_SECRET_KEY){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } if (pTemplate[i].type == CKA_KEY_TYPE) subclass = *(CK_ULONG *)pTemplate[i].pValue; } switch (mech->mechanism) { case CKM_DES_KEY_GEN: if (subclass != 0 && subclass != CKK_DES){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_DES; break; case CKM_DES3_KEY_GEN: if (subclass != 0 && subclass != CKK_DES3){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_DES3; break; #if !(NOCDMF) case CKM_CDMF_KEY_GEN: if (subclass != 0 && subclass != CKK_CDMF){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_CDMF; break; #endif case CKM_SSL3_PRE_MASTER_KEY_GEN: if (subclass != 0 && subclass != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } if (mech->ulParameterLen != sizeof(CK_VERSION)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } subclass = CKK_GENERIC_SECRET; break; case CKM_AES_KEY_GEN: if (subclass != 0 && subclass != CKK_AES){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_AES; break; case CKM_GENERIC_SECRET_KEY_GEN: if (subclass != 0 && subclass != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_GENERIC_SECRET; break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = object_mgr_create_skel( sess, pTemplate, ulCount, MODE_KEYGEN, CKO_SECRET_KEY, subclass, &key_obj ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_create_skel failed.\n"); goto error; } // at this point, 'key_obj' should contain a skeleton key. depending on // the key type, we may need to extract one or more attributes from // the object prior to generating the key data (ie. variable key length) // switch (mech->mechanism) { case CKM_DES_KEY_GEN: rc = ckm_des_key_gen( key_obj->template ); break; case CKM_DES3_KEY_GEN: rc = ckm_des3_key_gen( key_obj->template ); break; #if !(NOCDMF) case CKM_CDMF_KEY_GEN: rc = ckm_cdmf_key_gen( key_obj->template ); break; #endif case CKM_SSL3_PRE_MASTER_KEY_GEN: rc = ckm_ssl3_pre_master_key_gen( key_obj->template, mech ); break; #ifndef NOAES case CKM_AES_KEY_GEN: rc = ckm_aes_key_gen( key_obj->template ); break; #endif case CKM_GENERIC_SECRET_KEY_GEN: rc = ckm_generic_secret_key_gen( key_obj->template ); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } if (rc != CKR_OK){ TRACE_ERROR("Key generation failed.\n"); goto error; } // we can now set CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE // to their appropriate values. this only applies to CKO_SECRET_KEY // and CKO_PRIVATE_KEY objects // flag = template_attribute_find( key_obj->template, CKA_SENSITIVE, &attr ); if (flag == TRUE) { flag = *(CK_BBOOL *)attr->pValue; rc = build_attribute( CKA_ALWAYS_SENSITIVE, &flag, sizeof(CK_BBOOL), &new_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build attribute failed.\n"); goto error; } template_update_attribute( key_obj->template, new_attr ); } else { rc = CKR_FUNCTION_FAILED; TRACE_ERROR("Failed to find CKA_SENSITIVE in key object template.\n"); goto error; } flag = template_attribute_find( key_obj->template, CKA_EXTRACTABLE, &attr ); if (flag == TRUE) { flag = *(CK_BBOOL *)attr->pValue; rc = build_attribute( CKA_NEVER_EXTRACTABLE, &true, sizeof(CK_BBOOL), &new_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto error; } if (flag == TRUE) *(CK_BBOOL *)new_attr->pValue = FALSE; template_update_attribute( key_obj->template, new_attr ); } else { rc = CKR_FUNCTION_FAILED; TRACE_ERROR("Failed to find CKA_EXTRACTABLE in key object template.\n"); goto error; } // at this point, the key should be fully constructed...assign // an object handle and store the key // rc = object_mgr_create_final( sess, key_obj, handle ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_create_final failed.\n"); goto error; } return rc; error: if (key_obj) object_free( key_obj ); *handle = 0; return rc; } // // CK_RV key_mgr_generate_key_pair( SESSION * sess, CK_MECHANISM * mech, CK_ATTRIBUTE * publ_tmpl, CK_ULONG publ_count, CK_ATTRIBUTE * priv_tmpl, CK_ULONG priv_count, CK_OBJECT_HANDLE * publ_key_handle, CK_OBJECT_HANDLE * priv_key_handle ) { OBJECT * publ_key_obj = NULL; OBJECT * priv_key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * new_attr = NULL; CK_ULONG i, keyclass, subclass = 0; CK_BBOOL flag; CK_RV rc; if (!sess || !mech || !publ_key_handle || !priv_key_handle){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (!publ_tmpl && (publ_count != 0)){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (!priv_tmpl && (priv_count != 0)){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // it's silly but Cryptoki allows the user to specify the CKA_CLASS // in the template. so we have to iterate through the provided template // and make sure that if CKA_CLASS is valid, if it is present. // // it would have been more logical for Cryptoki to forbid specifying // the CKA_CLASS attribute when generating a key // for (i=0; i < publ_count; i++) { if (publ_tmpl[i].type == CKA_CLASS) { keyclass = *(CK_OBJECT_CLASS *)publ_tmpl[i].pValue; if (keyclass != CKO_PUBLIC_KEY){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } if (publ_tmpl[i].type == CKA_KEY_TYPE) subclass = *(CK_ULONG *)publ_tmpl[i].pValue; } for (i=0; i < priv_count; i++) { if (priv_tmpl[i].type == CKA_CLASS) { keyclass = *(CK_OBJECT_CLASS *)priv_tmpl[i].pValue; if (keyclass != CKO_PRIVATE_KEY){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } if (priv_tmpl[i].type == CKA_KEY_TYPE) { CK_ULONG temp = *(CK_ULONG *)priv_tmpl[i].pValue; if (temp != subclass){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } } switch (mech->mechanism) { case CKM_RSA_PKCS_KEY_PAIR_GEN: if (subclass != 0 && subclass != CKK_RSA){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_RSA; break; case CKM_EC_KEY_PAIR_GEN: if (subclass != 0 && subclass != CKK_EC){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_EC; break; #if !(NODSA) case CKM_DSA_KEY_PAIR_GEN: if (subclass != 0 && subclass != CKK_DSA){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_DSA; break; #endif /* Begin code contributed by Corrent corp. */ #if !(NODH) case CKM_DH_PKCS_KEY_PAIR_GEN: if (subclass != 0 && subclass != CKK_DH){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } subclass = CKK_DH; break; #endif /* End code contributed by Corrent corp. */ default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = object_mgr_create_skel( sess, publ_tmpl, publ_count, MODE_KEYGEN, CKO_PUBLIC_KEY, subclass, &publ_key_obj ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_create_skel failed.\n"); goto error; } rc = object_mgr_create_skel( sess, priv_tmpl, priv_count, MODE_KEYGEN, CKO_PRIVATE_KEY, subclass, &priv_key_obj ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_create_skel failed.\n"); goto error; } // at this point, 'key_obj' should contain a skeleton key. depending on // the key type, we may need to extract one or more attributes from // the object prior to generating the key data (ie. variable key length) // switch (mech->mechanism) { case CKM_RSA_PKCS_KEY_PAIR_GEN: rc = ckm_rsa_key_pair_gen( publ_key_obj->template, priv_key_obj->template ); break; case CKM_EC_KEY_PAIR_GEN: rc = ckm_ec_key_pair_gen( publ_key_obj->template, priv_key_obj->template ); break; #if !(NODSA) case CKM_DSA_KEY_PAIR_GEN: rc = ckm_dsa_key_pair_gen( publ_key_obj->template, priv_key_obj->template ); break; #endif /* Begin code contributed by Corrent corp. */ #if !(NODH) case CKM_DH_PKCS_KEY_PAIR_GEN: rc = ckm_dh_pkcs_key_pair_gen( publ_key_obj->template, priv_key_obj->template ); break; #endif /* End code contributed by Corrent corp. */ default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; break; } if (rc != CKR_OK){ TRACE_DEVEL("Key Generation failed.\n"); goto error; } // we can now set CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE // to their appropriate values. this only applies to CKO_SECRET_KEY // and CKO_PRIVATE_KEY objects // flag = template_attribute_find( priv_key_obj->template, CKA_SENSITIVE, &attr ); if (flag == TRUE) { flag = *(CK_BBOOL *)attr->pValue; rc = build_attribute( CKA_ALWAYS_SENSITIVE, &flag, sizeof(CK_BBOOL), &new_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed.\n"); goto error; } template_update_attribute( priv_key_obj->template, new_attr ); } else { TRACE_ERROR("Failed to find CKA_SENSITIVE in key object template.\n"); rc = CKR_FUNCTION_FAILED; goto error; } flag = template_attribute_find( priv_key_obj->template, CKA_EXTRACTABLE, &attr ); if (flag == TRUE) { flag = *(CK_BBOOL *)attr->pValue; rc = build_attribute( CKA_NEVER_EXTRACTABLE, &true, sizeof(CK_BBOOL), &new_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed.\n"); goto error; } if (flag == TRUE) *(CK_BBOOL *)new_attr->pValue = false; template_update_attribute( priv_key_obj->template, new_attr ); } else { TRACE_ERROR("Failed to find CKA_EXTRACTABLE in key object template.\n"); rc = CKR_FUNCTION_FAILED; goto error; } // at this point, the keys should be fully constructed...assign // object handles and store the keys // rc = object_mgr_create_final( sess, publ_key_obj, publ_key_handle ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_create_final failed.\n"); goto error; } rc = object_mgr_create_final( sess, priv_key_obj, priv_key_handle ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_create_final failed.\n"); // just calling object_free in the error path below would lead to a double // free error on session close - KEY 09/26/07 object_mgr_destroy_object( sess, *publ_key_handle ); publ_key_obj = NULL; goto error; } return rc; error: if (publ_key_obj) object_free( publ_key_obj ); if (priv_key_obj) object_free( priv_key_obj ); *publ_key_handle = 0; *priv_key_handle = 0; return rc; } // // CK_RV key_mgr_wrap_key( SESSION * sess, CK_BBOOL length_only, CK_MECHANISM * mech, CK_OBJECT_HANDLE h_wrapping_key, CK_OBJECT_HANDLE h_key, CK_BYTE * wrapped_key, CK_ULONG * wrapped_key_len ) { ENCR_DECR_CONTEXT * ctx = NULL; OBJECT * key1_obj = NULL; OBJECT * key2_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * data = NULL; CK_ULONG data_len; CK_OBJECT_CLASS class; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; if (!sess || !wrapped_key_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( h_wrapping_key, &key1_obj ); if (rc != CKR_OK){ TRACE_ERROR("%s\n", ock_err(ERR_WRAPPING_KEY_HANDLE_INVALID)); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_WRAPPING_KEY_HANDLE_INVALID; else return rc; } rc = object_mgr_find_in_map1( h_key, &key2_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } // is the key-to-be-wrapped EXTRACTABLE? // rc = template_attribute_find( key2_obj->template, CKA_EXTRACTABLE, &attr ); if (rc == FALSE){ TRACE_ERROR("Failed to find CKA_EXTRACTABLE in key template.\n"); return CKR_KEY_NOT_WRAPPABLE; // could happen if user tries to wrap a public key } else { flag = *(CK_BBOOL *)attr->pValue; if (flag == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_UNEXTRACTABLE)); return CKR_KEY_UNEXTRACTABLE; } } // what kind of key are we trying to wrap? make sure the mechanism is // allowed to wrap this kind of key // rc = template_attribute_find( key2_obj->template, CKA_CLASS, &attr ); if (rc == FALSE) { TRACE_DEVEL("CKA_CLASS is missing for key to be wrapped.\n"); return CKR_KEY_NOT_WRAPPABLE; } else class = *(CK_OBJECT_CLASS *)attr->pValue; // pkcs11v2-20rc3, page 178 // C_WrapKey can be used in following situations: // - To wrap any secret key with a public key that supports encryption // and decryption. // - To wrap any secret key with any other secret key. Consideration // must be given to key size and mechanism strength or the token may // not allow the operation. // - To wrap a private key with any secret key. // // These can be deduced to: // A public key or a secret key can be used to wrap a secret key. // A secret key can be used to wrap a private key. switch (mech->mechanism) { #if !(NOCDMF) case CKM_CDMF_CBC: case CKM_CDMF_CBC_PAD: #endif case CKM_DES_CBC: case CKM_DES3_ECB: case CKM_DES3_CBC: case CKM_AES_CTR: case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_AES_CBC_PAD: case CKM_AES_OFB: case CKM_AES_CFB8: case CKM_AES_CFB64: case CKM_AES_CFB128: if ((class != CKO_SECRET_KEY) && (class != CKO_PRIVATE_KEY)) { TRACE_ERROR("Specified mechanism only wraps secret & private keys.\n"); return CKR_KEY_NOT_WRAPPABLE; } break; case CKM_CDMF_ECB: case CKM_DES_ECB: case CKM_AES_ECB: case CKM_AES_CBC: case CKM_RSA_PKCS_OAEP: case CKM_RSA_PKCS: case CKM_RSA_X_509: if (class != CKO_SECRET_KEY){ TRACE_ERROR("Specified mechanism only wraps secret keys.\n"); return CKR_KEY_NOT_WRAPPABLE; } break; default: TRACE_ERROR("The mechanism does not support wrapping keys.\n"); return CKR_MECHANISM_INVALID; } // extract the secret data to be wrapped // rc = template_attribute_find( key2_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Failed to find CKA_KEY_TYPE in key template.\n"); return CKR_KEY_NOT_WRAPPABLE; } else keytype = *(CK_KEY_TYPE *)attr->pValue; switch (keytype) { #if !(NOCDMF) case CKK_CDMF: #endif case CKK_DES: rc = des_wrap_get_data( key2_obj->template, length_only, &data, &data_len ); if (rc != CKR_OK){ TRACE_DEVEL("des_wrap_get_data failed.\n"); return rc; } break; case CKK_DES3: rc = des3_wrap_get_data( key2_obj->template, length_only, &data, &data_len ); if (rc != CKR_OK){ TRACE_DEVEL("des3_wrap_get_data failed.\n"); return rc; } break; case CKK_RSA: rc = rsa_priv_wrap_get_data( key2_obj->template, length_only, &data, &data_len ); if (rc != CKR_OK){ TRACE_DEVEL("rsa_priv_wrap_get_data failed.\n"); return rc; } break; #if !(NODSA) case CKK_DSA: rc = dsa_priv_wrap_get_data( key2_obj->template, length_only, &data, &data_len ); if (rc != CKR_OK){ TRACE_DEVEL("dsa_priv_wrap_get_data failed.\n"); return rc; } break; #endif case CKK_GENERIC_SECRET: rc = generic_secret_wrap_get_data( key2_obj->template, length_only, &data, &data_len ); if (rc != CKR_OK){ TRACE_DEVEL("generic_secret_wrap_get_data failed.\n"); return rc; } break; #ifndef NOAES case CKK_AES: rc = aes_wrap_get_data( key2_obj->template, length_only, &data, &data_len ); if (rc != CKR_OK){ TRACE_DEVEL("aes_wrap_get_data failed.\n"); return rc; } break; #endif default: TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE)); return CKR_KEY_NOT_WRAPPABLE; } // we might need to format the wrapped data based on the mechanism // switch (mech->mechanism) { #if !(NOCMF) case CKM_CDMF_ECB: case CKM_CDMF_CBC: #endif case CKM_DES_ECB: case CKM_DES_CBC: case CKM_DES3_ECB: case CKM_DES3_CBC: rc = ckm_des_wrap_format( length_only, &data, &data_len ); if (rc != CKR_OK) { TRACE_DEVEL("ckm_des_wrap_format failed.\n"); if (data) free( data ); return rc; } break; #ifndef NOAES case CKM_AES_ECB: case CKM_AES_CBC: case CKM_AES_CTR: case CKM_AES_OFB: case CKM_AES_CFB8: case CKM_AES_CFB64: case CKM_AES_CFB128: rc = ckm_aes_wrap_format( length_only, &data, &data_len ); if (rc != CKR_OK) { TRACE_DEVEL("ckm_aes_wrap_format failed.\n"); if (data) free( data ); return rc; } break; #endif #if !(NOCMF) case CKM_CDMF_CBC_PAD: #endif case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_AES_CBC_PAD: // these mechanisms pad themselves // break; case CKM_RSA_PKCS_OAEP: case CKM_RSA_PKCS: case CKM_RSA_X_509: break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof(ENCR_DECR_CONTEXT)); if (!ctx){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx, 0x0, sizeof(ENCR_DECR_CONTEXT) ); // prepare to do the encryption // rc = encr_mgr_init( sess, ctx, OP_WRAP, mech, h_wrapping_key ); if (rc != CKR_OK){ TRACE_DEVEL("encr_mgr_init failed.\n"); free( ctx ); return rc; } // do the encryption and clean up. at this point, 'value' may or may not // be NULL depending on 'length_only' // rc = encr_mgr_encrypt( sess, length_only, ctx, data, data_len, wrapped_key, wrapped_key_len ); if (data != NULL){ free( data ); } encr_mgr_cleanup( ctx ); free( ctx ); return rc; } // // CK_RV key_mgr_unwrap_key( SESSION * sess, CK_MECHANISM * mech, CK_ATTRIBUTE * attributes, CK_ULONG attrib_count, CK_BYTE * wrapped_key, CK_ULONG wrapped_key_len, CK_OBJECT_HANDLE h_unwrapping_key, CK_OBJECT_HANDLE * h_unwrapped_key ) { ENCR_DECR_CONTEXT * ctx = NULL; OBJECT * key_obj = NULL, * tmp_obj = NULL; CK_BYTE * data = NULL; CK_ULONG data_len; CK_ULONG keyclass = 0, keytype = 0; CK_ULONG i; CK_BBOOL found_class, found_type, fromend, isopaque = FALSE; CK_RV rc; CK_ATTRIBUTE * attr = NULL; if (!sess || !wrapped_key || !h_unwrapped_key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( h_unwrapping_key, &tmp_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_WRAPPING_KEY_HANDLE_INVALID; else return rc; } if (template_attribute_find(tmp_obj->template, CKA_IBM_OPAQUE, &attr) == TRUE) isopaque = TRUE; found_class = FALSE; found_type = FALSE; /* * pkcs11v2-20 * C_WrapKey can be used in following situations: * - To wrap any secret key with a public key that supports encryption * and decryption. * - To wrap any secret key with any other secret key. Consideration * must be given to key size and mechanism strength or the token may * not allow the operation. * - To wrap a private key with any secret key. * * extract key type and key class from the passed in attributes */ for (i=0; i < attrib_count; i++) { switch (attributes[i].type) { case CKA_CLASS: keyclass = *(CK_OBJECT_CLASS *)attributes[i].pValue; found_class = TRUE; break; case CKA_KEY_TYPE: keytype = *(CK_KEY_TYPE *)attributes[i].pValue; found_type = TRUE; break; } } // we need both key class and key type in template. // we can be a bit lenient for private key since can extract key type // from BER-encoded information. if (found_class == FALSE || (found_type == FALSE && keyclass != CKO_PRIVATE_KEY)) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } switch (mech->mechanism) { case CKM_CDMF_ECB: case CKM_DES_ECB: case CKM_AES_ECB: case CKM_AES_CBC: case CKM_RSA_PKCS_OAEP: case CKM_RSA_PKCS: case CKM_RSA_X_509: if (keyclass != CKO_SECRET_KEY){ TRACE_ERROR("The specified mechanism unwraps secret keys only.\n"); return CKR_ARGUMENTS_BAD; } break; #if !(NOCMF) case CKM_CDMF_CBC: case CKM_CDMF_CBC_PAD: #endif case CKM_DES_CBC: case CKM_DES3_ECB: case CKM_DES3_CBC: case CKM_AES_CTR: case CKM_AES_OFB: case CKM_AES_CFB8: case CKM_AES_CFB64: case CKM_AES_CFB128: case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_AES_CBC_PAD: if ((keyclass != CKO_SECRET_KEY) && (keyclass != CKO_PRIVATE_KEY)) { TRACE_ERROR("Specified mech unwraps secret & private keys only.\n"); return CKR_ARGUMENTS_BAD; } break; default: TRACE_ERROR("The specified mechanism cannot unwrap keys.\n"); return CKR_MECHANISM_INVALID; } // looks okay... do the decryption ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof(ENCR_DECR_CONTEXT)); if (!ctx){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx, 0x0, sizeof(ENCR_DECR_CONTEXT) ); rc = decr_mgr_init( sess, ctx, OP_UNWRAP, mech, h_unwrapping_key ); if (rc != CKR_OK) return rc; rc = decr_mgr_decrypt( sess, TRUE, ctx, wrapped_key, wrapped_key_len, data, &data_len ); if (rc != CKR_OK){ TRACE_DEVEL("decr_mgr_decrypt failed.\n"); goto error; } data = (CK_BYTE *)malloc(data_len); if (!data) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto error; } rc = decr_mgr_decrypt( sess, FALSE, ctx, wrapped_key, wrapped_key_len, data, &data_len ); decr_mgr_cleanup( ctx ); free( ctx ); if (rc != CKR_OK){ TRACE_DEVEL("decr_mgr_decrypt failed.\n"); goto error; } // if we use X.509, the data will be padded from the front with zeros. // PKCS #11 specifies that for this mechanism, CK_VALUE is to be read // from the end of the data. // // Note: the PKCS #11 reference implementation gets this wrong. // if (mech->mechanism == CKM_RSA_X_509) fromend = TRUE; else fromend = FALSE; // extract the key type from the PrivateKeyInfo::AlgorithmIndicator // if (keyclass == CKO_PRIVATE_KEY) { rc = key_mgr_get_private_key_type( data, data_len, &keytype ); if (rc != CKR_OK){ TRACE_DEVEL("key_mgr_get_private_key_type failed.\n"); goto error; } } // we have decrypted the wrapped key data. we also // know what type of key it is. now we need to construct a new key // object... // rc = object_mgr_create_skel( sess, attributes, attrib_count, MODE_UNWRAP, keyclass, keytype, &key_obj ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_create_skel failed.\n"); goto error; } // at this point, 'key_obj' should contain a skeleton key. depending on // the key type. we're now ready to plug in the decrypted key data. // in some cases, the data will be BER-encoded so we'll need to decode it. // // this routine also ensires that CKA_EXTRACTABLE == FALSE, // CKA_ALWAYS_SENSITIVE == FALSE and CKA_LOCAL == FALSE // switch (keyclass) { case CKO_SECRET_KEY: rc = secret_key_unwrap(key_obj->template, keytype, data, data_len, fromend,isopaque); break; case CKO_PRIVATE_KEY: rc = priv_key_unwrap( key_obj->template, keytype, data, data_len, isopaque ); break; default: rc = CKR_WRAPPED_KEY_INVALID; break; } if (rc != CKR_OK){ TRACE_DEVEL("key_unwrap failed.\n"); goto error; } // at this point, the key should be fully constructed...assign // an object handle and store the key // rc = object_mgr_create_final( sess, key_obj, h_unwrapped_key ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_create_final failed.\n"); goto error; } if (data) free(data); return rc; error: if (key_obj) object_free( key_obj ); if (data) free(data); return rc; } CK_RV key_mgr_get_private_key_type( CK_BYTE *keydata, CK_ULONG keylen, CK_KEY_TYPE *keytype ) { CK_BYTE *alg = NULL; CK_BYTE *priv_key = NULL; CK_ULONG alg_len; CK_RV rc; rc = ber_decode_PrivateKeyInfo( keydata, keylen, &alg, &alg_len, &priv_key ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_PrivateKeyInfo failed.\n"); return rc; } // check the entire AlgorithmIdentifier for RSA // if (alg_len >= ber_rsaEncryptionLen) { if (memcmp(alg, ber_rsaEncryption, ber_rsaEncryptionLen) == 0) { *keytype = CKK_RSA; return CKR_OK; } } // Check only the OBJECT IDENTIFIER for DSA // if (alg_len >= ber_idDSALen) { if (memcmp(alg, ber_idDSA, ber_idDSALen) == 0) { *keytype = CKK_DSA; return CKR_OK; } } TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } // // CK_RV key_mgr_derive_key( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_OBJECT_HANDLE * derived_key, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ) { if (!sess || !mech){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (!pTemplate && (ulCount != 0)){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } switch (mech->mechanism) { case CKM_SSL3_MASTER_KEY_DERIVE: { if (!derived_key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } return ssl3_master_key_derive( sess, mech, base_key, pTemplate, ulCount, derived_key ); } break ; case CKM_SSL3_KEY_AND_MAC_DERIVE: { return ssl3_key_and_mac_derive( sess, mech, base_key, pTemplate, ulCount ); } break ; /* Begin code contributed by Corrent corp. */ #ifndef NODH case CKM_DH_PKCS_DERIVE: { if (!derived_key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } return dh_pkcs_derive( sess, mech, base_key, pTemplate, ulCount, derived_key ); } break ; #endif /* End code contributed by Corrent corp. */ default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } } opencryptoki+dfsg/usr/lib/pkcs11/common/tok_spec_struct.h0000755000175000017500000005444312630407154022651 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/lib/pkcs11/common/tok_spec_struct.h,v 1.5 2008/07/16 22:27:48 mhalcrow Exp $ */ // /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002,2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ #ifndef _TOK_SPECIFIC_STRUCT #define _TOK_SPECIFIC_STRUCT struct token_specific_struct { // Used to be in the token_local.h as a #def CK_BYTE token_directory[PATH_MAX]; // Subdirectory CK_BYTE token_subdir[PATH_MAX]; // Set to keysize for secure key tokens int token_keysize; // Information about how token's data should be stored. struct { // Use a separate directory for each user CK_BBOOL per_user; // Use data store? CK_BBOOL use_master_key; // Algorithm used to store private data (should be one of the // CKM_* macros). CK_MECHANISM_TYPE encryption_algorithm; // Default Initialization vectors used for each token. Its size // depends on the used algorithm. CK_BYTE *pin_initial_vector; CK_BYTE *obj_initial_vector; } data_store; // Create lockfile if different from standard way. int (*t_creatlock) (void); // Create or attach to token's shared memory CK_RV (*t_attach_shm) (CK_SLOT_ID slot_id, LW_SHM_TYPE **shmem); // Initialization function CK_RV(*t_init) (CK_SLOT_ID, char *); // Token data functions CK_RV (*t_init_token_data) (CK_SLOT_ID slot_id); CK_RV (*t_load_token_data) (CK_SLOT_ID slot_id, FILE *fh); CK_RV (*t_save_token_data) (CK_SLOT_ID slot_id, FILE *fh); // Random Number Gen CK_RV(*t_rng) (CK_BYTE *, CK_ULONG); // any specific final code CK_RV(*t_final) (); CK_RV(*t_init_token) (CK_SLOT_ID, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR); CK_RV(*t_login) (SESSION *, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG); CK_RV(*t_logout) (); CK_RV(*t_init_pin) (SESSION *, CK_CHAR_PTR, CK_ULONG); CK_RV(*t_set_pin) (SESSION *, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG); CK_RV(*t_des_key_gen) (CK_BYTE *, CK_ULONG, CK_ULONG); CK_RV(*t_des_ecb) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE); CK_RV(*t_des_cbc) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE *, CK_BYTE); CK_RV(*t_tdes_ecb) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE); CK_RV(*t_tdes_cbc) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE *, CK_BYTE); CK_RV(*t_tdes_ofb)(CK_BYTE *, CK_BYTE *, CK_ULONG, OBJECT *, CK_BYTE *, uint_32); CK_RV(*t_tdes_cfb)(CK_BYTE *, CK_BYTE *, CK_ULONG, OBJECT *, CK_BYTE *, uint_32, uint_32); CK_RV(*t_tdes_mac)(CK_BYTE *, CK_ULONG, OBJECT *, CK_BYTE *); CK_RV(*t_rsa_decrypt) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_rsa_encrypt) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_rsa_sign) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_rsa_verify) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *); CK_RV(*t_rsa_verify_recover) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_rsa_x509_decrypt) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_rsa_x509_encrypt) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_rsa_x509_sign) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_rsa_x509_verify) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *); CK_RV(*t_rsa_x509_verify_recover) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_rsa_oaep_decrypt) (ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE *, CK_ULONG); CK_RV(*t_rsa_oaep_encrypt) (ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE *, CK_ULONG); CK_RV(*t_rsa_pss_sign) (SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV(*t_rsa_pss_verify) (SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV(*t_rsa_generate_keypair) (TEMPLATE *, TEMPLATE *); CK_RV(*t_ec_sign) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV(*t_ec_verify) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *); CK_RV(*t_ec_generate_keypair) (TEMPLATE *, TEMPLATE *); /* Begin code contributed by Corrent corp. */ // Token Specific DH functions CK_RV(*t_dh_pkcs_derive) (CK_BYTE *, CK_ULONG *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV(*t_dh_pkcs_key_pair_gen) (TEMPLATE *, TEMPLATE *); /* End code contributed by Corrent corp. */ // Token Specific SHA1 functions CK_RV(*t_sha_init) (DIGEST_CONTEXT *, CK_MECHANISM *); CK_RV(*t_sha) (DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV(*t_sha_update) (DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV(*t_sha_final) (DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG *); // Token Specific HMAC CK_RV(*t_hmac_sign_init) (SESSION *, CK_MECHANISM *, CK_OBJECT_HANDLE); CK_RV(*t_hmac_sign) (SESSION *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV(*t_hmac_sign_update) (SESSION *, CK_BYTE *, CK_ULONG); CK_RV(*t_hmac_sign_final) (SESSION *, CK_BYTE *, CK_ULONG *); CK_RV(*t_hmac_verify_init) (SESSION *, CK_MECHANISM *, CK_OBJECT_HANDLE); CK_RV(*t_hmac_verify) (SESSION *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV(*t_hmac_verify_update) (SESSION *, CK_BYTE *, CK_ULONG); CK_RV(*t_hmac_verify_final) (SESSION *, CK_BYTE *, CK_ULONG); CK_RV (*t_generic_secret_key_gen) (TEMPLATE *); // Token Specific AES functions CK_RV(*t_aes_key_gen) (CK_BYTE *, CK_ULONG, CK_ULONG); CK_RV(*t_aes_ecb) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE); CK_RV(*t_aes_cbc) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE *, CK_BYTE); CK_RV(*t_aes_ctr) (CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE *, CK_ULONG, CK_BYTE); CK_RV(*t_aes_gcm_init) (SESSION *, ENCR_DECR_CONTEXT *, CK_MECHANISM *, CK_OBJECT_HANDLE, CK_BYTE); CK_RV(*t_aes_gcm) (SESSION *, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE); CK_RV(*t_aes_gcm_update) (SESSION *, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE); CK_RV(*t_aes_gcm_final) (SESSION *, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG *, CK_BYTE); CK_RV(*t_aes_ofb)(CK_BYTE *, CK_ULONG, CK_BYTE *, OBJECT *, CK_BYTE *, uint_32); CK_RV(*t_aes_cfb)(CK_BYTE *, CK_ULONG, CK_BYTE *, OBJECT *, CK_BYTE *, uint_32 , uint_32); CK_RV(*t_aes_mac)(CK_BYTE *, CK_ULONG, OBJECT *, CK_BYTE *); // Token Specific DSA functions CK_RV(*t_dsa_generate_keypair) (TEMPLATE *, TEMPLATE *); CK_RV(*t_dsa_sign) (CK_BYTE *, CK_BYTE *, OBJECT *); CK_RV(*t_dsa_verify) (CK_BYTE *, CK_BYTE *, OBJECT *); CK_RV(*t_get_mechanism_list) (CK_MECHANISM_TYPE_PTR, CK_ULONG_PTR); CK_RV(*t_get_mechanism_info) (CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); CK_RV (*t_object_add)(OBJECT *); }; typedef struct token_specific_struct token_spec_t; #endif opencryptoki+dfsg/usr/lib/pkcs11/common/ec_defs.h0000644000175000017500000000234712630407154021017 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * openCryptoki * * (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2006 * * */ #ifndef _EC_DEFS #define _EC_DEFS // Elliptic Curve type // #define PRIME_CURVE 0x00 #define BRAINPOOL_CURVE 0x01 // Elliptic Curve length in bits // #define CURVE160 0x00A0 #define CURVE192 0x00C0 #define CURVE224 0x00E0 #define CURVE256 0x0100 #define CURVE320 0x0140 #define CURVE384 0x0180 #define CURVE512 0x0200 #define CURVE521 0x0209 /* Supported Elliptic Curves */ #define NUMEC 12 /* number of supported curves */ extern CK_BYTE brainpoolP160r1[]; extern CK_BYTE brainpoolP192r1[]; extern CK_BYTE brainpoolP224r1[]; extern CK_BYTE brainpoolP256r1[]; extern CK_BYTE brainpoolP320r1[]; extern CK_BYTE brainpoolP384r1[]; extern CK_BYTE brainpoolP512r1[]; extern CK_BYTE prime192[]; extern CK_BYTE secp224[]; extern CK_BYTE prime256[]; extern CK_BYTE secp384[]; extern CK_BYTE secp521[]; // structure of supported Elliptic Curves struct _ec { uint8_t curve_type; /* uint8_t - prime or brainpool curve */ uint16_t len_bits; /* uint16_t - len in bits */ CK_ULONG data_size; CK_VOID_PTR data; }__attribute__ ((__packed__)); extern struct _ec der_ec_supported[NUMEC]; #endif opencryptoki+dfsg/usr/lib/pkcs11/common/host_defs.h0000755000175000017500000005400712630407154021410 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/lib/pkcs11/common/host_defs.h,v 1.8 2007/09/06 15:40:12 tlendacky Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ #include #ifndef _HOST_DEFS_H #define _HOST_DEFS_H #include #include #include "pkcs32.h" typedef struct _ENCR_DECR_CONTEXT { CK_OBJECT_HANDLE key; CK_MECHANISM mech; CK_BYTE *context; CK_ULONG context_len; CK_BBOOL multi; CK_BBOOL active; } ENCR_DECR_CONTEXT; typedef struct _DIGEST_CONTEXT { CK_MECHANISM mech; CK_BYTE *context; CK_ULONG context_len; CK_BBOOL multi; CK_BBOOL active; } DIGEST_CONTEXT; typedef struct _SIGN_VERIFY_CONTEXT { CK_OBJECT_HANDLE key; CK_MECHANISM mech; // current sign mechanism CK_BYTE *context; // temporary work area CK_ULONG context_len; CK_BBOOL multi; // is this a multi-part operation? CK_BBOOL recover; // are we in recover mode? CK_BBOOL active; } SIGN_VERIFY_CONTEXT; typedef struct _SESSION { CK_SESSION_HANDLE handle; CK_SESSION_INFO session_info; CK_OBJECT_HANDLE *find_list; // array of CK_OBJECT_HANDLE CK_ULONG_32 find_count; // # handles in the list CK_ULONG_32 find_len; // max # of handles in the list CK_ULONG_32 find_idx; // current position CK_BBOOL find_active; ENCR_DECR_CONTEXT encr_ctx; ENCR_DECR_CONTEXT decr_ctx; DIGEST_CONTEXT digest_ctx; SIGN_VERIFY_CONTEXT sign_ctx; SIGN_VERIFY_CONTEXT verify_ctx; } SESSION; /* TODO: * Add compile-time checking that sizeof(void *) == sizeof(CK_SESSION_HANDLE) * */ typedef struct _DES_CONTEXT { CK_BYTE data[ DES_BLOCK_SIZE ]; CK_ULONG len; CK_BBOOL cbc_pad; // is this a CKM_DES_CBC_PAD operation? } DES_CONTEXT; typedef struct _DES_DATA_CONTEXT { CK_BYTE data[ DES_BLOCK_SIZE ]; CK_ULONG len; CK_BYTE iv[ DES_BLOCK_SIZE ]; } DES_DATA_CONTEXT; typedef struct _AES_CONTEXT { CK_BYTE data[ AES_BLOCK_SIZE ]; CK_ULONG len; CK_BBOOL cbc_pad; } AES_CONTEXT; typedef struct _AES_DATA_CONTEXT { CK_BYTE data[ AES_BLOCK_SIZE ]; CK_ULONG len; CK_BYTE iv[ AES_BLOCK_SIZE ]; } AES_DATA_CONTEXT; typedef struct _AES_GCM_CONTEXT { /* Data buffer for DecryptUpdate needs space * for tag data and remaining tail data */ CK_BYTE data[2*AES_BLOCK_SIZE]; CK_ULONG len; CK_BYTE icb[AES_BLOCK_SIZE]; CK_BYTE ucb[AES_BLOCK_SIZE]; CK_BYTE hash[AES_BLOCK_SIZE]; CK_BYTE subkey[AES_BLOCK_SIZE]; CK_ULONG ulAlen; CK_ULONG ulClen; } AES_GCM_CONTEXT; typedef struct _SHA1_CONTEXT { unsigned int buf[16]; unsigned int hash_value[5]; unsigned int bits_hi, bits_lo; // # bits processed so far } SHA1_CONTEXT; typedef SHA1_CONTEXT SHA2_CONTEXT; typedef struct _MD2_CONTEXT { CK_BYTE state[16]; // state CK_BYTE checksum[16]; // checksum CK_ULONG count; // number of bytes, modulo 16 CK_BYTE buffer[16]; // input buffer } MD2_CONTEXT; typedef struct _MD5_CONTEXT { CK_ULONG i[2]; // number of _bits_ handled mod 2^64 CK_ULONG buf[4]; // scratch buffer CK_BYTE in[64]; // input buffer CK_BYTE digest[16]; // actual digest after MD5Final call } MD5_CONTEXT; // linux typedef pthread_mutex_t MUTEX; // This is actualy wrong... XPROC will be with spinlocks typedef struct _TEMPLATE { DL_NODE *attribute_list; } TEMPLATE; typedef struct _OBJECT { CK_OBJECT_CLASS class; CK_BYTE name[8]; // for token objects SESSION *session; // creator; only for session objects TEMPLATE *template; CK_ULONG count_hi; // only significant for token objects CK_ULONG count_lo; // only significant for token objects CK_ULONG index; // SAB Index into the SHM CK_OBJECT_HANDLE map_handle; } OBJECT; typedef struct _OBJECT_MAP { CK_OBJECT_HANDLE obj_handle; CK_BBOOL is_private; CK_BBOOL is_session_obj; SESSION * session; } OBJECT_MAP; /* FIXME: Compile-time check that sizeof(void *) == sizeof(CK_OBJECT_HANDLE) */ typedef struct _ATTRIBUTE_PARSE_LIST { CK_ATTRIBUTE_TYPE type; void *ptr; CK_ULONG len; CK_BBOOL found; } ATTRIBUTE_PARSE_LIST; typedef struct _OP_STATE_DATA { CK_STATE session_state; CK_ULONG active_operation; CK_ULONG data_len; // state data gets appended here // // mechanism parameter gets appended here // } OP_STATE_DATA; // this is our internal "tweak" vector (not the FCV) used to tweak various // aspects of the PKCS #11 implementation. Some of these tweaks deviate from // the PKCS #11 specification but are needed to support Netscape. Others // are left as token-defined values by PKCS #11. // // - whether or not to allow weak/semi-weak DES keys to be imported // - whether to insist imported DES keys have proper parity // - whether the CKA_ENCRYPT/DECRYPT/SIGN/VERIFY attributes are modifiable // after key creation // typedef struct _TWEAK_VEC { int allow_weak_des ; int check_des_parity ; int allow_key_mods ; int netscape_mods ; } TWEAK_VEC; typedef struct _TOKEN_DATA { CK_TOKEN_INFO_32 token_info; CK_BYTE user_pin_sha[3 * DES_BLOCK_SIZE]; CK_BYTE so_pin_sha[3 * DES_BLOCK_SIZE]; CK_BYTE next_token_object_name[8]; TWEAK_VEC tweak_vector; } TOKEN_DATA; typedef struct _SSL3_MAC_CONTEXT { DIGEST_CONTEXT hash_context; CK_BBOOL flag; } SSL3_MAC_CONTEXT; typedef struct _RSA_DIGEST_CONTEXT { DIGEST_CONTEXT hash_context; CK_BBOOL flag; } RSA_DIGEST_CONTEXT; typedef struct _MECH_LIST_ELEMENT { CK_MECHANISM_TYPE mech_type; CK_MECHANISM_INFO mech_info; } MECH_LIST_ELEMENT; struct mech_list_item; struct mech_list_item { struct mech_list_item *next; MECH_LIST_ELEMENT element; }; struct mech_list_item * find_mech_list_item_for_type(CK_MECHANISM_TYPE type, struct mech_list_item *head); /* mech_list.c */ CK_RV ock_generic_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount); /* mech_list.c */ CK_RV ock_generic_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); typedef struct _TOK_OBJ_ENTRY { CK_BBOOL deleted; char name[8]; CK_ULONG_32 count_lo; CK_ULONG_32 count_hi; } TOK_OBJ_ENTRY; typedef struct _LW_SHM_TYPE { TOKEN_DATA nv_token_data; CK_ULONG_32 num_priv_tok_obj; CK_ULONG_32 num_publ_tok_obj; CK_BBOOL priv_loaded; CK_BBOOL publ_loaded; TOK_OBJ_ENTRY publ_tok_objs[ MAX_TOK_OBJS ]; TOK_OBJ_ENTRY priv_tok_objs[ MAX_TOK_OBJS ]; } LW_SHM_TYPE; // These are the same for both AIX and Linux... #define MY_CreateMutex(x) _CreateMutex((MUTEX *)(x)) #define MY_DestroyMutex(x) _DestroyMutex((MUTEX *)(x)) #define MY_LockMutex(x) _LockMutex((MUTEX *)(x)) #define MY_UnlockMutex(x) _UnlockMutex((MUTEX *)(x)) #endif opencryptoki+dfsg/usr/lib/pkcs11/common/data_obj.c0000755000175000017500000004317112630407154021170 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: data_obj.c // // Functions contained within: // // data_object_check_required_attributes // data_object_set_default_attributes // data_object_validate_attribute // #include #include #include // for memcmp() et al #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" // data_object_check_required_attributes() // CK_RV data_object_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { // CKO_DATA has no required attributes // return template_check_required_base_attributes( tmpl, mode ); } // data_object_set_default_attributes() // // Set the default attributes for data objects: // // CKA_APPLICATION : empty string // CKA_VALUE : empty byte array // CK_RV data_object_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ) { CK_ATTRIBUTE *class_attr = NULL; CK_ATTRIBUTE *app_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; // satisfy the compiler // if (mode) app_attr = NULL; // add the default CKO_DATA attributes // class_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); app_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); value_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) ); if (!class_attr || !app_attr || !value_attr) { if (class_attr) free( class_attr ); if (app_attr) free( app_attr ); if (value_attr) free( value_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } app_attr->type = CKA_APPLICATION; app_attr->ulValueLen = 0; // empty string app_attr->pValue = NULL; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 0; // empty byte array value_attr->pValue = NULL; class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_DATA; template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, app_attr ); template_update_attribute( tmpl, value_attr ); return CKR_OK; } // data_object_validate_attribute() // // Determine whether a CKO_DATA object's attribute are valid. // CK_RV data_object_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ) { if (!attr){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } switch (attr->type) { case CKA_APPLICATION: case CKA_VALUE: return CKR_OK; default: return template_validate_base_attribute( tmpl, attr, mode ); } return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/verify_mgr.c0000755000175000017500000014056512630407154021603 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: verify_mgr.c // // Verify manager routines // #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV verify_mgr_init( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_KEY_TYPE keytype; CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active != FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } // key usage restrictions // rc = object_mgr_find_in_map1( key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle.\n"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } // is key allowed to verify signatures? // rc = template_attribute_find( key_obj->template, CKA_VERIFY, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_VERIFY for the key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } else { flag = *(CK_BBOOL *)attr->pValue; if (flag != TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_FUNCTION_NOT_PERMITTED)); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } // is the mechanism supported? is the key type correct? is a // parameter present if required? is the key size allowed? // is the key allowed to generate signatures? // switch (mech->mechanism) { case CKM_RSA_X_509: case CKM_RSA_PKCS: case CKM_RSA_PKCS_PSS: { if (mech->mechanism == CKM_RSA_PKCS_PSS) { rc = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VERIFY for the key.\n"); return CKR_FUNCTION_FAILED; } rc = check_pss_params(mech, attr->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("check_pss_params failed.\n"); return rc; } } else { if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PUBLIC key operation // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PUBLIC_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } // PKCS #11 doesn't allow multi-part RSA operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_ECDSA: case CKM_ECDSA_SHA1: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_EC){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PUBLIC key operation // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PUBLIC_KEY){ TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if (mech->mechanism == CKM_ECDSA) { ctx->context_len = 0; ctx->context = NULL; } else { ctx->context_len = sizeof(RSA_DIGEST_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(RSA_DIGEST_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(RSA_DIGEST_CONTEXT)); } } break; case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PUBLIC key operation // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PUBLIC_KEY){ TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } ctx->context_len = sizeof(RSA_DIGEST_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(RSA_DIGEST_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(RSA_DIGEST_CONTEXT)); } break; case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: { rc = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } rc = check_pss_params(mech, attr->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("check_pss_params failed.\n"); return rc; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PUBLIC key operation // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PUBLIC_KEY) { TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } ctx->context_len = sizeof(DIGEST_CONTEXT); ctx->context = (CK_BYTE *)malloc(ctx->context_len); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(ctx->context, 0x0, ctx->context_len); } break; #if !(NODSA) case CKM_DSA: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DSA){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PUBLIC key operation // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PUBLIC_KEY){ TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } // PKCS #11 doesn't allow multi-part DSA operations // ctx->context_len = 0; ctx->context = NULL; } break; #endif case CKM_MD2_HMAC: case CKM_MD5_HMAC: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // PKCS #11 doesn't allow multi-part HMAC operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } /* Note: It was previously believed that pkcs#11 did not * support hmac multipart. As a result, those tokens using the * locally implemented hmac helper functions do not support * multipart hmac. */ ctx->context_len = 0; ctx->context = NULL; rc = hmac_verify_init(sess, mech, key); if (rc != CKR_OK) { TRACE_ERROR("Failed to initialize hmac.\n"); return rc; } } break; case CKM_MD2_HMAC_GENERAL: case CKM_MD5_HMAC_GENERAL: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_MD2_HMAC_GENERAL) && (*param > 16)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && (*param > 16)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // PKCS #11 doesn't allow multi-part HMAC operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_MD2_HMAC_GENERAL) && (*param > 16)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && (*param > 16)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) && (*param > 20)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_SHA256_HMAC_GENERAL) && (*param > 32)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_SHA384_HMAC_GENERAL) && (*param > 48)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_SHA512_HMAC_GENERAL) && (*param > 64)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } /* Note: It was previously believed that pkcs#11 did not * support hmac multipart. As a result, those tokens using the * locally implemented hmac helper functions do not support * multipart hmac. */ ctx->context_len = 0; ctx->context = NULL; rc = hmac_verify_init(sess, mech, key); if (rc != CKR_OK) { TRACE_ERROR("Failed to initialize hmac.\n"); return rc; } } break; case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // Netscape sets the parameter == 16. PKCS #11 limit is 8 // if (mech->mechanism == CKM_SSL3_MD5_MAC) { if (*param < 4 || *param > 16){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } if (mech->mechanism == CKM_SSL3_SHA1_MAC) { if (*param < 4 || *param > 20){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } rc = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else { class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_SECRET_KEY){ TRACE_ERROR("This operation requires a secret key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } ctx->context_len = sizeof(SSL3_MAC_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(SSL3_MAC_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(SSL3_MAC_CONTEXT)); } break; case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: { if (mech->pParameter) { if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->mechanism == CKM_DES3_MAC_GENERAL) { if (*param < 1 || *param > DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } /* CKM_DES_MAC or CKM_DES3_MAC should not have params */ else return CKR_MECHANISM_PARAM_INVALID; } ctx->context = (CK_BYTE *)malloc(sizeof(DES_DATA_CONTEXT)); ctx->context_len = sizeof(DES_DATA_CONTEXT); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_DATA_CONTEXT)); } break; case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: { if (mech->pParameter) { if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->mechanism == CKM_AES_MAC_GENERAL) { if (*param < 1 || *param > AES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } /* CKM_AES_MAC should not have params */ else return CKR_MECHANISM_PARAM_INVALID; } ctx->context = (CK_BYTE *)malloc(sizeof(AES_DATA_CONTEXT)); ctx->context_len = sizeof(AES_DATA_CONTEXT); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_DATA_CONTEXT)); } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (mech->ulParameterLen > 0) { ptr = (CK_BYTE *)malloc(mech->ulParameterLen); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, mech->pParameter, mech->ulParameterLen ); } ctx->key = key; ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = ptr; ctx->multi = FALSE; ctx->active = TRUE; ctx->recover = recover_mode; return CKR_OK; } // // CK_RV verify_mgr_cleanup( SIGN_VERIFY_CONTEXT *ctx ) { if (!ctx){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->recover = FALSE; ctx->context_len = 0; if (ctx->mech.pParameter) { free( ctx->mech.pParameter ); ctx->mech.pParameter = NULL; } if (ctx->context) { free( ctx->context ); ctx->context = NULL; } return CKR_OK; } // // CK_RV verify_mgr_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } // if the caller just wants the signature length, there is no reason to // specify the input data. I just need the input data length // if (!in_data || !signature){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->multi == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return rsa_pkcs_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_RSA_X_509: return rsa_x509_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_RSA_PKCS_PSS: return rsa_pss_verify(sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_verify(sess, ctx, in_data, in_data_len, signature, sig_len); #if !(NODSA) case CKM_DSA: return dsa_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); #endif #if !(NOMD2) case CKM_MD2_HMAC: case CKM_MD2_HMAC_GENERAL: return md2_hmac_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); #endif case CKM_MD5_HMAC: case CKM_MD5_HMAC_GENERAL: return md5_hmac_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: return sha1_hmac_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: return sha2_hmac_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: return sha3_hmac_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: return sha5_hmac_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_verify( sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_verify( sess, ctx, in_data, in_data_len, signature, sig_len); case CKM_ECDSA_SHA1: return ec_hash_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); case CKM_ECDSA: return ec_verify( sess, ctx, in_data, in_data_len, signature, sig_len ); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV verify_mgr_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { if (!sess || !ctx) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } ctx->multi = TRUE; switch (ctx->mech.mechanism) { case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_verify_update( sess, ctx, in_data, in_data_len ); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_update(sess, ctx, in_data, in_data_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_verify_update( sess, ctx, in_data, in_data_len ); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_verify_update( sess, ctx, in_data, in_data_len ); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_verify_update( sess, ctx, in_data, in_data_len ); case CKM_ECDSA_SHA1: return ec_hash_verify_update( sess, ctx, in_data, in_data_len ); case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: return hmac_verify_update(sess, in_data, in_data_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV verify_mgr_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len ) { if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } switch (ctx->mech.mechanism) { case CKM_MD2_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_verify_final( sess, ctx, signature, sig_len ); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_verify_final(sess, ctx, signature, sig_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_verify_final( sess, ctx, signature, sig_len ); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_verify_final( sess, ctx, signature, sig_len ); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_verify_final( sess, ctx, signature, sig_len ); case CKM_ECDSA_SHA1: return ec_hash_verify_final( sess, ctx, signature, sig_len ); case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: return hmac_verify_final(sess, signature, sig_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV verify_mgr_verify_recover( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len, CK_BYTE * out_data, CK_ULONG * out_len ) { if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } // if the caller just wants the signature length, there is no reason to // specify the input data. I just need the input data length // if (!signature || !out_len){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->multi == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return rsa_pkcs_verify_recover( sess, length_only, ctx, signature, sig_len, out_data, out_len ); case CKM_RSA_X_509: return rsa_x509_verify_recover( sess, length_only, ctx, signature, sig_len, out_data, out_len ); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } opencryptoki+dfsg/usr/lib/pkcs11/common/tok_specific.h0000755000175000017500000006135412630407154022077 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/lib/pkcs11/common/tok_specific.h,v 1.4 2007/12/05 22:52:01 mhalcrow Exp $ */ // /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ // Token specific functions that tokens must implement..... // // Prototypes #ifndef _TOK_SPECIFIC #define _TOK_SPECIFIC int token_specific_creatlock(void); CK_RV token_specific_attach_shm(CK_SLOT_ID slot_id, LW_SHM_TYPE **shmem); CK_RV token_specific_rng(CK_BYTE *, CK_ULONG); CK_RV token_specific_init(CK_SLOT_ID, char *); CK_RV token_specific_init_token_data(CK_SLOT_ID slot_id); CK_RV token_specific_load_token_data(CK_SLOT_ID slot_id, FILE *fh); CK_RV token_specific_save_token_data(CK_SLOT_ID slot_id, FILE *fh); CK_RV token_specific_final(void); CK_RV token_specific_init_token(CK_SLOT_ID, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR); CK_RV token_specific_login(SESSION *, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG); CK_RV token_specific_logout(); CK_RV token_specific_init_pin(SESSION *, CK_CHAR_PTR, CK_ULONG); CK_RV token_specific_set_pin(SESSION *, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG); CK_RV token_specific_des_key_gen(CK_BYTE *,CK_ULONG, CK_ULONG) ; CK_RV token_specific_des_ecb(CK_BYTE *, CK_ULONG , CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE ); CK_RV token_specific_des_cbc(CK_BYTE *, CK_ULONG , CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE *, CK_BYTE ); CK_RV token_specific_tdes_ecb(CK_BYTE *, CK_ULONG , CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE ); CK_RV token_specific_tdes_cbc(CK_BYTE *, CK_ULONG , CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE *, CK_BYTE ); CK_RV token_specific_tdes_mac(CK_BYTE *, CK_ULONG , OBJECT *, CK_BYTE *); CK_RV token_specific_tdes_ofb(CK_BYTE *, CK_BYTE *, CK_ULONG , OBJECT *, CK_BYTE *, uint_32 ); CK_RV token_specific_tdes_cfb(CK_BYTE *, CK_BYTE *, CK_ULONG , OBJECT *, CK_BYTE *, uint_32, uint_32 ); CK_RV token_specific_rsa_decrypt( CK_BYTE * , CK_ULONG , CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_encrypt( CK_BYTE * , CK_ULONG , CK_BYTE * , CK_ULONG *, OBJECT * ); CK_RV token_specific_rsa_generate_keypair( TEMPLATE * , TEMPLATE * ); CK_RV token_specific_rsa_sign(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_verify(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *); CK_RV token_specific_rsa_verify_recover(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_x509_encrypt(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_x509_decrypt(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_x509_sign(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_x509_verify(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *); CK_RV token_specific_rsa_x509_verify_recover(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, OBJECT *); CK_RV token_specific_rsa_oaep_encrypt(ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE *, CK_ULONG); CK_RV token_specific_rsa_oaep_decrypt(ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE *, CK_ULONG); CK_RV token_specific_rsa_pss_sign(SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV token_specific_rsa_pss_verify(SIGN_VERIFY_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV token_specific_ec_sign(CK_BYTE * , CK_ULONG , CK_BYTE * , CK_ULONG * , OBJECT * ); CK_RV token_specific_ec_verify(CK_BYTE * , CK_ULONG , CK_BYTE * , CK_ULONG , OBJECT * ); CK_RV token_specific_copy_object(SESSION *, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE_PTR); CK_RV token_specific_ec_generate_keypair( TEMPLATE * , TEMPLATE * ); CK_RV token_specific_create_object(SESSION *, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR); CK_RV token_specific_generate_key(SESSION *, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR); CK_RV token_specific_generate_key_pair(SESSION *, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR); /* Begin code contributed by Corrent corp. */ #ifndef NODH CK_RV token_specific_dh_pkcs_derive( CK_BYTE *, CK_ULONG *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG ) ; CK_RV token_specific_dh_pkcs_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ); #endif /* End code contributed by Corrent corp. */ CK_RV tok_cdmv_transform(CK_VOID_PTR, CK_ULONG); CK_RV token_specific_sha_init(DIGEST_CONTEXT *, CK_MECHANISM *); CK_RV token_specific_sha(DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV token_specific_sha_update(DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG); CK_RV token_specific_sha_final(DIGEST_CONTEXT *, CK_BYTE *, CK_ULONG *); CK_RV token_specific_hmac_sign_init(SESSION *, CK_MECHANISM *, CK_OBJECT_HANDLE); CK_RV token_specific_hmac_sign(SESSION *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV token_specific_hmac_sign_update(SESSION *, CK_BYTE *, CK_ULONG); CK_RV token_specific_hmac_sign_final(SESSION *, CK_BYTE *, CK_ULONG *); CK_RV token_specific_hmac_verify_init(SESSION *, CK_MECHANISM *, CK_OBJECT_HANDLE); CK_RV token_specific_hmac_verify(SESSION *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG); CK_RV token_specific_hmac_verify_update(SESSION *, CK_BYTE *, CK_ULONG); CK_RV token_specific_hmac_verify_final(SESSION *, CK_BYTE *, CK_ULONG); CK_RV token_specific_generic_secret_key_gen(TEMPLATE *template); #ifndef NOAES CK_RV token_specific_aes_key_gen( CK_BYTE *, CK_ULONG, CK_ULONG ); CK_RV token_specific_aes_ecb( CK_BYTE *, CK_ULONG , CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE ); CK_RV token_specific_aes_cbc( CK_BYTE *, CK_ULONG , CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE *, CK_BYTE ); CK_RV token_specific_aes_ctr( CK_BYTE *, CK_ULONG , CK_BYTE *, CK_ULONG *, OBJECT *, CK_BYTE *, CK_ULONG , CK_BYTE ); CK_RV token_specific_aes_gcm_init(SESSION *, ENCR_DECR_CONTEXT *, CK_MECHANISM *, CK_OBJECT_HANDLE, CK_BYTE); CK_RV token_specific_aes_gcm(SESSION *, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE); CK_RV token_specific_aes_gcm_update(SESSION *, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE); CK_RV token_specific_aes_gcm_final(SESSION *, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG *, CK_BYTE); CK_RV token_specific_aes_ofb( CK_BYTE *, CK_ULONG, CK_BYTE *, OBJECT *, CK_BYTE *, uint_32 ); CK_RV token_specific_aes_cfb( CK_BYTE *, CK_ULONG, CK_BYTE *, OBJECT *, CK_BYTE *, uint_32, uint_32 ); CK_RV token_specific_aes_mac(CK_BYTE *, CK_ULONG , OBJECT *, CK_BYTE *); #endif CK_RV token_specific_dsa_generate_keypair( TEMPLATE *, TEMPLATE *); CK_RV token_specific_dsa_sign( CK_BYTE *, CK_ULONG, CK_ULONG ); CK_RV token_specific_dsa_verify( CK_BYTE *, CK_BYTE *, OBJECT * ); CK_RV token_specific_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount); CK_RV token_specific_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); CK_RV token_specific_object_add(OBJECT *); #endif opencryptoki+dfsg/usr/lib/pkcs11/common/trace.h0000644000175000017500000004437612630407154020535 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2015 */ #ifndef _TRACE_H #define _TRACE_H /* pkcs11 error messages */ enum errmsg { ERR_HOST_MEMORY = 0, ERR_SLOT_ID_INVALID, ERR_GENERAL_ERROR, ERR_FUNCTION_FAILED, ERR_ARGUMENTS_BAD, ERR_NO_EVENT, ERR_ATTRIBUTE_READ_ONLY, ERR_ATTRIBUTE_SENSITIVE, ERR_ATTRIBUTE_TYPE_INVALID, ERR_ATTRIBUTE_VALUE_INVALID, ERR_DATA_INVALID, ERR_DATA_LEN_RANGE, ERR_DEVICE_ERROR, ERR_DEVICE_MEMORY, ERR_DEVICE_REMOVED, ERR_ENCRYPTED_DATA_INVALID, ERR_ENCRYPTED_DATA_LEN_RANGE, ERR_FUNCTION_CANCELED, ERR_FUNCTION_NOT_PARALLEL, ERR_FUNCTION_NOT_SUPPORTED, ERR_KEY_CHANGED, ERR_KEY_FUNCTION_NOT_PERMITTED, ERR_KEY_HANDLE_INVALID, ERR_KEY_INDIGESTIBLE, ERR_KEY_NEEDED, ERR_KEY_NOT_NEEDED, ERR_KEY_NOT_WRAPPABLE, ERR_KEY_SIZE_RANGE, ERR_KEY_TYPE_INCONSISTENT, ERR_KEY_UNEXTRACTABLE, ERR_MECHANISM_INVALID, ERR_MECHANISM_PARAM_INVALID, ERR_OBJECT_HANDLE_INVALID, ERR_OPERATION_ACTIVE, ERR_OPERATION_NOT_INITIALIZED, ERR_PIN_INCORRECT, ERR_PIN_INVALID, ERR_PIN_LEN_RANGE, ERR_PIN_EXPIRED, ERR_PIN_LOCKED, ERR_SESSION_CLOSED, ERR_SESSION_COUNT, ERR_SESSION_HANDLE_INVALID, ERR_SESSION_PARALLEL_NOT_SUPPORTED, ERR_SESSION_READ_ONLY, ERR_SESSION_EXISTS, ERR_SESSION_READ_ONLY_EXISTS, ERR_SESSION_READ_WRITE_SO_EXISTS, ERR_SIGNATURE_INVALID, ERR_SIGNATURE_LEN_RANGE, ERR_TEMPLATE_INCOMPLETE, ERR_TEMPLATE_INCONSISTENT, ERR_TOKEN_NOT_PRESENT, ERR_TOKEN_NOT_RECOGNIZED, ERR_TOKEN_WRITE_PROTECTED, ERR_UNWRAPPING_KEY_HANDLE_INVALID, ERR_UNWRAPPING_KEY_SIZE_RANGE, ERR_UNWRAPPING_KEY_TYPE_INCONSISTENT, ERR_USER_ALREADY_LOGGED_IN, ERR_USER_NOT_LOGGED_IN, ERR_USER_PIN_NOT_INITIALIZED, ERR_USER_TYPE_INVALID, ERR_USER_ANOTHER_ALREADY_LOGGED_IN, ERR_USER_TOO_MANY_TYPES, ERR_WRAPPED_KEY_INVALID, ERR_WRAPPED_KEY_LEN_RANGE, ERR_WRAPPING_KEY_HANDLE_INVALID, ERR_WRAPPING_KEY_SIZE_RANGE, ERR_WRAPPING_KEY_TYPE_INCONSISTENT, ERR_RANDOM_SEED_NOT_SUPPORTED, ERR_DOMAIN_PARAMS_INVALID, ERR_BUFFER_TOO_SMALL, ERR_SAVED_STATE_INVALID, ERR_INFORMATION_SENSITIVE, ERR_STATE_UNSAVEABLE, ERR_CRYPTOKI_NOT_INITIALIZED, ERR_CRYPTOKI_ALREADY_INITIALIZED, ERR_MUTEX_BAD, ERR_MUTEX_NOT_LOCKED, ERR_MAX, }; /* Log levels */ typedef enum { TRACE_LEVEL_NONE = 0, TRACE_LEVEL_ERROR, TRACE_LEVEL_WARNING, TRACE_LEVEL_INFO, TRACE_LEVEL_DEVEL, TRACE_LEVEL_DEBUG } trace_level_t; /* Encapsulate all trace variables */ struct trace_handle_t { int fd; /* file descriptor for filename */ int level; /* trace level */ }; extern struct trace_handle_t trace; void set_trace(struct trace_handle_t t); CK_RV trace_initialize(); void trace_finalize(); void ock_traceit(trace_level_t level, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); const char *ock_err(int num); #define TRACE_ERROR(fmt, ...) ock_traceit(TRACE_LEVEL_ERROR, "[%s:%d %s] ERROR: " fmt, __FILE__, __LINE__, STDLL_NAME, ##__VA_ARGS__) #define TRACE_WARNING(fmt, ...) ock_traceit(TRACE_LEVEL_WARNING, "[%s:%d %s] WARN: " fmt, __FILE__, __LINE__, STDLL_NAME, ##__VA_ARGS__) #define TRACE_INFO(fmt, ...) ock_traceit(TRACE_LEVEL_INFO, "[%s:%d %s] INFO: " fmt, __FILE__, __LINE__, STDLL_NAME, ##__VA_ARGS__) #define TRACE_DEVEL(fmt, ...) ock_traceit(TRACE_LEVEL_DEVEL, "[%s:%d %s] DEVEL: " fmt, __FILE__, __LINE__, STDLL_NAME, ##__VA_ARGS__) #ifdef DEBUG #define TRACE_DEBUG(fmt, ...) ock_traceit(TRACE_LEVEL_DEBUG, "[%s:%d %s] DEBUG: " fmt, __FILE__, __LINE__, STDLL_NAME, ##__VA_ARGS__) void dump_shm(const char *); #define DUMP_SHM(x) dump_shm(x) #else #define TRACE_DEBUG(fmt, ...) #define DUMP_SHM(x) #endif #endif opencryptoki+dfsg/usr/lib/pkcs11/common/sess_mgr.c0000755000175000017500000013112712630407154021246 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: session.c // // Session manager related functions // #include #include #include // for memcmp() et al #include "pkcs11types.h" #include "local_types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // session_mgr_find() // // search for the specified session. returning a pointer to the session // might be dangerous, but performs well // // Returns: SESSION * or NULL // SESSION * session_mgr_find( CK_SESSION_HANDLE handle ) { SESSION * result = NULL; CK_RV rc; if (!handle) { return NULL; } rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return NULL; } result = bt_get_node_value(&sess_btree, handle); MY_UnlockMutex( &sess_list_mutex ); return result; } // session_mgr_new() // // creates a new session structure and adds it to the process's list // of sessions // // Args: CK_ULONG flags : session flags (INPUT) // SESSION ** sess : new session pointer (OUTPUT) // // Returns: CK_RV // CK_RV session_mgr_new( CK_ULONG flags, CK_SLOT_ID slot_id, CK_SESSION_HANDLE_PTR phSession ) { SESSION * new_session = NULL; CK_BBOOL user_session = FALSE; CK_BBOOL so_session = FALSE; CK_BBOOL pkcs_locked = TRUE; CK_BBOOL sess_locked = TRUE; CK_RV rc; new_session = (SESSION *)malloc(sizeof(SESSION)); if (!new_session) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset( new_session, 0x0, sizeof(SESSION) ); // find an unused session handle. session handles will wrap // automatically... // rc = MY_LockMutex( &pkcs_mutex ); // this protects next_session_handle if (rc != CKR_OK){ TRACE_ERROR("Mutex lock failed.\n"); return rc; } pkcs_locked = TRUE; MY_UnlockMutex( &pkcs_mutex ); pkcs_locked = FALSE; new_session->session_info.slotID = slot_id; new_session->session_info.flags = flags; new_session->session_info.ulDeviceError = 0; // determine the login/logout status of the new session. PKCS 11 requires // that all sessions belonging to a process have the same login/logout status // so_session = session_mgr_so_session_exists(); user_session = session_mgr_user_session_exists(); rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex lock failed.\n"); return rc; } sess_locked = TRUE; // we don't have to worry about having a user and SO session at the same time. // that is prevented in the login routine // if (user_session) { if (new_session->session_info.flags & CKF_RW_SESSION) new_session->session_info.state = CKS_RW_USER_FUNCTIONS; else { new_session->session_info.state = CKS_RO_USER_FUNCTIONS; ro_session_count++; } } else if (so_session) { new_session->session_info.state = CKS_RW_SO_FUNCTIONS; } else { if (new_session->session_info.flags & CKF_RW_SESSION) new_session->session_info.state = CKS_RW_PUBLIC_SESSION; else { new_session->session_info.state = CKS_RO_PUBLIC_SESSION; ro_session_count++; } } *phSession = bt_node_add(&sess_btree, new_session); if (*phSession == 0) { rc = CKR_HOST_MEMORY; /* new_session will be free'd below */ } done: if (pkcs_locked) MY_UnlockMutex( &pkcs_mutex ); if (sess_locked) MY_UnlockMutex( &sess_list_mutex ); if (rc != CKR_OK && new_session != NULL){ TRACE_ERROR("Mutex Lock failed.\n"); free( new_session ); } return rc; } // session_mgr_so_session_exists() // // determines whether a RW_SO session exists for the specified process // // Returns: TRUE or FALSE // CK_BBOOL session_mgr_so_session_exists( void ) { CK_BBOOL result; CK_RV rc; /* we must acquire sess_list_mutex in order to inspect glogal_login_state */ rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return FALSE; // FIXME: make this function return proper errors } result = (global_login_state == CKS_RW_SO_FUNCTIONS); MY_UnlockMutex( &sess_list_mutex ); return result; } // session_mgr_user_session_exists() // // determines whether a USER session exists for the specified process // // Returns: TRUE or FALSE // CK_BBOOL session_mgr_user_session_exists( void ) { CK_BBOOL result; CK_RV rc; /* we must acquire sess_list_mutex in order to inspect glogal_login_state */ rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return FALSE; // FIXME: return proper errors } result = ( (global_login_state == CKS_RO_USER_FUNCTIONS) || (global_login_state == CKS_RW_USER_FUNCTIONS) ); MY_UnlockMutex( &sess_list_mutex ); return result; } // session_mgr_public_session_exists() // // determines whether a PUBLIC session exists for the specified process // // Returns: TRUE or FALSE // CK_BBOOL session_mgr_public_session_exists( void ) { CK_BBOOL result; CK_RV rc; /* we must acquire sess_list_mutex in order to inspect glogal_login_state */ rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return FALSE; // FIXME: return proper errors } result = ( (global_login_state == CKS_RO_PUBLIC_SESSION) || (global_login_state == CKS_RW_PUBLIC_SESSION) ); MY_UnlockMutex( &sess_list_mutex ); return result; } // session_mgr_readonly_exists() // // determines whether the specified process owns any read-only sessions. this is useful // because the SO cannot log in if a read-only session exists. // CK_BBOOL session_mgr_readonly_session_exists( void ) { CK_BBOOL result; CK_RV rc; /* we must acquire sess_list_mutex in order to inspect glogal_login_state */ rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return rc; } result = (ro_session_count > 0); MY_UnlockMutex( &sess_list_mutex ); return result; } // session_mgr_close_session() // // removes the specified session from the process' session list // // Args: PROCESS * proc : parent process // SESSION * session : session to remove // // Returns: TRUE on success else FALSE // CK_RV session_mgr_close_session( CK_SESSION_HANDLE handle ) { SESSION *sess; CK_RV rc = CKR_OK; rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return CKR_FUNCTION_FAILED; } sess = bt_get_node_value(&sess_btree, handle); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } object_mgr_purge_session_objects( sess, ALL ); if ( (sess->session_info.state == CKS_RO_PUBLIC_SESSION) || (sess->session_info.state == CKS_RO_USER_FUNCTIONS) ) { ro_session_count--; } // Make sure this address is now invalid sess->handle = CK_INVALID_HANDLE; if (sess->find_list) free( sess->find_list ); if (sess->encr_ctx.context) free( sess->encr_ctx.context ); if (sess->encr_ctx.mech.pParameter) free( sess->encr_ctx.mech.pParameter ); if (sess->decr_ctx.context) free( sess->decr_ctx.context ); if (sess->decr_ctx.mech.pParameter) free( sess->decr_ctx.mech.pParameter ); if (sess->digest_ctx.context) free( sess->digest_ctx.context ); if (sess->digest_ctx.mech.pParameter) free( sess->digest_ctx.mech.pParameter ); if (sess->sign_ctx.context) free( sess->sign_ctx.context ); if (sess->sign_ctx.mech.pParameter) free( sess->sign_ctx.mech.pParameter ); if (sess->verify_ctx.context) free( sess->verify_ctx.context ); if (sess->verify_ctx.mech.pParameter) free( sess->verify_ctx.mech.pParameter ); bt_node_free(&sess_btree, handle, free); // XXX XXX Not having this is a problem // for IHS. The spec states that there is an implicit logout // when the last session is closed. Cannonicaly this is what other // implementaitons do. however on linux for some reason IHS can't seem // to keep the session open, which means that they go through the login // path EVERY time, which of course causes a reload of the private // objects EVERY time. If we are logged out, we MUST purge the private // objects from this process.. // if (bt_is_empty(&sess_btree)) { // SAB XXX if all sessions are closed. Is this effectivly logging out if (token_specific.t_logout) { rc = token_specific.t_logout(); } object_mgr_purge_private_token_objects(); global_login_state = CKS_RO_PUBLIC_SESSION; // The objects really need to be purged .. but this impacts the // performance under linux. So we need to make sure that the // login state is valid. I don't really like this. MY_LockMutex( &obj_list_mutex ); object_mgr_purge_map((SESSION *)0xFFFF, PRIVATE); MY_UnlockMutex( &obj_list_mutex ); } done: MY_UnlockMutex( &sess_list_mutex ); return rc; } /* session_free * * Callback used to free an individual SESSION object */ void session_free(void *node_value, unsigned long node_idx, void *p3) { SESSION *sess = (SESSION *)node_value; object_mgr_purge_session_objects( sess, ALL ); sess->handle = CK_INVALID_HANDLE; if (sess->find_list) free( sess->find_list ); if (sess->encr_ctx.context) free( sess->encr_ctx.context ); if (sess->encr_ctx.mech.pParameter) free( sess->encr_ctx.mech.pParameter); if (sess->decr_ctx.context) free( sess->decr_ctx.context ); if (sess->decr_ctx.mech.pParameter) free( sess->decr_ctx.mech.pParameter); if (sess->digest_ctx.context) free( sess->digest_ctx.context ); if (sess->digest_ctx.mech.pParameter) free( sess->digest_ctx.mech.pParameter); if (sess->sign_ctx.context) free( sess->sign_ctx.context ); if (sess->sign_ctx.mech.pParameter) free( sess->sign_ctx.mech.pParameter); if (sess->verify_ctx.context) free( sess->verify_ctx.context ); if (sess->verify_ctx.mech.pParameter) free( sess->verify_ctx.mech.pParameter); /* NB: any access to sess or @node_value after this returns will segfault */ bt_node_free(&sess_btree, node_idx, free); } // session_mgr_close_all_sessions() // // removes all sessions from the specified process // CK_RV session_mgr_close_all_sessions( void ) { CK_RV rc = CKR_OK; rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return CKR_FUNCTION_FAILED; } bt_for_each_node(&sess_btree, session_free, NULL); global_login_state = CKS_RO_PUBLIC_SESSION; ro_session_count = 0; MY_UnlockMutex( &sess_list_mutex ); return CKR_OK; } /* session_login * * Callback used to update a SESSION object's login state to logged in based on user type */ void session_login(void *node_value, unsigned long node_idx, void *p3) { SESSION *s = (SESSION *)node_value; CK_USER_TYPE user_type = *(CK_USER_TYPE *)p3; if (s->session_info.flags & CKF_RW_SESSION) { if (user_type == CKU_USER) s->session_info.state = CKS_RW_USER_FUNCTIONS; else s->session_info.state = CKS_RW_SO_FUNCTIONS; } else { if (user_type == CKU_USER) s->session_info.state = CKS_RO_USER_FUNCTIONS; } global_login_state = s->session_info.state; // SAB } // session_mgr_login_all() // // changes the login status of all sessions in the token // // Arg: CK_USER_TYPE user_type : USER or SO // CK_RV session_mgr_login_all( CK_USER_TYPE user_type ) { CK_RV rc = CKR_OK; rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return CKR_FUNCTION_FAILED; } bt_for_each_node(&sess_btree, session_login, (void *)&user_type); MY_UnlockMutex( &sess_list_mutex ); return CKR_OK; } /* session_logout * * Callback used to update a SESSION object's login state to be logged out */ void session_logout(void *node_value, unsigned long node_idx, void *p3) { SESSION *s = (SESSION *)node_value; // all sessions get logged out so destroy any private objects // public objects are left alone // object_mgr_purge_session_objects( s, PRIVATE ); if (s->session_info.flags & CKF_RW_SESSION) s->session_info.state = CKS_RW_PUBLIC_SESSION; else s->session_info.state = CKS_RO_PUBLIC_SESSION; global_login_state = s->session_info.state; // SAB } // session_mgr_logout_all() // // changes the login status of all sessions in the token // CK_RV session_mgr_logout_all( void ) { CK_RV rc = CKR_OK; rc = MY_LockMutex( &sess_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return CKR_FUNCTION_FAILED; } bt_for_each_node(&sess_btree, session_logout, NULL); MY_UnlockMutex( &sess_list_mutex ); return CKR_OK; } // // CK_RV session_mgr_get_op_state( SESSION *sess, CK_BBOOL length_only, CK_BYTE *data, CK_ULONG *data_len ) { OP_STATE_DATA *op_data = NULL; CK_ULONG op_data_len = 0; CK_ULONG offset; if (!sess){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } // ensure that at least one operation is active // if (sess->find_active == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); return CKR_STATE_UNSAVEABLE; } if (sess->encr_ctx.active == TRUE) { if (op_data != NULL){ TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); return CKR_STATE_UNSAVEABLE; } op_data_len = sizeof(OP_STATE_DATA) + sizeof(ENCR_DECR_CONTEXT) + sess->encr_ctx.context_len + sess->encr_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)data; op_data->data_len = op_data_len - sizeof(OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_ENCR; offset = sizeof(OP_STATE_DATA); memcpy( (CK_BYTE *)op_data + offset, &sess->encr_ctx, sizeof(ENCR_DECR_CONTEXT) ); offset += sizeof(ENCR_DECR_CONTEXT); if (sess->encr_ctx.context_len != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->encr_ctx.context, sess->encr_ctx.context_len ); offset += sess->encr_ctx.context_len; } if (sess->encr_ctx.mech.ulParameterLen != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->encr_ctx.mech.pParameter, sess->encr_ctx.mech.ulParameterLen ); } } } if (sess->decr_ctx.active == TRUE) { if (op_data != NULL){ TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); return CKR_STATE_UNSAVEABLE; } op_data_len = sizeof(OP_STATE_DATA) + sizeof(ENCR_DECR_CONTEXT) + sess->decr_ctx.context_len + sess->decr_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)data; op_data->data_len = op_data_len - sizeof(OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_DECR; offset = sizeof(OP_STATE_DATA); memcpy( (CK_BYTE *)op_data + offset, &sess->decr_ctx, sizeof(ENCR_DECR_CONTEXT) ); offset += sizeof(ENCR_DECR_CONTEXT); if (sess->decr_ctx.context_len != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->decr_ctx.context, sess->decr_ctx.context_len ); offset += sess->decr_ctx.context_len; } if (sess->decr_ctx.mech.ulParameterLen != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->decr_ctx.mech.pParameter, sess->decr_ctx.mech.ulParameterLen ); } } } if (sess->digest_ctx.active == TRUE) { if (op_data != NULL){ TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); return CKR_STATE_UNSAVEABLE; } op_data_len = sizeof(OP_STATE_DATA) + sizeof(DIGEST_CONTEXT) + sess->digest_ctx.context_len + sess->digest_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)data; op_data->data_len = op_data_len - sizeof(OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_DIGEST; offset = sizeof(OP_STATE_DATA); memcpy( (CK_BYTE *)op_data + offset, &sess->digest_ctx, sizeof(DIGEST_CONTEXT) ); offset += sizeof(DIGEST_CONTEXT); if (sess->digest_ctx.context_len != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->digest_ctx.context, sess->digest_ctx.context_len ); offset += sess->digest_ctx.context_len; } if (sess->digest_ctx.mech.ulParameterLen != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->digest_ctx.mech.pParameter, sess->digest_ctx.mech.ulParameterLen ); } } } if (sess->sign_ctx.active == TRUE) { if (op_data != NULL){ TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); return CKR_STATE_UNSAVEABLE; } op_data_len = sizeof(OP_STATE_DATA) + sizeof(SIGN_VERIFY_CONTEXT) + sess->sign_ctx.context_len + sess->sign_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)data; op_data->data_len = op_data_len - sizeof(OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_SIGN; offset = sizeof(OP_STATE_DATA); memcpy( (CK_BYTE *)op_data + offset, &sess->sign_ctx, sizeof(SIGN_VERIFY_CONTEXT) ); offset += sizeof(SIGN_VERIFY_CONTEXT); if (sess->sign_ctx.context_len != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->sign_ctx.context, sess->sign_ctx.context_len ); offset += sess->sign_ctx.context_len; } if (sess->sign_ctx.mech.ulParameterLen != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->sign_ctx.mech.pParameter, sess->sign_ctx.mech.ulParameterLen ); } } } if (sess->verify_ctx.active == TRUE) { if (op_data != NULL){ TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE)); return CKR_STATE_UNSAVEABLE; } op_data_len = sizeof(OP_STATE_DATA) + sizeof(SIGN_VERIFY_CONTEXT) + sess->verify_ctx.context_len + sess->verify_ctx.mech.ulParameterLen; if (length_only == FALSE) { op_data = (OP_STATE_DATA *)data; op_data->data_len = op_data_len - sizeof(OP_STATE_DATA); op_data->session_state = sess->session_info.state; op_data->active_operation = STATE_SIGN; offset = sizeof(OP_STATE_DATA); memcpy( (CK_BYTE *)op_data + offset, &sess->verify_ctx, sizeof(SIGN_VERIFY_CONTEXT) ); offset += sizeof(SIGN_VERIFY_CONTEXT); if (sess->verify_ctx.context_len != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->verify_ctx.context, sess->verify_ctx.context_len ); offset += sess->verify_ctx.context_len; } if (sess->verify_ctx.mech.ulParameterLen != 0) { memcpy( (CK_BYTE *)op_data + offset, sess->verify_ctx.mech.pParameter, sess->verify_ctx.mech.ulParameterLen ); } } } *data_len = op_data_len; return CKR_OK; } // // CK_RV session_mgr_set_op_state( SESSION * sess, CK_OBJECT_HANDLE encr_key, CK_OBJECT_HANDLE auth_key, CK_BYTE * data, CK_ULONG data_len ) { OP_STATE_DATA *op_data = NULL; CK_BYTE *mech_param = NULL; CK_BYTE *context = NULL; CK_BYTE *ptr1 = NULL; CK_BYTE *ptr2 = NULL; CK_BYTE *ptr3 = NULL; CK_ULONG len; if (!sess || !data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } op_data = (OP_STATE_DATA *)data; // make sure the session states are compatible // if (sess->session_info.state != op_data->session_state){ TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID)); return CKR_SAVED_STATE_INVALID; } // validate the new state information. don't touch the session // until the new state is valid. // switch (op_data->active_operation) { case STATE_ENCR: case STATE_DECR: { ENCR_DECR_CONTEXT *ctx = (ENCR_DECR_CONTEXT *)(data + sizeof(OP_STATE_DATA)); len = sizeof(ENCR_DECR_CONTEXT) + ctx->context_len + ctx->mech.ulParameterLen; if (len != op_data->data_len){ TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID)); return CKR_SAVED_STATE_INVALID; } if (auth_key != 0){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_NEEDED)); return CKR_KEY_NOT_NEEDED; } if (encr_key == 0){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NEEDED)); return CKR_KEY_NEEDED; } ptr1 = (CK_BYTE *)ctx; ptr2 = ptr1 + sizeof(ENCR_DECR_CONTEXT); ptr3 = ptr2 + ctx->context_len; if (ctx->context_len) { context = (CK_BYTE *)malloc( ctx->context_len ); if (!context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( context, ptr2, ctx->context_len ); } if (ctx->mech.ulParameterLen) { mech_param = (CK_BYTE *)malloc( ctx->mech.ulParameterLen ); if (!mech_param) { if (context) free( context ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( mech_param, ptr3, ctx->mech.ulParameterLen ); } } break; case STATE_SIGN: case STATE_VERIFY: { SIGN_VERIFY_CONTEXT *ctx = (SIGN_VERIFY_CONTEXT *)(data + sizeof(OP_STATE_DATA)); len = sizeof(SIGN_VERIFY_CONTEXT) + ctx->context_len + ctx->mech.ulParameterLen; if (len != op_data->data_len){ TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID)); return CKR_SAVED_STATE_INVALID; } if (auth_key == 0){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NEEDED)); return CKR_KEY_NEEDED; } if (encr_key != 0){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_NEEDED)); return CKR_KEY_NOT_NEEDED; } ptr1 = (CK_BYTE *)ctx; ptr2 = ptr1 + sizeof(SIGN_VERIFY_CONTEXT); ptr3 = ptr2 + ctx->context_len; if (ctx->context_len) { context = (CK_BYTE *)malloc( ctx->context_len ); if (!context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( context, ptr2, ctx->context_len ); } if (ctx->mech.ulParameterLen) { mech_param = (CK_BYTE *)malloc( ctx->mech.ulParameterLen ); if (!mech_param) { if (context) free( context ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( mech_param, ptr3, ctx->mech.ulParameterLen ); } } break; case STATE_DIGEST: { DIGEST_CONTEXT *ctx = (DIGEST_CONTEXT *)(data + sizeof(OP_STATE_DATA)); len = sizeof(DIGEST_CONTEXT) + ctx->context_len + ctx->mech.ulParameterLen; if (len != op_data->data_len){ TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID)); return CKR_SAVED_STATE_INVALID; } if (auth_key != 0){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_NEEDED)); return CKR_KEY_NOT_NEEDED; } if (encr_key != 0){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_NEEDED)); return CKR_KEY_NOT_NEEDED; } ptr1 = (CK_BYTE *)ctx; ptr2 = ptr1 + sizeof(DIGEST_CONTEXT); ptr3 = ptr2 + ctx->context_len; if (ctx->context_len) { context = (CK_BYTE *)malloc( ctx->context_len ); if (!context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( context, ptr2, ctx->context_len ); } if (ctx->mech.ulParameterLen) { mech_param = (CK_BYTE *)malloc( ctx->mech.ulParameterLen ); if (!mech_param) { if (context) free( context ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( mech_param, ptr3, ctx->mech.ulParameterLen ); } } break; default: TRACE_ERROR("%s\n", ock_err(ERR_SAVED_STATE_INVALID)); return CKR_SAVED_STATE_INVALID; } // state information looks okay. cleanup the current session state, first // if (sess->encr_ctx.active) encr_mgr_cleanup( &sess->encr_ctx ); if (sess->decr_ctx.active) decr_mgr_cleanup( &sess->decr_ctx ); if (sess->digest_ctx.active) digest_mgr_cleanup( &sess->digest_ctx ); if (sess->sign_ctx.active) sign_mgr_cleanup( &sess->sign_ctx ); if (sess->verify_ctx.active) verify_mgr_cleanup( &sess->verify_ctx ); // copy the new state information // switch (op_data->active_operation) { case STATE_ENCR: memcpy( &sess->encr_ctx, ptr1, sizeof(ENCR_DECR_CONTEXT) ); sess->encr_ctx.key = encr_key; sess->encr_ctx.context = context; sess->encr_ctx.mech.pParameter = mech_param; break; case STATE_DECR: memcpy( &sess->decr_ctx, ptr1, sizeof(ENCR_DECR_CONTEXT) ); sess->decr_ctx.key = encr_key; sess->decr_ctx.context = context; sess->decr_ctx.mech.pParameter = mech_param; break; case STATE_SIGN: memcpy( &sess->sign_ctx, ptr1, sizeof(SIGN_VERIFY_CONTEXT) ); sess->sign_ctx.key = auth_key; sess->sign_ctx.context = context; sess->sign_ctx.mech.pParameter = mech_param; break; case STATE_VERIFY: memcpy( &sess->verify_ctx, ptr1, sizeof(SIGN_VERIFY_CONTEXT) ); sess->verify_ctx.key = auth_key; sess->verify_ctx.context = context; sess->verify_ctx.mech.pParameter = mech_param; break; case STATE_DIGEST: memcpy( &sess->digest_ctx, ptr1, sizeof(DIGEST_CONTEXT) ); sess->digest_ctx.context = context; sess->digest_ctx.mech.pParameter = mech_param; break; } return CKR_OK; } // Return TRUE if the session we're in has its PIN // expired. CK_BBOOL pin_expired(CK_SESSION_INFO *si, CK_FLAGS flags) { // If this is an SO session if ( (flags & CKF_SO_PIN_TO_BE_CHANGED) && (si->state == CKS_RW_SO_FUNCTIONS) ) return TRUE; // Else we're a User session return( (flags & CKF_USER_PIN_TO_BE_CHANGED) && ((si->state == CKS_RO_USER_FUNCTIONS) || (si->state == CKS_RW_USER_FUNCTIONS)) ); } // Return TRUE if the session we're in has its PIN // locked. CK_BBOOL pin_locked(CK_SESSION_INFO *si, CK_FLAGS flags) { // If this is an SO session if ( (flags & CKF_SO_PIN_LOCKED) && (si->state == CKS_RW_SO_FUNCTIONS) ) return TRUE; // Else we're a User session return( (flags & CKF_USER_PIN_LOCKED) && ((si->state == CKS_RO_USER_FUNCTIONS) || (si->state == CKS_RW_USER_FUNCTIONS)) ); } // Increment the login flags after an incorrect password // has been passed to C_Login. New for v2.11. - KEY void set_login_flags(CK_USER_TYPE userType, CK_FLAGS_32 *flags) { if(userType == CKU_USER) { if(*flags & CKF_USER_PIN_FINAL_TRY) { *flags |= CKF_USER_PIN_LOCKED; *flags &= ~(CKF_USER_PIN_FINAL_TRY); } else if (*flags & CKF_USER_PIN_COUNT_LOW) { *flags |= CKF_USER_PIN_FINAL_TRY; *flags &= ~(CKF_USER_PIN_COUNT_LOW); } else { *flags |= CKF_USER_PIN_COUNT_LOW; } } else { if(*flags & CKF_SO_PIN_FINAL_TRY) { *flags |= CKF_SO_PIN_LOCKED; *flags &= ~(CKF_SO_PIN_FINAL_TRY); } else if (*flags & CKF_SO_PIN_COUNT_LOW) { *flags |= CKF_SO_PIN_FINAL_TRY; *flags &= ~(CKF_SO_PIN_COUNT_LOW); } else { *flags |= CKF_SO_PIN_COUNT_LOW; } } } opencryptoki+dfsg/usr/lib/pkcs11/common/p11util.h0000755000175000017500000004060612630407154020731 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ #ifndef _P11UTIL_H_ #define _P11UTIL_H__ #include "pkcs11types.h" // // p11_get_ckr - return textual interpretation of a CKR_ error code // @rc is the CKR_.. error // char *p11_get_ckr( CK_RV rc ); // // p11_get_ckm - return textual interpretation of a CKM_ mechanism code // @rc is the CKM_.. as a string // char *p11_get_ckm(CK_ULONG); // is_attribute_defined() // // determine whether the specified attribute is defined by Cryptoki // CK_BBOOL is_attribute_defined( CK_ATTRIBUTE_TYPE type ); // Allocates memory on *dst and puts hex dump from ptr // with len bytes. // *dst must be freed by the caller char * p11_ahex_dump(char **dst, CK_BYTE_PTR ptr, CK_ULONG len); /* p11_bigint_trim() - trim a big integer. Returns pointer that is * contained within 'in' + '*size' that represents * the same number, but without leading zeros. * @in points to a sequence of bytes forming a big integer, * unsigned, right-aligned and big-endian * @size points to the size of @in on input, and the minimum * size that can represent it on output */ CK_BYTE_PTR p11_bigint_trim(CK_BYTE_PTR in, CK_ULONG_PTR size); /* p11_attribute_trim() - trim a PKCS#11 CK_ATTRIBUTE in place, * using memmove() to move the data and adjusting * ulValueLen. The resulting "pValue" pointer stays the * same so that the caller can free() it normally * @attr is the pointer to the CK_ATTRIBUTE to be trimmed */ void p11_attribute_trim(CK_ATTRIBUTE *attr); #endif // #ifndef _P11UTIL_H_ opencryptoki+dfsg/usr/lib/pkcs11/common/object.c0000755000175000017500000010442312630407154020671 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: object.c // // Object manager related functions // // Functions contained within: // // object_create // object_free // object_is_modifiable // object_is_private // object_is_token_object // object_is_session_object // #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "pkcs32.h" #include "trace.h" // object_create() // // Args: void * attributes : (INPUT) pointer to data block containing ATTRIBUTEs // OBJECT * obj : (OUTPUT) destination object // // Creates an object with the specified attributes. Verifies that all required // attributes are present and adds any missing attributes that have Cryptoki-defined // default values. This routine does not check whether the session is authorized // to create the object. That is done elsewhere (see object_mgr_create()) // CK_RV object_create( CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, OBJECT ** obj ) { OBJECT * o = NULL; CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * sensitive = NULL; CK_ATTRIBUTE * extractable = NULL; CK_ATTRIBUTE * local = NULL; CK_BBOOL class_given = FALSE; CK_BBOOL subclass_given = FALSE; CK_BBOOL flag; CK_ULONG class = 0xFFFFFFFF, subclass = 0xFFFFFFFF; CK_RV rc; unsigned int i; if (!pTemplate){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } // extract the object class and subclass // attr = pTemplate; for (i=0; i < ulCount; i++, attr++) { if (attr->type == CKA_CLASS) { class = *(CK_OBJECT_CLASS *)attr->pValue; class_given = TRUE; } if (attr->type == CKA_CERTIFICATE_TYPE) { subclass = *(CK_CERTIFICATE_TYPE *)attr->pValue; subclass_given = TRUE; } if (attr->type == CKA_KEY_TYPE) { subclass = *(CK_KEY_TYPE *)attr->pValue; subclass_given = TRUE; } if (attr->type == CKA_HW_FEATURE_TYPE) { subclass = *(CK_HW_FEATURE_TYPE *)attr->pValue; subclass_given = TRUE; } } if (class_given == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } // Return CKR_ATTRIBUTE_TYPE_INVALID when trying to create a // vendor-defined object. if (class >= CKO_VENDOR_DEFINED) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); return CKR_ATTRIBUTE_TYPE_INVALID; } if (class != CKO_DATA && subclass_given != TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } rc = object_create_skel( pTemplate, ulCount, MODE_CREATE, class, subclass, &o ); if (rc != CKR_OK){ TRACE_DEVEL("object_create_skel failed.\n"); return rc; } // for key objects, we need be careful... // // note: I would think that keys loaded with C_CreateObject should // have their CKA_NEVER_EXTRACTABLE == FALSE and // CKA_ALWAYS_SENSITIVE == FALSE since the key data was presumably // stored in the clear prior to the call to C_CreateObject. The // PKCS #11 spec doesn't impose this restriction however. // if (class == CKO_PRIVATE_KEY || class == CKO_SECRET_KEY) { rc = template_attribute_find( o->template, CKA_SENSITIVE, &attr ); if (rc == FALSE) { TRACE_ERROR("Failed to find CKA_SENSITIVE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto error; } flag = *(CK_BBOOL *)attr->pValue; rc = build_attribute( CKA_ALWAYS_SENSITIVE, &flag, sizeof(CK_BYTE), &sensitive ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed.\n"); goto error; } rc = template_attribute_find( o->template, CKA_EXTRACTABLE, &attr ); if (rc == FALSE) { TRACE_ERROR("Failed to find CKA_EXTRACTABLE for the key.\n"); rc = CKR_FUNCTION_FAILED; goto error; } flag = *(CK_BBOOL *)attr->pValue; flag = (~flag) & 0x1; rc = build_attribute( CKA_NEVER_EXTRACTABLE, &flag, sizeof(CK_BYTE), &extractable ); if (rc != CKR_OK){ TRACE_DEVEL("build attribute failed.\n"); goto error; } template_update_attribute( o->template, sensitive ); template_update_attribute( o->template, extractable ); } *obj = o; return CKR_OK; error: if (sensitive) free( sensitive ); if (extractable) free( extractable ); if (local) free( local ); object_free( o ); return rc; } // object_copy() // // Args: OBJECT * old_obj : (INPUT) pointer to the source object // void * attributes : (INPUT) pointer to data block containing additional ATTRIBUTEs // CK_ULONG count : (INPUT) number of new attributes // OBJECT ** new_obj : (OUTPUT) destination object // // Builds a copy of the specified object. The new object gets the original // object's attribute template plus any additional attributes that are specified. // Verifies that all required attributes are present. This routine does not // check whether the session is authorized to copy the object -- routines at // the individual object level don't have the concept of "session". These checks // are done by the object manager. // CK_RV object_copy( CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, OBJECT * old_obj, OBJECT ** new_obj ) { TEMPLATE * tmpl = NULL; TEMPLATE * new_tmpl = NULL; OBJECT * o = NULL; CK_BBOOL found; CK_ULONG class, subclass; CK_RV rc; if (!old_obj || !pTemplate || !new_obj){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } o = (OBJECT *)malloc(sizeof(OBJECT)); tmpl = (TEMPLATE *)malloc(sizeof(TEMPLATE)); new_tmpl = (TEMPLATE *)malloc(sizeof(TEMPLATE)); if (!o || !tmpl || !new_tmpl) { rc = CKR_HOST_MEMORY; TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto error; } memset( o, 0x0, sizeof(OBJECT) ); memset( tmpl, 0x0, sizeof(TEMPLATE) ); memset( new_tmpl, 0x0, sizeof(TEMPLATE) ); // copy the original object's attribute template // rc = template_copy( tmpl, old_obj->template ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to copy template.\n"); goto error; } rc = template_add_attributes( new_tmpl, pTemplate, ulCount ); if (rc != CKR_OK){ TRACE_DEVEL("template_add_attributes failed.\n"); goto error; } // at this point, the new object has the list of attributes. we need // to do some more checking now: // 1) invalid attribute values // 2) missing required attributes // 3) attributes inappropriate for the object class // 4) conflicting attributes/values // found = template_get_class( tmpl, &class, &subclass ); if (found == FALSE) { TRACE_ERROR("Could not find CKA_CLASS in object's template.\n"); rc = CKR_TEMPLATE_INCONSISTENT; goto error; } // the user cannot change object classes so we assume the existing // object attributes are valid. we still need to check the new attributes. // we cannot merge the new attributes in with the old ones and then check // for validity because some attributes are added internally and are not // allowed to be specified by the user (ie. CKA_LOCAL for key types) but // may still be part of the old template. // rc = template_validate_attributes( new_tmpl, class, subclass, MODE_COPY ); if (rc != CKR_OK){ TRACE_DEVEL("template_validate_attributes failed.\n"); goto error; } // merge in the new attributes // rc = template_merge( tmpl, &new_tmpl ); if (rc != CKR_OK){ TRACE_DEVEL("template_merge failed.\n"); goto error; } // do we need this? since an attribute cannot be removed, the original // object's template (contained in tmpl) already has the required attributes // present // rc = template_check_required_attributes( tmpl, class, subclass, MODE_COPY ); if (rc != CKR_OK){ TRACE_ERROR("template_check_required_attributes failed.\n"); goto error; } // at this point, we should have a valid object with correct attributes // o->template = tmpl; *new_obj = o; return CKR_OK; error: if (tmpl) template_free( tmpl ); if (new_tmpl) template_free( new_tmpl ); if (o) object_free( o ); return rc; } // object_flatten() - this is still used when saving token objects // CK_RV object_flatten( OBJECT * obj, CK_BYTE ** data, CK_ULONG * len ) { CK_BYTE * buf = NULL; CK_ULONG tmpl_len, total_len; CK_ULONG offset; CK_ULONG_32 count; long rc; if (!obj){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } count = template_get_count( obj->template ); tmpl_len = template_get_compressed_size ( obj->template ); total_len = tmpl_len + sizeof(CK_OBJECT_CLASS_32) + sizeof(CK_ULONG_32) + 8; buf = (CK_BYTE *)malloc(total_len); if (!buf){ // SAB XXX FIXME This was DATA TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( (CK_BYTE *)buf,0x0,total_len); offset = 0; memcpy( buf + offset, &obj->class, sizeof(CK_OBJECT_CLASS_32) ); offset += sizeof(CK_OBJECT_CLASS_32); memcpy( buf + offset, &count, sizeof(CK_ULONG_32) ); offset += sizeof(CK_ULONG_32); memcpy( buf + offset, &obj->name, sizeof(CK_BYTE) * 8 ); offset += 8; rc = template_flatten( obj->template, buf + offset ); if (rc != CKR_OK) { free( buf ); return rc; } *data = buf; *len = total_len; return CKR_OK; } // object_free() // // does what it says... // void object_free(OBJECT *obj) { if (obj && obj->template) { template_free(obj->template); free(obj); } } // object_is_modifiable() // CK_BBOOL object_is_modifiable( OBJECT *obj ) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL modifiable; CK_BBOOL found; found = template_attribute_find( obj->template, CKA_MODIFIABLE, &attr ); if (found == FALSE) return TRUE; // should always be found but we default to TRUE //axelrh: prevent dereferencing NULL from bad parse if (attr->pValue == NULL) return TRUE; //default to TRUE modifiable = *(CK_BBOOL *)attr->pValue; return modifiable; } // object_is_private() // // an is_private member should probably be added to OBJECT // CK_BBOOL object_is_private( OBJECT *obj ) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL priv; CK_BBOOL found; found = template_attribute_find( obj->template, CKA_PRIVATE, &attr ); if (found == FALSE){ return TRUE; // should always be found but we default to TRUE } if ( attr == NULL) return TRUE; //axelrh: prevent segfault caused by 0-len attribute //that has a null pValue CK_BBOOL *bboolPtr = (CK_BBOOL *)attr->pValue; if (bboolPtr == NULL) return TRUE; //default priv = *(bboolPtr); return priv; } // object_is_public() // CK_BBOOL object_is_public( OBJECT *obj ) { CK_BBOOL rc; rc = object_is_private( obj ); if (rc) return FALSE; return TRUE; } // object_is_token_object() // CK_BBOOL object_is_token_object( OBJECT *obj ) { CK_ATTRIBUTE * attr = NULL; CK_BBOOL is_token; CK_BBOOL found; found = template_attribute_find( obj->template, CKA_TOKEN, &attr ); if (found == FALSE) return FALSE; //axelrh: prevent dereferencing NULL from bad parse if (attr->pValue == NULL) return FALSE; is_token = *(CK_BBOOL *)attr->pValue; return is_token; } // object_is_session_object() // CK_BBOOL object_is_session_object( OBJECT *obj ) { CK_BBOOL rc; rc = object_is_token_object( obj ); if (rc) return FALSE; else return TRUE; } // object_get_size() // CK_ULONG object_get_size( OBJECT *obj ) { CK_ULONG size; size = sizeof(OBJECT) + template_get_size(obj->template); return size; } // // CK_RV object_get_attribute_values( OBJECT * obj, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ) { TEMPLATE *obj_tmpl = NULL; CK_ATTRIBUTE *attr = NULL; CK_ULONG i; CK_BBOOL flag; CK_RV rc; rc = CKR_OK; obj_tmpl = obj->template; for (i=0; i < ulCount; i++) { flag = template_check_exportability( obj_tmpl, pTemplate[i].type); if (flag == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_SENSITIVE)); rc = CKR_ATTRIBUTE_SENSITIVE; pTemplate[i].ulValueLen = (CK_ULONG)-1; continue; } flag = template_attribute_find( obj_tmpl, pTemplate[i].type, &attr ); if (flag == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID)); rc = CKR_ATTRIBUTE_TYPE_INVALID; pTemplate[i].ulValueLen = (CK_ULONG)-1; continue; } if (pTemplate[i].pValue == NULL) { pTemplate[i].ulValueLen = attr->ulValueLen; } else if (pTemplate[i].ulValueLen >= attr->ulValueLen) { memcpy( pTemplate[i].pValue, attr->pValue, attr->ulValueLen ); pTemplate[i].ulValueLen = attr->ulValueLen; } else { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); rc = CKR_BUFFER_TOO_SMALL; pTemplate[i].ulValueLen = (CK_ULONG)-1; } } return rc; } // object_set_attribute_values() // CK_RV object_set_attribute_values( OBJECT * obj, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ) { TEMPLATE * new_tmpl; CK_BBOOL found; CK_ULONG class, subclass; CK_RV rc; if (!obj || !pTemplate){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } found = template_get_class( obj->template, &class, &subclass ); if (found == FALSE) { TRACE_ERROR("Failed to find CKA_CLASS in object template.\n"); rc = CKR_FUNCTION_FAILED; goto error; } new_tmpl = (TEMPLATE *)malloc(sizeof(TEMPLATE)); if (!new_tmpl){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( new_tmpl, 0x0, sizeof(TEMPLATE) ); rc = template_add_attributes( new_tmpl, pTemplate, ulCount ); if (rc != CKR_OK){ TRACE_DEVEL("template_add_attributes failed.\n"); goto error; } // the user cannot change object classes so we assume the existing // object attributes are valid. we still need to check the new attributes. // we cannot merge the new attributes in with the old ones and then check // for validity because some attributes are added internally and are not // allowed to be specified by the user (ie. CKA_LOCAL for key types) but // may still be part of the old template. // rc = template_validate_attributes( new_tmpl, class, subclass, MODE_MODIFY ); if (rc != CKR_OK){ TRACE_DEVEL("template_validate_attributes failed.\n"); goto error; } // merge in the new attributes // rc = template_merge( obj->template, &new_tmpl ); if (rc != CKR_OK){ TRACE_DEVEL("template_merge failed.\n"); return rc; } return CKR_OK; error: // we only free the template if there was an error...otherwise the // object "owns" the template // if (new_tmpl) template_free( new_tmpl ); return rc; } // // CK_RV object_restore( CK_BYTE *data, OBJECT **new_obj, CK_BBOOL replace ) { return object_restore_withSize(data, new_obj, replace, -1); } // //Modified object_restore to prevent buffer overflow //If data_size=-1, won't do bounds checking CK_RV object_restore_withSize( CK_BYTE *data, OBJECT **new_obj, CK_BBOOL replace, int data_size ) { TEMPLATE * tmpl = NULL; OBJECT * obj = NULL; CK_ULONG offset = 0; CK_ULONG_32 count = 0; CK_RV rc; if (!data || !new_obj){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } obj = (OBJECT *)malloc(sizeof(OBJECT)); if (!obj) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto error; } memset( obj, 0x0, sizeof(OBJECT) ); memcpy( &obj->class, data + offset, sizeof(CK_OBJECT_CLASS_32) ); offset += sizeof(CK_OBJECT_CLASS_32); memcpy( &count, data + offset, sizeof(CK_ULONG_32) ); offset += sizeof(CK_ULONG_32); memcpy( &obj->name, data + offset, 8 ); offset += 8; rc = template_unflatten_withSize( &tmpl, data + offset, count, data_size ); if (rc != CKR_OK){ TRACE_DEVEL("template_unflatten_withSize failed.\n"); goto error; } obj->template = tmpl; if (replace == FALSE) { *new_obj = obj; } else { template_free( (*new_obj)->template ); memcpy( *new_obj, obj, sizeof(OBJECT) ); free( obj ); // don't want to do object_free() here! } return CKR_OK; error: if (obj) object_free( obj ); if (tmpl) template_free( tmpl ); return rc; } // // CK_RV object_create_skel( CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_ULONG mode, CK_ULONG class, CK_ULONG subclass, OBJECT ** obj ) { TEMPLATE * tmpl = NULL; TEMPLATE * tmpl2 = NULL; OBJECT * o = NULL; CK_RV rc; if (!obj){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (!pTemplate && (ulCount != 0)){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } o = (OBJECT *)malloc(sizeof(OBJECT)); tmpl = (TEMPLATE *)malloc(sizeof(TEMPLATE)); tmpl2 = (TEMPLATE *)malloc(sizeof(TEMPLATE)); if (!o || !tmpl || !tmpl2) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memset( o, 0x0, sizeof(OBJECT) ); memset( tmpl, 0x0, sizeof(TEMPLATE) ); memset( tmpl2, 0x0, sizeof(TEMPLATE) ); rc = template_add_attributes( tmpl2, pTemplate, ulCount ); if (rc != CKR_OK) goto done; // at this point, the new template has the list of attributes. we need // to do some more checking now: // 1) invalid attribute values // 2) missing required attributes // 3) attributes inappropriate for the object class // 4) conflicting attributes/values // rc = template_validate_attributes( tmpl2, class, subclass, mode ); if (rc != CKR_OK){ TRACE_DEVEL("template_validate_attributes failed.\n"); goto done; } rc = template_check_required_attributes( tmpl2, class, subclass, mode ); if (rc != CKR_OK){ TRACE_DEVEL("template_check_required_attributes failed.\n"); goto done; } rc = template_add_default_attributes( tmpl, tmpl2, class, subclass, mode ); if (rc != CKR_OK) goto done; rc = template_merge( tmpl, &tmpl2 ); if (rc != CKR_OK){ TRACE_DEVEL("template_merge failed.\n"); goto done; } // at this point, we should have a valid object with correct attributes // o->template = tmpl; *obj = o; return CKR_OK; done: if (o) free( o ); if (tmpl) template_free( tmpl ); if (tmpl2) template_free( tmpl2 ); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/common/asn1.c0000755000175000017500000015334712630407154020276 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // ASN.1 encoding/decoding routines // // This code is a mess... // #include #include #include // for memcmp() et al #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" // // CK_ULONG ber_encode_INTEGER( CK_BBOOL length_only, CK_BYTE ** ber_int, CK_ULONG * ber_int_len, CK_BYTE * data, CK_ULONG data_len ) { CK_BYTE *buf = NULL; CK_ULONG len; // if data_len < 127 use short-form length id // if data_len < 256 use long-form length id with 1-byte length field // if data_len < 65536 use long-form length id with 2-byte length field // if data_len < 16777216 use long-form length id with 3-byte length field // if (data_len < 128) len = 1 + 1 + data_len; else if (data_len < 256) len = 1 + (1 + 1) + data_len; else if (data_len < (1 << 16)) len = 1 + (1 + 2) + data_len; else if (data_len < (1 << 24)) len = 1 + (1 + 3) + data_len; else{ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *ber_int_len = len; return CKR_OK; } buf = (CK_BYTE *)malloc( len ); if (!buf){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } if (data_len < 128) { buf[0] = 0x02; buf[1] = data_len; memcpy( &buf[2], data, data_len ); *ber_int_len = len; *ber_int = buf; return CKR_OK; } if (data_len < 256) { buf[0] = 0x02; buf[1] = 0x81; buf[2] = data_len; memcpy( &buf[3], data, data_len ); *ber_int_len = len; *ber_int = buf; return CKR_OK; } if (data_len < (1 << 16)) { buf[0] = 0x02; buf[1] = 0x82; buf[2] = (data_len >> 8) & 0xFF; buf[3] = (data_len ) & 0xFF; memcpy( &buf[4], data, data_len ); *ber_int_len = len; *ber_int = buf; return CKR_OK; } if (data_len < (1 << 24)) { buf[0] = 0x02; buf[1] = 0x83; buf[2] = (data_len >> 16) & 0xFF; buf[3] = (data_len >> 8) & 0xFF; buf[4] = (data_len ) & 0xFF; memcpy( &buf[5], data, data_len ); *ber_int_len = len; *ber_int = buf; return CKR_OK; } // we should never reach this // free( buf ); TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV ber_decode_INTEGER( CK_BYTE * ber_int, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len ) { CK_ULONG len, length_octets; if (!ber_int){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } if (ber_int[0] != 0x02){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // short form lengths are easy // if ((ber_int[1] & 0x80) == 0) { len = ber_int[1] & 0x7F; *data = &ber_int[2]; *data_len = len; *field_len = 1 + 1 + len; return CKR_OK; } length_octets = ber_int[1] & 0x7F; if (length_octets == 1) { len = ber_int[2]; *data = &ber_int[3]; *data_len = len; *field_len = 1 + (1 + 1) + len; return CKR_OK; } if (length_octets == 2) { len = ber_int[2]; len = len << 8; len |= ber_int[3]; *data = &ber_int[4]; *data_len = len; *field_len = 1 + (1 + 2) + len; return CKR_OK; } if (length_octets == 3) { len = ber_int[2]; len = len << 8; len |= ber_int[3]; len = len << 8; len |= ber_int[4]; *data = &ber_int[5]; *data_len = len; *field_len = 1 + (1 + 3) + len; return CKR_OK; } // > 3 length octets implies a length > 16MB which isn't possible for // the coprocessor // TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV ber_encode_OCTET_STRING( CK_BBOOL length_only, CK_BYTE ** str, CK_ULONG * str_len, CK_BYTE * data, CK_ULONG data_len ) { CK_BYTE *buf = NULL; CK_ULONG len; // I only support Primitive encoding for OCTET STRINGS // // if data_len < 128 use short-form length id // if data_len < 256 use long-form length id with 1-byte length field // if data_len < 65536 use long-form length id with 2-byte length field // if (data_len < 128) len = 1 + 1 + data_len; else if (data_len < 256) len = 1 + (1 + 1) + data_len; else if (data_len < (1 << 16)) len = 1 + (1 + 2) + data_len; else if (data_len < (1 << 24)) len = 1 + (1 + 3) + data_len; else{ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *str_len = len; return CKR_OK; } buf = (CK_BYTE *)malloc( len ); if (!buf){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } if (data_len < 128) { buf[0] = 0x04; // primitive, OCTET STRING buf[1] = data_len; memcpy( &buf[2], data, data_len ); *str_len = len; *str = buf; return CKR_OK; } if (data_len < 256) { buf[0] = 0x04; // primitive, OCTET STRING buf[1] = 0x81; // length header -- 1 length octets buf[2] = data_len; memcpy( &buf[3], data, data_len ); *str_len = len; *str = buf; return CKR_OK; } if (data_len < (1 << 16)) { buf[0] = 0x04; // primitive, OCTET STRING buf[1] = 0x82; // length header -- 2 length octets buf[2] = (data_len >> 8) & 0xFF; buf[3] = (data_len ) & 0xFF; memcpy( &buf[4], data, data_len ); *str_len = len; *str = buf; return CKR_OK; } if (data_len < (1 << 24)) { buf[0] = 0x04; // primitive, OCTET STRING buf[1] = 0x83; // length header -- 3 length octets buf[2] = (data_len >> 16) & 0xFF; buf[3] = (data_len >> 8) & 0xFF; buf[4] = (data_len ) & 0xFF; memcpy( &buf[5], data, data_len ); *str_len = len; *str = buf; return CKR_OK; } // we should never reach this // free( buf ); TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV ber_decode_OCTET_STRING( CK_BYTE * str, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len ) { CK_ULONG len, length_octets; // I only support decoding primitive OCTET STRINGS // if (!str){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (str[0] != 0x04){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // short form lengths are easy // if ((str[1] & 0x80) == 0) { len = str[1] & 0x7F; *data = &str[2]; *data_len = len; *field_len = 1 + (1) + len; return CKR_OK; } length_octets = str[1] & 0x7F; if (length_octets == 1) { len = str[2]; *data = &str[3]; *data_len = len; *field_len = 1 + (1 + 1) + len; return CKR_OK; } if (length_octets == 2) { len = str[2]; len = len << 8; len |= str[3]; *data = &str[4]; *data_len = len; *field_len = 1 + (1 + 2) + len; return CKR_OK; } if (length_octets == 3) { len = str[2]; len = len << 8; len |= str[3]; len = len << 8; len |= str[4]; *data = &str[5]; *data_len = len; *field_len = 1 + (1 + 3) + len; return CKR_OK; } // > 3 length octets implies a length > 16MB // TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV ber_encode_SEQUENCE( CK_BBOOL length_only, CK_BYTE ** seq, CK_ULONG * seq_len, CK_BYTE * data, CK_ULONG data_len ) { CK_BYTE *buf = NULL; CK_ULONG len; // if data_len < 127 use short-form length id // if data_len < 65536 use long-form length id with 2-byte length field // if (data_len < 128) len = 1 + 1 + data_len; else if (data_len < 256) len = 1 + (1 + 1) + data_len; else if (data_len < (1 << 16)) len = 1 + (1 + 2) + data_len; else if (data_len < (1 << 24)) len = 1 + (1 + 3) + data_len; else{ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *seq_len = len; return CKR_OK; } buf = (CK_BYTE *)malloc( len ); if (!buf){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } if (data_len < 128) { buf[0] = 0x30; // constructed, SEQUENCE buf[1] = data_len; memcpy( &buf[2], data, data_len ); *seq_len = len; *seq = buf; return CKR_OK; } if (data_len < 256) { buf[0] = 0x30; // constructed, SEQUENCE buf[1] = 0x81; // length header -- 1 length octets buf[2] = data_len; memcpy( &buf[3], data, data_len ); *seq_len = len; *seq = buf; return CKR_OK; } if (data_len < (1 << 16)) { buf[0] = 0x30; // constructed, SEQUENCE buf[1] = 0x82; // length header -- 2 length octets buf[2] = (data_len >> 8) & 0xFF; buf[3] = (data_len ) & 0xFF; memcpy( &buf[4], data, data_len ); *seq_len = len; *seq = buf; return CKR_OK; } if (data_len < (1 << 24)) { buf[0] = 0x30; // constructed, SEQUENCE buf[1] = 0x83; // length header -- 3 length octets buf[2] = (data_len >> 16) & 0xFF; buf[3] = (data_len >> 8) & 0xFF; buf[4] = (data_len ) & 0xFF; memcpy( &buf[5], data, data_len ); *seq_len = len; *seq = buf; return CKR_OK; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV ber_decode_SEQUENCE( CK_BYTE * seq, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len ) { CK_ULONG len, length_octets; if (!seq){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (seq[0] != 0x30){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // short form lengths are easy // if ((seq[1] & 0x80) == 0) { len = seq[1] & 0x7F; *data = &seq[2]; *data_len = len; *field_len = 1 + (1) + len; return CKR_OK; } length_octets = seq[1] & 0x7F; if (length_octets == 1) { len = seq[2]; *data = &seq[3]; *data_len = len; *field_len = 1 + (1 + 1) + len; return CKR_OK; } if (length_octets == 2) { len = seq[2]; len = len << 8; len |= seq[3]; *data = &seq[4]; *data_len = len; *field_len = 1 + (1 + 2) + len; return CKR_OK; } if (length_octets == 3) { len = seq[2]; len = len << 8; len |= seq[3]; len = len << 8; len |= seq[4]; *data = &seq[5]; *data_len = len; *field_len = 1 + (1 + 3) + len; return CKR_OK; } // > 3 length octets implies a length > 16MB // TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // PrivateKeyInfo ::= SEQUENCE { // version Version -- always '0' for now // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier // privateKey PrivateKey // attributes // } // CK_RV ber_encode_PrivateKeyInfo( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len, CK_BYTE * algorithm_id, CK_ULONG algorithm_id_len, CK_BYTE * priv_key, CK_ULONG priv_key_len ) { CK_BYTE * buf = NULL; CK_BYTE * tmp = NULL; CK_BYTE version[] = { 0 }; CK_ULONG len, total; CK_RV rc; len = 0; rc = ber_encode_INTEGER( TRUE, NULL, &total, version, sizeof(version) ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); return rc; } else len += total; len += algorithm_id_len; rc = ber_encode_OCTET_STRING( TRUE, NULL, &total, priv_key, priv_key_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_OCTET_STRING failed\n"); return rc; } else len += total; // for this stuff, attributes can be suppressed. // if (length_only == TRUE) { rc = ber_encode_SEQUENCE( TRUE, NULL, &total, NULL, len ); if (rc == CKR_OK) *data_len = total; if (rc != CKR_OK) TRACE_DEVEL("ber_encode_SEQUENCE failed\n"); return rc; } buf = (CK_BYTE *)malloc(len); if (!buf){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } len = 0; rc = ber_encode_INTEGER( FALSE, &tmp, &total, version, sizeof(version) ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+len, tmp, total ); len += total; free( tmp ); memcpy( buf+len, algorithm_id, algorithm_id_len ); len += algorithm_id_len; rc = ber_encode_OCTET_STRING( FALSE, &tmp, &total, priv_key, priv_key_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_OCTET_STRING failed\n"); goto error; } memcpy( buf+len, tmp, total ); len += total; free( tmp ); rc = ber_encode_SEQUENCE( FALSE, data, data_len, buf, len ); if (rc != CKR_OK) TRACE_DEVEL("ber_encode_SEQUENCE failed\n"); error: free( buf ); return rc; } // // CK_RV ber_decode_PrivateKeyInfo( CK_BYTE * data, CK_ULONG data_len, CK_BYTE ** algorithm, CK_ULONG * alg_len, CK_BYTE ** priv_key ) { CK_BYTE *buf = NULL; CK_BYTE *alg = NULL; CK_BYTE *ver = NULL; CK_ULONG buf_len, offset, len, field_len; CK_RV rc; if (!data || (data_len == 0)){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = ber_decode_SEQUENCE( data, &buf, &buf_len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_SEQUENCE failed\n"); return rc; } // version -- we just ignore this // offset = 0; rc = ber_decode_INTEGER( buf+offset, &ver, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); return rc; } offset += field_len; // 'buf' is now pointing to the PrivateKeyAlgorithmIdentifier // rc = ber_decode_SEQUENCE( buf+offset, &alg, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_SEQUENCE failed\n"); return rc; } *algorithm = alg; *alg_len = len; rc = ber_decode_OCTET_STRING( alg + len, priv_key, &buf_len, &field_len ); if (rc != CKR_OK) TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); return rc; } // RSAPrivateKey ::= SEQUENCE { // version Version -- always '0' for now // modulus INTEGER // publicExponent INTEGER // if secure key // opaque OCTET_STRING // else // privateExponent INTEGER // prime1 INTEGER // prime2 INTEGER // exponent1 INTEGER // exponent2 INTEGER // coefficient INTEGER // } // CK_RV ber_encode_RSAPrivateKey( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len, CK_ATTRIBUTE * modulus, CK_ATTRIBUTE * publ_exp, CK_ATTRIBUTE * priv_exp, CK_ATTRIBUTE * prime1, CK_ATTRIBUTE * prime2, CK_ATTRIBUTE * exponent1, CK_ATTRIBUTE * exponent2, CK_ATTRIBUTE * coeff, CK_ATTRIBUTE * opaque ) { CK_BYTE *buf = NULL; CK_BYTE *buf2 = NULL; CK_ULONG len, offset; CK_BYTE version[] = { 0 }; CK_RV rc; offset = 0; rc = 0; rc |= ber_encode_INTEGER( TRUE, NULL, &len, NULL, sizeof(version) ); offset += len; rc |= ber_encode_INTEGER( TRUE, NULL, &len, NULL, modulus->ulValueLen ); offset += len; rc |= ber_encode_INTEGER( TRUE, NULL, &len, NULL, publ_exp->ulValueLen ); offset += len; if (opaque != NULL) { rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, opaque->ulValueLen); offset += len; } else { rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, priv_exp->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime1->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, prime2->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, exponent1->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, exponent2->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, coeff->ulValueLen); offset += len; } if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { rc = ber_encode_SEQUENCE( TRUE, NULL, &len, NULL, offset ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_SEQUENCE failed\n"); return rc; } rc = ber_encode_PrivateKeyInfo( TRUE, NULL, data_len, NULL, ber_AlgIdRSAEncryptionLen, NULL, len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_PrivateKeyInfo failed\n"); return rc; } return rc; } buf = (CK_BYTE *)malloc(offset); if (!buf){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } offset = 0; rc = 0; rc = ber_encode_INTEGER( FALSE, &buf2, &len, version, sizeof(version) ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); rc = ber_encode_INTEGER( FALSE, &buf2, &len, (CK_BYTE *)modulus + sizeof(CK_ATTRIBUTE), modulus->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); rc = ber_encode_INTEGER( FALSE, &buf2, &len, (CK_BYTE *)publ_exp + sizeof(CK_ATTRIBUTE), publ_exp->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); if (opaque != NULL) { // the CKA_IBM_OPAQUE attrib rc = ber_encode_OCTET_STRING( FALSE, &buf2, &len, (CK_BYTE *)opaque + sizeof(CK_ATTRIBUTE), opaque->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_OCTET_STRING failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); } else { rc = ber_encode_INTEGER( FALSE, &buf2, &len, (CK_BYTE *)priv_exp + sizeof(CK_ATTRIBUTE), priv_exp->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); rc = ber_encode_INTEGER( FALSE, &buf2, &len, (CK_BYTE *)prime1 + sizeof(CK_ATTRIBUTE), prime1->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); rc = ber_encode_INTEGER( FALSE, &buf2, &len, (CK_BYTE *)prime2 + sizeof(CK_ATTRIBUTE), prime2->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); rc = ber_encode_INTEGER( FALSE, &buf2, &len, (CK_BYTE *)exponent1 + sizeof(CK_ATTRIBUTE), exponent1->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); rc = ber_encode_INTEGER( FALSE, &buf2, &len, (CK_BYTE *)exponent2 + sizeof(CK_ATTRIBUTE), exponent2->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); rc = ber_encode_INTEGER( FALSE, &buf2, &len, (CK_BYTE *)coeff + sizeof(CK_ATTRIBUTE), coeff->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, buf2, len ); offset += len; free( buf2 ); } rc = ber_encode_SEQUENCE( FALSE, &buf2, &len, buf, offset ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_SEQUENCE failed\n"); goto error; } rc = ber_encode_PrivateKeyInfo( FALSE, data, data_len, ber_AlgIdRSAEncryption, ber_AlgIdRSAEncryptionLen, buf2, len ); if (rc != CKR_OK) { TRACE_ERROR("ber_encode_PrivateKeyInfo failed\n"); } error: if (buf2) free( buf2 ); if (buf) free( buf ); return rc; } // // CK_RV ber_decode_RSAPrivateKey( CK_BYTE * data, CK_ULONG data_len, CK_ATTRIBUTE ** modulus, CK_ATTRIBUTE ** publ_exp, CK_ATTRIBUTE ** priv_exp, CK_ATTRIBUTE ** prime1, CK_ATTRIBUTE ** prime2, CK_ATTRIBUTE ** exponent1, CK_ATTRIBUTE ** exponent2, CK_ATTRIBUTE ** coeff, CK_ATTRIBUTE ** opaque, CK_BBOOL isopaque ) { CK_ATTRIBUTE *n_attr = NULL; CK_ATTRIBUTE *e_attr = NULL; CK_ATTRIBUTE *d_attr = NULL; CK_ATTRIBUTE *p_attr = NULL; CK_ATTRIBUTE *q_attr = NULL; CK_ATTRIBUTE *e1_attr = NULL; CK_ATTRIBUTE *e2_attr = NULL; CK_ATTRIBUTE *coeff_attr = NULL; CK_ATTRIBUTE *o_attr = NULL; CK_BYTE *alg = NULL; CK_BYTE *rsa_priv_key = NULL; CK_BYTE *buf = NULL; CK_BYTE *tmp = NULL; CK_ULONG offset, buf_len, field_len, len; CK_RV rc; rc = ber_decode_PrivateKeyInfo( data, data_len, &alg, &len, &rsa_priv_key ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n"); return rc; } // make sure we're dealing with an RSA key // if (memcmp(alg, ber_rsaEncryption, ber_rsaEncryptionLen) != 0){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; // probably ought to use a different error } rc = ber_decode_SEQUENCE( rsa_priv_key, &buf, &buf_len, &field_len ); if (rc != CKR_OK) return rc; // parse the RSAPrivateKey // offset = 0; // Version // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // modulus // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // public exponent // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; if (isopaque) { // opaque attribute, the CCA key // rc = ber_decode_OCTET_STRING( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); goto cleanup; } offset += field_len; } else { // private exponent // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // prime #1 // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // prime #2 // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // exponent #1 // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // exponent #2 // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // coefficient // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; if (offset > buf_len){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } } // // it looks okay. build the attributes // offset = 0; // skip the version // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // modulus // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_MODULUS, tmp, len, &n_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // public exponent // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_PUBLIC_EXPONENT, tmp, len, &e_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } if (isopaque) { // opaque attribute, the CCA key // rc = ber_decode_OCTET_STRING( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); goto cleanup; } else { rc = build_attribute( CKA_IBM_OPAQUE, tmp, len, &o_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } *opaque = o_attr; } else { // private exponent // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_PRIVATE_EXPONENT, tmp, len, &d_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // prime #1 // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_PRIME_1, tmp, len, &p_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // prime #2 // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_PRIME_2, tmp, len, &q_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // exponent #1 // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_EXPONENT_1, tmp, len, &e1_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // exponent #2 // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_EXPONENT_2, tmp, len, &e2_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // coefficient // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_COEFFICIENT, tmp, len, &coeff_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += len; } *priv_exp = d_attr; *prime1 = p_attr; *prime2 = q_attr; *exponent1 = e1_attr; *exponent2 = e2_attr; *coeff = coeff_attr; } *modulus = n_attr; *publ_exp = e_attr; return CKR_OK; cleanup: if (n_attr) free(n_attr); if (e_attr) free(e_attr); if (isopaque) { if (o_attr) free(o_attr); } else { if (d_attr) free(d_attr); if (p_attr) free(p_attr); if (q_attr) free(q_attr); if (e1_attr) free(e1_attr); if (e2_attr) free(e2_attr); if (coeff_attr) free(coeff_attr); } return rc; } // DSA is a little different from RSA // // DSAPrivateKey ::= INTEGER // // The 'parameters' field of the AlgorithmIdentifier are as follows: // // DSSParameters ::= SEQUENCE { // prime1 INTEGER // prime2 INTEGER // base INTEGER // } // CK_RV ber_encode_DSAPrivateKey( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len, CK_ATTRIBUTE * prime1, CK_ATTRIBUTE * prime2, CK_ATTRIBUTE * base, CK_ATTRIBUTE * priv_key ) { CK_BYTE *param = NULL; CK_BYTE *buf = NULL; CK_BYTE *tmp = NULL; CK_BYTE *alg = NULL; CK_ULONG offset, len, param_len; CK_ULONG alg_len; CK_RV rc; // build the DSS parameters first // offset = 0; rc = 0; rc |= ber_encode_INTEGER( TRUE, NULL, &len, NULL, prime1->ulValueLen ); offset += len; rc |= ber_encode_INTEGER( TRUE, NULL, &len, NULL, prime2->ulValueLen ); offset += len; rc |= ber_encode_INTEGER( TRUE, NULL, &len, NULL, base->ulValueLen ); offset += len; if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { rc = ber_encode_SEQUENCE( TRUE, NULL, ¶m_len, NULL, offset ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_SEQUENCE failed\n"); return rc; } rc = ber_encode_INTEGER( TRUE, NULL, &len, NULL, priv_key->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); return rc; } rc = ber_encode_PrivateKeyInfo( TRUE, NULL, data_len, NULL, ber_idDSALen + param_len, NULL, len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_PrivateKeyInfo failed\n"); } return rc; } // 'buf' will be the sequence data for the AlgorithmIdentifyer::parameter // buf = (CK_BYTE *)malloc(offset); if (!buf){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } len = 0; offset = 0; rc = ber_encode_INTEGER( FALSE, &tmp, &len, (CK_BYTE *)prime1 + sizeof(CK_ATTRIBUTE), prime1->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, tmp, len ); offset += len; free( tmp ); tmp = NULL; rc = ber_encode_INTEGER( FALSE, &tmp, &len, (CK_BYTE *)prime2 + sizeof(CK_ATTRIBUTE), prime2->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, tmp, len ); offset += len; free( tmp ); tmp = NULL; rc = ber_encode_INTEGER( FALSE, &tmp, &len, (CK_BYTE *)base + sizeof(CK_ATTRIBUTE), base->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } memcpy( buf+offset, tmp, len ); offset += len; free( tmp ); tmp = NULL; rc = ber_encode_SEQUENCE( FALSE, ¶m, ¶m_len, buf, offset ); if (rc != CKR_OK) { TRACE_DEVEL("ber_encode_SEQUENCE failed\n"); free(buf); return rc; } free( buf ); buf = NULL; // Build the DSA AlgorithmIdentifier // // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER // parameters ANY DEFINED BY algorithm OPTIONAL // } // len = ber_idDSALen + param_len; buf = (CK_BYTE *)malloc( len ); if (!buf){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto error; } memcpy( buf, ber_idDSA, ber_idDSALen ); memcpy( buf + ber_idDSALen, param, param_len ); free( param ); param = NULL; rc = ber_encode_SEQUENCE( FALSE, &alg, &alg_len, buf, len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_SEQUENCE failed\n"); goto error; } free( buf ); buf = NULL; // build the private key INTEGER // rc = ber_encode_INTEGER( FALSE, &buf, &len, (CK_BYTE *)priv_key + sizeof(CK_ATTRIBUTE), priv_key->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_INTEGER failed\n"); goto error; } rc = ber_encode_PrivateKeyInfo( FALSE, data, data_len, alg, alg_len, buf, len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_encode_PrivateKeyInfo failed\n"); goto error; } error: if (alg) free( alg ); if (buf) free( buf ); if (param) free( param ); if (tmp) free( tmp ); return rc; } // // CK_RV ber_decode_DSAPrivateKey( CK_BYTE * data, CK_ULONG data_len, CK_ATTRIBUTE ** prime, CK_ATTRIBUTE ** subprime, CK_ATTRIBUTE ** base, CK_ATTRIBUTE ** priv_key ) { CK_ATTRIBUTE *p_attr = NULL; CK_ATTRIBUTE *q_attr = NULL; CK_ATTRIBUTE *g_attr = NULL; CK_ATTRIBUTE *x_attr = NULL; CK_BYTE *alg = NULL; CK_BYTE *buf = NULL; CK_BYTE *dsakey = NULL; CK_BYTE *tmp = NULL; CK_ULONG buf_len, field_len, len, offset; CK_RV rc; rc = ber_decode_PrivateKeyInfo( data, data_len, &alg, &len, &dsakey ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n"); return rc; } // make sure we're dealing with a DSA key. just compare the OBJECT // IDENTIFIER // if (memcmp(alg, ber_idDSA, ber_idDSALen) != 0){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // extract the parameter data into ATTRIBUTES // rc = ber_decode_SEQUENCE( alg + ber_idDSALen, &buf, &buf_len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_SEQUENCE failed\n"); return rc; } offset = 0; // prime // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // subprime // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; // base // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } offset += field_len; if (offset > buf_len){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // it looks okay. build the attributes // offset = 0; // prime // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_PRIME, tmp, len, &p_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // subprime // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_SUBPRIME, tmp, len, &q_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // base // rc = ber_decode_INTEGER( buf+offset, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_BASE, tmp, len, &g_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } // now get the private key // rc = ber_decode_INTEGER( dsakey, &tmp, &len, &field_len ); if (rc != CKR_OK){ TRACE_DEVEL("ber_decode_INTEGER failed\n"); goto cleanup; } else { rc = build_attribute( CKA_VALUE, tmp, len, &x_attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto cleanup; } offset += field_len; } *prime = p_attr; *subprime = q_attr; *base = g_attr; *priv_key = x_attr; return CKR_OK; cleanup: if (p_attr) free(p_attr); if (q_attr) free(q_attr); if (g_attr) free(g_attr); if (x_attr) free(x_attr); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/common/attributes.c0000644000175000017500000000540212630407154021603 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token - LDAP functions * * (C) COPYRIGHT International Business Machines Corp. 2012 * * Author: Marcelo Cerri (mhcerri@br.ibm.com) * */ #include #include #include "attributes.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" /* * Free an array of attributes allocated with dup_attribute_array(). */ void free_attribute_array(CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len) { CK_ULONG i; if (!attrs) return; for (i = 0; i < attrs_len; i++) if (attrs[i].pValue) free(attrs[i].pValue); free(attrs); } /* * Duplicate an array of attributes and all its values. * * The returned array must be freed with free_attribute_array(). */ CK_RV dup_attribute_array(CK_ATTRIBUTE_PTR orig, CK_ULONG orig_len, CK_ATTRIBUTE_PTR *p_dest, CK_ULONG *p_dest_len) { CK_RV rc = CKR_OK; CK_ATTRIBUTE_PTR dest; CK_ULONG dest_len; CK_ATTRIBUTE_PTR it; /* Allocate the new array */ dest_len = orig_len; dest = malloc(dest_len * sizeof(*dest)); if (dest == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(dest, 0, dest_len); /* Copy each element */ for (it = dest; it != (dest + orig_len); it++, orig++) { it->type = orig->type; it->ulValueLen = orig->ulValueLen; it->pValue = malloc(it->ulValueLen); if (it->pValue == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(it->pValue, orig->pValue, orig->ulValueLen); } done: if (rc == CKR_OK) { *p_dest = dest; *p_dest_len = dest_len; } else { free_attribute_array(dest, dest_len); } return rc; } /* * Return the attribute structure for a given type. */ CK_ATTRIBUTE_PTR get_attribute_by_type(CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_ULONG type) { CK_ATTRIBUTE_PTR it; for (it = attrs; it != attrs + attrs_len; it++) if (it->type == type) return it; return NULL; } /* * Reallocate the attribute array and add the new element. */ CK_RV add_to_attribute_array(CK_ATTRIBUTE_PTR *p_attrs, CK_ULONG_PTR p_attrs_len, CK_ULONG type, CK_BYTE_PTR value, CK_ULONG value_len) { CK_ATTRIBUTE_PTR attrs; CK_BYTE_PTR copied_value; copied_value = malloc(value_len); if (copied_value == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy(copied_value, value, value_len); attrs = realloc(*p_attrs, sizeof(**p_attrs) * (*p_attrs_len + 1)); if (attrs == NULL) { free(copied_value); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } attrs[*p_attrs_len].type = type; attrs[*p_attrs_len].pValue = copied_value; attrs[*p_attrs_len].ulValueLen= value_len; *p_attrs = attrs; *p_attrs_len += 1; return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/sw_crypt.c0000644000175000017500000004105512630407154021273 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "p11util.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" #include "sw_crypt.h" CK_RV sw_des3_cbc(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *init_v, CK_BYTE *key_value, CK_BYTE encrypt) { des_key_schedule des_key1; des_key_schedule des_key2; des_key_schedule des_key3; const_des_cblock key_SSL1, key_SSL2, key_SSL3; des_cblock ivec; // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } // The key as passed in is a 24 byte string containing 3 keys // pick it apart and create the key schedules memcpy(&key_SSL1, key_value, (size_t)8); memcpy(&key_SSL2, key_value+8, (size_t)8); memcpy(&key_SSL3, key_value+16, (size_t)8); des_set_key_unchecked(&key_SSL1, des_key1); des_set_key_unchecked(&key_SSL2, des_key2); des_set_key_unchecked(&key_SSL3, des_key3); memcpy(ivec, init_v, sizeof(ivec)); // Encrypt or decrypt the data if (encrypt) { des_ede3_cbc_encrypt(in_data, out_data, in_data_len, des_key1, des_key2, des_key3, &ivec, DES_ENCRYPT); *out_data_len = in_data_len; } else { des_ede3_cbc_encrypt(in_data, out_data, in_data_len, des_key1, des_key2, des_key3, &ivec, DES_DECRYPT); *out_data_len = in_data_len; } return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/sign_mgr.c0000755000175000017500000014030312630407154021225 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: sign_mgr.c // // Signature manager routines // #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV sign_mgr_init( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_KEY_TYPE keytype; CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active != FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } // key usage restrictions // rc = object_mgr_find_in_map1( key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle.\n"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } // is key allowed to generate signatures? // rc = template_attribute_find( key_obj->template, CKA_SIGN, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_SIGN for the key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } else { flag = *(CK_BBOOL *)attr->pValue; if (flag != TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_FUNCTION_NOT_PERMITTED)); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } // is the mechanism supported? is the key type correct? is a // parameter present if required? is the key size allowed? // is the key allowed to generate signatures? // switch (mech->mechanism) { case CKM_RSA_X_509: case CKM_RSA_PKCS: case CKM_RSA_PKCS_PSS: { if (mech->mechanism == CKM_RSA_PKCS_PSS) { rc = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } rc = check_pss_params(mech, attr->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("check_pss_params() failed.\n"); return rc; } } else { if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PRIVATE key // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; // if it's not a private RSA key then we have an internal failure...means // that somehow a public key got assigned a CKA_SIGN attribute // if (class != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } // PKCS #11 doesn't allow multi-part RSA operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_ECDSA: case CKM_ECDSA_SHA1: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_EC){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PRIVATE key // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if (mech->mechanism == CKM_ECDSA) { ctx->context_len = 0; ctx->context = NULL; } else { ctx->context_len = sizeof(RSA_DIGEST_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(RSA_DIGEST_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(RSA_DIGEST_CONTEXT)); } } break; #if !(NOMD2) case CKM_MD2_RSA_PKCS: #endif case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PRIVATE key operation // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } ctx->context_len = sizeof(RSA_DIGEST_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(RSA_DIGEST_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(RSA_DIGEST_CONTEXT)); } break; case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: { rc = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } rc = check_pss_params(mech, attr->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("check_pss_params failed.\n"); return rc; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PRIVATE key operation // flag = template_attribute_find(key_obj->template, CKA_CLASS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PRIVATE_KEY) { TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } ctx->context_len = sizeof(DIGEST_CONTEXT); ctx->context = (CK_BYTE *)malloc(ctx->context_len); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(ctx->context, 0x0, ctx->context_len); } break; #if !(NODSA) case CKM_DSA: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DSA){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // must be a PRIVATE key // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; // if it's not a private RSA key then we have an internal failure...means // that somehow a public key got assigned a CKA_SIGN attribute // if (class != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } // PKCS #11 doesn't allow multi-part DSA operations // ctx->context_len = 0; ctx->context = NULL; } break; #endif #if !(NOMD2) case CKM_MD2_HMAC: #endif case CKM_MD5_HMAC: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } /* Note: It was previously believed that pkcs#11 did not * support hmac multipart. As a result, those tokens using the * locally implemented hmac helper functions do not support * multipart hmac. */ ctx->context_len = 0; ctx->context = NULL; } break; case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // PKCS #11 doesn't allow multi-part HMAC operations // ctx->context_len = 0; ctx->context = NULL; rc = hmac_sign_init(sess, mech, key); if (rc != CKR_OK) { TRACE_ERROR("Failed to initialize hmac.\n"); return rc; } } break; #if !(NOMD2) case CKM_MD2_HMAC_GENERAL: #endif case CKM_MD5_HMAC_GENERAL: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } #if !(NOMD2) if ((mech->mechanism == CKM_MD2_HMAC_GENERAL) && (*param > 16)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } #endif if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && (*param > 16)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("A generic secret key is required.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } // PKCS #11 doesn't allow multi-part HMAC operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) && (*param > 20)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_SHA256_HMAC_GENERAL) && (*param > 32)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_SHA384_HMAC_GENERAL) && (*param > 48)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if ((mech->mechanism == CKM_SHA512_HMAC_GENERAL) && (*param > 64)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("A generic secret key is required.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } /* Note: It was previously believed that pkcs#11 did not * support hmac multipart. As a result, those tokens using the * locally implemented hmac helper functions do not support * multipart hmac. */ ctx->context_len = 0; ctx->context = NULL; rc = hmac_sign_init(sess, mech, key); if (rc != CKR_OK) { TRACE_ERROR("Failed to initialize hmac.\n"); return rc; } } break; case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: { CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // FIXME - Netscape sets the parameter == 16. PKCS #11 limit is 8 // if (mech->mechanism == CKM_SSL3_MD5_MAC) { if (*param < 4 || *param > 16){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } if (mech->mechanism == CKM_SSL3_SHA1_MAC) { if (*param < 4 || *param > 20){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } rc = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_CLASS for the key.\n"); return CKR_FUNCTION_FAILED; } else { class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_SECRET_KEY){ TRACE_ERROR("This operation requires a secret key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } ctx->context_len = sizeof(SSL3_MAC_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(SSL3_MAC_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(SSL3_MAC_CONTEXT)); } break; case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: { if (mech->pParameter) { if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->mechanism == CKM_DES3_MAC_GENERAL) { if (*param < 1 || *param > DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } /* CKM_DES3_MAC should not have params */ else { return CKR_MECHANISM_PARAM_INVALID; } } ctx->context = (CK_BYTE *)malloc(sizeof(DES_DATA_CONTEXT)); ctx->context_len = sizeof(DES_DATA_CONTEXT); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_DATA_CONTEXT)); } break; case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: { if (mech->pParameter) { if (mech->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } CK_MAC_GENERAL_PARAMS *param = (CK_MAC_GENERAL_PARAMS *)mech->pParameter; if (mech->mechanism == CKM_AES_MAC_GENERAL) { if (*param < 1 || *param > AES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } } /* CKM_AES_MAC should not have params */ else return CKR_MECHANISM_PARAM_INVALID; } ctx->context = (CK_BYTE *)malloc(sizeof(AES_DATA_CONTEXT)); ctx->context_len = sizeof(AES_DATA_CONTEXT); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_DATA_CONTEXT)); } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (mech->ulParameterLen > 0) { ptr = (CK_BYTE *)malloc(mech->ulParameterLen); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, mech->pParameter, mech->ulParameterLen ); } ctx->key = key; ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = ptr; ctx->multi = FALSE; ctx->active = TRUE; ctx->recover = recover_mode; return CKR_OK; } // // CK_RV sign_mgr_cleanup( SIGN_VERIFY_CONTEXT *ctx ) { if (!ctx){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->recover = FALSE; ctx->context_len = 0; if (ctx->mech.pParameter) { free( ctx->mech.pParameter ); ctx->mech.pParameter = NULL; } if (ctx->context) { free( ctx->context ); ctx->context = NULL; } return CKR_OK; } // // CK_RV sign_mgr_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } // if the caller just wants the signature length, there is no reason to // specify the input data. I just need the input data length // if ((length_only == FALSE) && (!in_data || !out_data)){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->multi == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: return rsa_pkcs_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_RSA_X_509: return rsa_x509_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_RSA_PKCS_PSS: return rsa_pss_sign(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); #if !(NOMD2) case CKM_MD2_RSA_PKCS: #endif case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_sign(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); #if !(NODSA) case CKM_DSA: return dsa_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); #endif #if !(NOMD2) case CKM_MD2_HMAC: case CKM_MD2_HMAC_GENERAL: return md2_hmac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); #endif case CKM_MD5_HMAC: case CKM_MD5_HMAC_GENERAL: return md5_hmac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_SHA_1_HMAC: case CKM_SHA_1_HMAC_GENERAL: return sha1_hmac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_SHA256_HMAC: case CKM_SHA256_HMAC_GENERAL: return sha2_hmac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_SHA384_HMAC: case CKM_SHA384_HMAC_GENERAL: return sha3_hmac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_SHA512_HMAC: case CKM_SHA512_HMAC_GENERAL: return sha5_hmac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_ECDSA_SHA1: return ec_hash_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_ECDSA: return ec_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_DEVEL("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV sign_mgr_sign_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { if (!sess || !ctx) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } ctx->multi = TRUE; switch (ctx->mech.mechanism) { #if !(NOMD2) case CKM_MD2_RSA_PKCS: #endif case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_sign_update( sess, ctx, in_data, in_data_len ); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_update(sess, ctx, in_data, in_data_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_sign_update( sess, ctx, in_data, in_data_len ); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_sign_update( sess, ctx, in_data, in_data_len ); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_sign_update( sess, ctx, in_data, in_data_len ); case CKM_ECDSA_SHA1: return ec_hash_sign_update( sess, ctx, in_data, in_data_len ); case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: return hmac_sign_update(sess, in_data, in_data_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_DEVEL("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV sign_mgr_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG * sig_len ) { if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } switch (ctx->mech.mechanism) { #if !(NOMD2) case CKM_MD2_RSA_PKCS: #endif case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: return rsa_hash_pkcs_sign_final( sess, length_only, ctx, signature, sig_len ); case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: return rsa_hash_pss_sign_final(sess, length_only, ctx, signature, sig_len); case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: return ssl3_mac_sign_final( sess, length_only, ctx, signature, sig_len ); case CKM_DES3_MAC: case CKM_DES3_MAC_GENERAL: return des3_mac_sign_final( sess, length_only, ctx, signature, sig_len ); case CKM_AES_MAC: case CKM_AES_MAC_GENERAL: return aes_mac_sign_final( sess, length_only, ctx, signature, sig_len ); case CKM_ECDSA_SHA1: return ec_hash_sign_final (sess, length_only, ctx, signature, sig_len ); case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: return hmac_sign_final(sess, signature, sig_len); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_DEVEL("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV sign_mgr_sign_recover( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } if (ctx->recover == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } // if the caller just wants the signature length, there is no reason to // specify the input data. I just need the input data length // if ((length_only == FALSE) && (!in_data || !out_data)){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->multi == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_RSA_PKCS: // we can use the same sign mechanism to do sign-recover // return rsa_pkcs_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_RSA_X_509: return rsa_x509_sign( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_DEVEL("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } opencryptoki+dfsg/usr/lib/pkcs11/common/p11util.c0000755000175000017500000006722112630407154020726 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ #include #include #include #include "pkcs11types.h" #define _sym2str(X) case X: return #X // // p11_get_ckr - return textual interpretation of a CKR_ error code // @rc is the CKR_.. error // char *p11_get_ckr( CK_RV rc ) { switch (rc) { _sym2str(CKR_OK); _sym2str(CKR_CANCEL); _sym2str(CKR_HOST_MEMORY); _sym2str(CKR_SLOT_ID_INVALID); _sym2str(CKR_GENERAL_ERROR); _sym2str(CKR_FUNCTION_FAILED); _sym2str(CKR_ARGUMENTS_BAD); _sym2str(CKR_NO_EVENT); _sym2str(CKR_NEED_TO_CREATE_THREADS); _sym2str(CKR_CANT_LOCK); _sym2str(CKR_ATTRIBUTE_READ_ONLY); _sym2str(CKR_ATTRIBUTE_SENSITIVE); _sym2str(CKR_ATTRIBUTE_TYPE_INVALID); _sym2str(CKR_ATTRIBUTE_VALUE_INVALID); _sym2str(CKR_DATA_INVALID); _sym2str(CKR_DATA_LEN_RANGE); _sym2str(CKR_DEVICE_ERROR); _sym2str(CKR_DEVICE_MEMORY); _sym2str(CKR_DEVICE_REMOVED); _sym2str(CKR_ENCRYPTED_DATA_INVALID); _sym2str(CKR_ENCRYPTED_DATA_LEN_RANGE); _sym2str(CKR_FUNCTION_CANCELED); _sym2str(CKR_FUNCTION_NOT_PARALLEL); _sym2str(CKR_FUNCTION_NOT_SUPPORTED); _sym2str(CKR_KEY_HANDLE_INVALID); _sym2str(CKR_KEY_SIZE_RANGE); _sym2str(CKR_KEY_TYPE_INCONSISTENT); _sym2str(CKR_KEY_NOT_NEEDED); _sym2str(CKR_KEY_CHANGED); _sym2str(CKR_KEY_NEEDED); _sym2str(CKR_KEY_INDIGESTIBLE); _sym2str(CKR_KEY_FUNCTION_NOT_PERMITTED); _sym2str(CKR_KEY_NOT_WRAPPABLE); _sym2str(CKR_KEY_UNEXTRACTABLE); _sym2str(CKR_MECHANISM_INVALID); _sym2str(CKR_MECHANISM_PARAM_INVALID); _sym2str(CKR_OBJECT_HANDLE_INVALID); _sym2str(CKR_OPERATION_ACTIVE); _sym2str(CKR_OPERATION_NOT_INITIALIZED); _sym2str(CKR_PIN_INCORRECT); _sym2str(CKR_PIN_INVALID); _sym2str(CKR_PIN_LEN_RANGE); _sym2str(CKR_PIN_EXPIRED); _sym2str(CKR_PIN_LOCKED); _sym2str(CKR_SESSION_CLOSED); _sym2str(CKR_SESSION_COUNT); _sym2str(CKR_SESSION_HANDLE_INVALID); _sym2str(CKR_SESSION_PARALLEL_NOT_SUPPORTED); _sym2str(CKR_SESSION_READ_ONLY); _sym2str(CKR_SESSION_EXISTS); _sym2str(CKR_SESSION_READ_ONLY_EXISTS); _sym2str(CKR_SESSION_READ_WRITE_SO_EXISTS); _sym2str(CKR_SIGNATURE_INVALID); _sym2str(CKR_SIGNATURE_LEN_RANGE); _sym2str(CKR_TEMPLATE_INCOMPLETE); _sym2str(CKR_TEMPLATE_INCONSISTENT); _sym2str(CKR_TOKEN_NOT_PRESENT); _sym2str(CKR_TOKEN_NOT_RECOGNIZED); _sym2str(CKR_TOKEN_WRITE_PROTECTED); _sym2str(CKR_UNWRAPPING_KEY_HANDLE_INVALID); _sym2str(CKR_UNWRAPPING_KEY_SIZE_RANGE); _sym2str(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT); _sym2str(CKR_USER_ALREADY_LOGGED_IN); _sym2str(CKR_USER_NOT_LOGGED_IN); _sym2str(CKR_USER_PIN_NOT_INITIALIZED); _sym2str(CKR_USER_TYPE_INVALID); _sym2str(CKR_USER_ANOTHER_ALREADY_LOGGED_IN); _sym2str(CKR_USER_TOO_MANY_TYPES); _sym2str(CKR_WRAPPED_KEY_INVALID); _sym2str(CKR_WRAPPED_KEY_LEN_RANGE); _sym2str(CKR_WRAPPING_KEY_HANDLE_INVALID); _sym2str(CKR_WRAPPING_KEY_SIZE_RANGE); _sym2str(CKR_WRAPPING_KEY_TYPE_INCONSISTENT); _sym2str(CKR_RANDOM_SEED_NOT_SUPPORTED); _sym2str(CKR_RANDOM_NO_RNG); _sym2str(CKR_BUFFER_TOO_SMALL); _sym2str(CKR_SAVED_STATE_INVALID); _sym2str(CKR_INFORMATION_SENSITIVE); _sym2str(CKR_STATE_UNSAVEABLE); _sym2str(CKR_CRYPTOKI_NOT_INITIALIZED); _sym2str(CKR_CRYPTOKI_ALREADY_INITIALIZED); _sym2str(CKR_MUTEX_BAD); _sym2str(CKR_MUTEX_NOT_LOCKED); default: return "UNKNOWN"; } } // is_attribute_defined() // // determine whether the specified attribute is defined by Cryptoki // CK_BBOOL is_attribute_defined( CK_ATTRIBUTE_TYPE type ) { if (type >= CKA_VENDOR_DEFINED) return TRUE; switch (type) { case CKA_CLASS: case CKA_TOKEN: case CKA_PRIVATE: case CKA_LABEL: case CKA_APPLICATION: case CKA_VALUE: case CKA_CERTIFICATE_TYPE: case CKA_ISSUER: case CKA_SERIAL_NUMBER: case CKA_KEY_TYPE: case CKA_SUBJECT: case CKA_ID: case CKA_SENSITIVE: case CKA_ENCRYPT: case CKA_DECRYPT: case CKA_WRAP: case CKA_UNWRAP: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_DERIVE: case CKA_START_DATE: case CKA_END_DATE: case CKA_MODULUS: case CKA_MODULUS_BITS: case CKA_PUBLIC_EXPONENT: case CKA_PRIVATE_EXPONENT: case CKA_PRIME_1: case CKA_PRIME_2: case CKA_EXPONENT_1: case CKA_EXPONENT_2: case CKA_COEFFICIENT: case CKA_PRIME: case CKA_SUBPRIME: case CKA_BASE: case CKA_VALUE_BITS: case CKA_VALUE_LEN: case CKA_EXTRACTABLE: case CKA_LOCAL: case CKA_NEVER_EXTRACTABLE: case CKA_ALWAYS_SENSITIVE: case CKA_MODIFIABLE: case CKA_ECDSA_PARAMS: case CKA_EC_POINT: case CKA_HW_FEATURE_TYPE: case CKA_HAS_RESET: case CKA_RESET_ON_INIT: case CKA_KEY_GEN_MECHANISM: case CKA_PRIME_BITS: case CKA_SUBPRIME_BITS: case CKA_OBJECT_ID: case CKA_AC_ISSUER: case CKA_OWNER: case CKA_ATTR_TYPES: case CKA_TRUSTED: return TRUE; } return FALSE; } char * p11_get_ckm(CK_ULONG mechanism) { switch (mechanism) { _sym2str(CKM_RSA_PKCS_KEY_PAIR_GEN); _sym2str(CKM_RSA_PKCS); _sym2str(CKM_RSA_9796); _sym2str(CKM_RSA_X_509); _sym2str(CKM_MD2_RSA_PKCS); _sym2str(CKM_MD5_RSA_PKCS); _sym2str(CKM_SHA1_RSA_PKCS); _sym2str(CKM_RIPEMD128_RSA_PKCS); _sym2str(CKM_RIPEMD160_RSA_PKCS); _sym2str(CKM_RSA_PKCS_OAEP); _sym2str(CKM_RSA_X9_31_KEY_PAIR_GEN); _sym2str(CKM_RSA_X9_31); _sym2str(CKM_SHA1_RSA_X9_31); _sym2str(CKM_RSA_PKCS_PSS); _sym2str(CKM_SHA1_RSA_PKCS_PSS); _sym2str(CKM_DSA_KEY_PAIR_GEN); _sym2str(CKM_DSA); _sym2str(CKM_DSA_SHA1); _sym2str(CKM_DH_PKCS_KEY_PAIR_GEN); _sym2str(CKM_DH_PKCS_DERIVE); _sym2str(CKM_X9_42_DH_KEY_PAIR_GEN); _sym2str(CKM_X9_42_DH_DERIVE); _sym2str(CKM_X9_42_DH_HYBRID_DERIVE); _sym2str(CKM_X9_42_MQV_DERIVE); _sym2str(CKM_SHA256_RSA_PKCS); _sym2str(CKM_SHA384_RSA_PKCS); _sym2str(CKM_SHA512_RSA_PKCS); _sym2str(CKM_RC2_KEY_GEN); _sym2str(CKM_RC2_ECB); _sym2str(CKM_RC2_CBC); _sym2str(CKM_RC2_MAC); _sym2str(CKM_RC2_MAC_GENERAL); _sym2str(CKM_RC2_CBC_PAD); _sym2str(CKM_RC4_KEY_GEN); _sym2str(CKM_RC4); _sym2str(CKM_DES_KEY_GEN); _sym2str(CKM_DES_ECB); _sym2str(CKM_DES_CBC); _sym2str(CKM_DES_MAC); _sym2str(CKM_DES_MAC_GENERAL); _sym2str(CKM_DES_CBC_PAD); _sym2str(CKM_DES2_KEY_GEN); _sym2str(CKM_DES3_KEY_GEN); _sym2str(CKM_DES3_ECB); _sym2str(CKM_DES3_CBC); _sym2str(CKM_DES3_MAC); _sym2str(CKM_DES3_MAC_GENERAL); _sym2str(CKM_DES3_CBC_PAD); _sym2str(CKM_CDMF_KEY_GEN); _sym2str(CKM_CDMF_ECB); _sym2str(CKM_CDMF_CBC); _sym2str(CKM_CDMF_MAC); _sym2str(CKM_CDMF_MAC_GENERAL); _sym2str(CKM_CDMF_CBC_PAD); _sym2str(CKM_MD2); _sym2str(CKM_MD2_HMAC); _sym2str(CKM_MD2_HMAC_GENERAL); _sym2str(CKM_MD5); _sym2str(CKM_MD5_HMAC); _sym2str(CKM_MD5_HMAC_GENERAL); _sym2str(CKM_SHA_1); _sym2str(CKM_SHA_1_HMAC); _sym2str(CKM_SHA_1_HMAC_GENERAL); _sym2str(CKM_RIPEMD128); _sym2str(CKM_RIPEMD128_HMAC); _sym2str(CKM_RIPEMD128_HMAC_GENERAL); _sym2str(CKM_RIPEMD160); _sym2str(CKM_RIPEMD160_HMAC); _sym2str(CKM_RIPEMD160_HMAC_GENERAL); _sym2str(CKM_SHA256); _sym2str(CKM_SHA256_HMAC); _sym2str(CKM_SHA256_HMAC_GENERAL); _sym2str(CKM_SHA384); _sym2str(CKM_SHA384_HMAC); _sym2str(CKM_SHA384_HMAC_GENERAL); _sym2str(CKM_SHA512); _sym2str(CKM_SHA512_HMAC); _sym2str(CKM_SHA512_HMAC_GENERAL); _sym2str(CKM_CAST_KEY_GEN); _sym2str(CKM_CAST_ECB); _sym2str(CKM_CAST_CBC); _sym2str(CKM_CAST_MAC); _sym2str(CKM_CAST_MAC_GENERAL); _sym2str(CKM_CAST_CBC_PAD); _sym2str(CKM_CAST3_KEY_GEN); _sym2str(CKM_CAST3_ECB); _sym2str(CKM_CAST3_CBC); _sym2str(CKM_CAST3_MAC); _sym2str(CKM_CAST3_MAC_GENERAL); _sym2str(CKM_CAST3_CBC_PAD); _sym2str(CKM_CAST5_KEY_GEN); _sym2str(CKM_CAST5_ECB); _sym2str(CKM_CAST5_CBC); _sym2str(CKM_CAST5_MAC); _sym2str(CKM_CAST5_MAC_GENERAL); _sym2str(CKM_CAST5_CBC_PAD); _sym2str(CKM_RC5_KEY_GEN); _sym2str(CKM_RC5_ECB); _sym2str(CKM_RC5_CBC); _sym2str(CKM_RC5_MAC); _sym2str(CKM_RC5_MAC_GENERAL); _sym2str(CKM_RC5_CBC_PAD); _sym2str(CKM_IDEA_KEY_GEN); _sym2str(CKM_IDEA_ECB); _sym2str(CKM_IDEA_CBC); _sym2str(CKM_IDEA_MAC); _sym2str(CKM_IDEA_MAC_GENERAL); _sym2str(CKM_IDEA_CBC_PAD); _sym2str(CKM_GENERIC_SECRET_KEY_GEN); _sym2str(CKM_CONCATENATE_BASE_AND_KEY); _sym2str(CKM_CONCATENATE_BASE_AND_DATA); _sym2str(CKM_CONCATENATE_DATA_AND_BASE); _sym2str(CKM_XOR_BASE_AND_DATA); _sym2str(CKM_EXTRACT_KEY_FROM_KEY); _sym2str(CKM_SSL3_PRE_MASTER_KEY_GEN); _sym2str(CKM_SSL3_MASTER_KEY_DERIVE); _sym2str(CKM_SSL3_KEY_AND_MAC_DERIVE); _sym2str(CKM_SSL3_MASTER_KEY_DERIVE_DH); _sym2str(CKM_TLS_PRE_MASTER_KEY_GEN); _sym2str(CKM_TLS_MASTER_KEY_DERIVE); _sym2str(CKM_TLS_KEY_AND_MAC_DERIVE); _sym2str(CKM_TLS_MASTER_KEY_DERIVE_DH); _sym2str(CKM_SSL3_MD5_MAC); _sym2str(CKM_SSL3_SHA1_MAC); _sym2str(CKM_MD5_KEY_DERIVATION); _sym2str(CKM_MD2_KEY_DERIVATION); _sym2str(CKM_SHA1_KEY_DERIVATION); _sym2str(CKM_SHA256_KEY_DERIVATION); _sym2str(CKM_PBE_MD2_DES_CBC); _sym2str(CKM_PBE_MD5_DES_CBC); _sym2str(CKM_PBE_MD5_CAST_CBC); _sym2str(CKM_PBE_MD5_CAST3_CBC); _sym2str(CKM_PBE_MD5_CAST5_CBC); _sym2str(CKM_PBE_SHA1_CAST5_CBC); _sym2str(CKM_PBE_SHA1_RC4_128); _sym2str(CKM_PBE_SHA1_RC4_40); _sym2str(CKM_PBE_SHA1_DES3_EDE_CBC); _sym2str(CKM_PBE_SHA1_DES2_EDE_CBC); _sym2str(CKM_PBE_SHA1_RC2_128_CBC); _sym2str(CKM_PBE_SHA1_RC2_40_CBC); _sym2str(CKM_PKCS5_PBKD2); _sym2str(CKM_PBA_SHA1_WITH_SHA1_HMAC); _sym2str(CKM_KEY_WRAP_LYNKS); _sym2str(CKM_KEY_WRAP_SET_OAEP); _sym2str(CKM_SKIPJACK_KEY_GEN); _sym2str(CKM_SKIPJACK_ECB64); _sym2str(CKM_SKIPJACK_CBC64); _sym2str(CKM_SKIPJACK_OFB64); _sym2str(CKM_SKIPJACK_CFB64); _sym2str(CKM_SKIPJACK_CFB32); _sym2str(CKM_SKIPJACK_CFB16); _sym2str(CKM_SKIPJACK_CFB8); _sym2str(CKM_SKIPJACK_WRAP); _sym2str(CKM_SKIPJACK_PRIVATE_WRAP); _sym2str(CKM_SKIPJACK_RELAYX); _sym2str(CKM_KEA_KEY_PAIR_GEN); _sym2str(CKM_KEA_KEY_DERIVE); _sym2str(CKM_FORTEZZA_TIMESTAMP); _sym2str(CKM_BATON_KEY_GEN); _sym2str(CKM_BATON_ECB128); _sym2str(CKM_BATON_ECB96); _sym2str(CKM_BATON_CBC128); _sym2str(CKM_BATON_COUNTER); _sym2str(CKM_BATON_SHUFFLE); _sym2str(CKM_BATON_WRAP); _sym2str(CKM_EC_KEY_PAIR_GEN); _sym2str(CKM_ECDSA); _sym2str(CKM_ECDSA_SHA1); _sym2str(CKM_ECDH1_DERIVE); _sym2str(CKM_ECDH1_COFACTOR_DERIVE); _sym2str(CKM_ECMQV_DERIVE); _sym2str(CKM_JUNIPER_KEY_GEN); _sym2str(CKM_JUNIPER_ECB128); _sym2str(CKM_JUNIPER_CBC128); _sym2str(CKM_JUNIPER_COUNTER); _sym2str(CKM_JUNIPER_SHUFFLE); _sym2str(CKM_JUNIPER_WRAP); _sym2str(CKM_FASTHASH); _sym2str(CKM_AES_KEY_GEN); _sym2str(CKM_AES_ECB); _sym2str(CKM_AES_CBC); _sym2str(CKM_AES_MAC); _sym2str(CKM_AES_MAC_GENERAL); _sym2str(CKM_AES_CBC_PAD); _sym2str(CKM_AES_CTR); _sym2str(CKM_DSA_PARAMETER_GEN); _sym2str(CKM_DH_PKCS_PARAMETER_GEN); _sym2str(CKM_X9_42_DH_PARAMETER_GEN); _sym2str(CKM_VENDOR_DEFINED); default: return "UNKNOWN"; } } // Allocates memory on *dst and puts hex dump from ptr // with len bytes. // *dst must be freed by the caller char * p11_ahex_dump(char **dst, CK_BYTE_PTR ptr, CK_ULONG len) { CK_ULONG i; if (dst == NULL) { return NULL; } *dst = (char *) calloc(2*len + 1 , sizeof(char)); if (*dst == NULL) { return NULL; } for (i = 0; i < len; i++) { sprintf(*dst + 2*i, "%02hhX", ptr[i]); } *(*dst + 2*len) = '\0'; // null-terminate return *dst; } /* p11_bigint_trim() - trim a big integer. Returns pointer that is * contained within 'in' + '*size' that represents * the same number, but without leading zeros. * @in points to a sequence of bytes forming a big integer, * unsigned, right-aligned and big-endian * @size points to the size of @in on input, and the minimum * size that can represent it on output */ CK_BYTE_PTR p11_bigint_trim(CK_BYTE_PTR in, CK_ULONG_PTR size) { CK_ULONG i; for (i = 0; (i < *size) && in[i] == 0x00; i++); *size -= i; return in + i; } /* p11_attribute_trim() - trim a PKCS#11 CK_ATTRIBUTE in place, * using memmove() to move the data and adjusting * ulValueLen. The resulting "pValue" pointer stays the * same so that the caller can free() it normally * @attr is the pointer to the CK_ATTRIBUTE to be trimmed */ void p11_attribute_trim(CK_ATTRIBUTE *attr) { CK_BYTE_PTR ptr; CK_ULONG size; if (attr != NULL) { size = attr->ulValueLen; ptr = p11_bigint_trim(attr->pValue, &size); if (ptr != attr->pValue) { attr->ulValueLen = size; memmove(attr->pValue, ptr, size); } } } opencryptoki+dfsg/usr/lib/pkcs11/common/shared_memory.h0000644000175000017500000000146412630407154022264 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token - Shared memory abstraction for OpenCryptoki * * (C) COPYRIGHT International Business Machines Corp. 2012 * * Author: Marcelo Cerri (mhcerri@br.ibm.com) * * Note: the functions in this files are implemented as an abstraction layer for * POSIX shared memory functions but they can be extended to support other * APIs of shared memory. */ #ifndef OCK_SHARED_MEMORY_H #define OCK_SHARED_MEMORY_H #include #define SM_NAME_LEN (NAME_MAX) int sm_open(const char *sm_name, int mode, void **p_addr, size_t len, int force); int sm_close(void *addr, int destroy); int sm_destroy(const char *name); int sm_sync(void *addr); int sm_copy_name(void *addr, char *buffer, size_t len); int sm_get_count(void *addr); #endif opencryptoki+dfsg/usr/lib/pkcs11/common/dig_mgr.c0000755000175000017500000006274712630407154021047 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: dig_mgr.c // // Digest manager routines // #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV digest_mgr_init( SESSION *sess, DIGEST_CONTEXT *ctx, CK_MECHANISM *mech ) { CK_RV rc = CKR_OK; CK_BYTE * ptr = NULL; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active != FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } // is the mechanism supported? is the parameter present if required? // switch (mech->mechanism) { case CKM_SHA_1: case CKM_SHA256: case CKM_SHA384: case CKM_SHA512: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } ctx->context = NULL; rc = sha_init(sess, ctx, mech); if (rc != CKR_OK) { digest_mgr_cleanup(ctx); // to de-initialize context above TRACE_ERROR("Failed to init sha context.\n"); return rc; } } break; case CKM_MD2: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } ctx->context_len = sizeof(MD2_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(MD2_CONTEXT)); if (!ctx->context){ digest_mgr_cleanup(ctx); // to de-initialize context above TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(MD2_CONTEXT) ); } break; case CKM_MD5: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } ctx->context_len = sizeof(MD5_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(MD5_CONTEXT)); if (!ctx->context){ digest_mgr_cleanup(ctx); // to de-initialize context above TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } ckm_md5_init( (MD5_CONTEXT *)ctx->context ); } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (mech->ulParameterLen > 0) { ptr = (CK_BYTE *)malloc(mech->ulParameterLen); if (!ptr){ digest_mgr_cleanup(ctx); // to de-initialize context above TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, mech->pParameter, mech->ulParameterLen ); } ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = ptr; ctx->multi = FALSE; ctx->active = TRUE; return CKR_OK; } // // CK_RV digest_mgr_cleanup( DIGEST_CONTEXT *ctx ) { if (!ctx){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->context_len = 0; if (ctx->mech.pParameter) { free( ctx->mech.pParameter ); ctx->mech.pParameter = NULL; } if (ctx->context != NULL) { free( ctx->context ); ctx->context = NULL; } return CKR_OK; } // // CK_RV digest_mgr_digest( SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } // if the caller just wants the encrypted length, there is no reason to // specify the input data. I just need the data length // if ((length_only == FALSE) && (!in_data || !out_data)){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto out; } if (ctx->multi == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto out; } switch (ctx->mech.mechanism) { case CKM_SHA_1: case CKM_SHA256: case CKM_SHA384: case CKM_SHA512: rc = sha_hash(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); break; #if !(NOMD2 ) case CKM_MD2: rc = md2_hash( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); break; #endif case CKM_MD5: rc = md5_hash( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } out: if ( !((rc == CKR_BUFFER_TOO_SMALL) || (rc == CKR_OK && length_only == TRUE)) ) { // "A call to C_Digest always terminates the active digest operation unless it // returns CKR_BUFFER_TOO_SMALL or is a successful call (i.e., one which returns CKR_OK) // to determine the length of the buffer needed to hold the message digest." digest_mgr_cleanup(ctx); } return rc; } // // CK_RV digest_mgr_digest_update( SESSION *sess, DIGEST_CONTEXT *ctx, CK_BYTE *data, CK_ULONG data_len ) { CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } ctx->multi = TRUE; switch (ctx->mech.mechanism) { case CKM_SHA_1: case CKM_SHA256: case CKM_SHA384: case CKM_SHA512: rc = sha_hash_update(sess, ctx, data, data_len); break; #if !(NOMD2) case CKM_MD2: rc = md2_hash_update( sess, ctx, data, data_len ); break; #endif case CKM_MD5: rc = md5_hash_update( sess, ctx, data, data_len ); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } if (rc != CKR_OK) { digest_mgr_cleanup(ctx); // "A call to C_DigestUpdate which results in an error // terminates the current digest operation." } return rc; } // // CK_RV digest_mgr_digest_key( SESSION * sess, DIGEST_CONTEXT * ctx, CK_OBJECT_HANDLE key_handle ) { CK_ATTRIBUTE * attr = NULL; OBJECT * key_obj = NULL; CK_OBJECT_CLASS class; CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( key_handle, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_HANDLE_INVALID)); rc = CKR_KEY_HANDLE_INVALID; goto out; } // only allow digesting of CKO_SECRET keys // rc = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (rc == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_INDIGESTIBLE)); rc = CKR_KEY_INDIGESTIBLE; goto out; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_SECRET_KEY){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_INDIGESTIBLE)); rc = CKR_KEY_INDIGESTIBLE; goto out; } // every secret key has a CKA_VALUE attribute // rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr ); if (!rc){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_INDIGESTIBLE)); rc = CKR_KEY_INDIGESTIBLE; goto out; } rc = digest_mgr_digest_update( sess, ctx, attr->pValue, attr->ulValueLen ); if (rc != CKR_OK){ TRACE_DEVEL("digest_mgr_digest_update failed\n"); } out: if (rc != CKR_OK) { digest_mgr_cleanup(ctx); } return rc; } // // CK_RV digest_mgr_digest_final( SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *hash, CK_ULONG *hash_len ) { CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } switch (ctx->mech.mechanism) { case CKM_SHA_1: case CKM_SHA256: case CKM_SHA384: case CKM_SHA512: rc = sha_hash_final(sess, length_only, ctx, hash, hash_len); break; #if !(NOMD2) case CKM_MD2: rc = md2_hash_final( sess, length_only, ctx, hash, hash_len ); break; #endif case CKM_MD5: rc = md5_hash_final( sess, length_only, ctx, hash, hash_len ); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; // shouldn't happen } if ( !((rc == CKR_BUFFER_TOO_SMALL) || (rc == CKR_OK && length_only == TRUE)) ) { // "A call to C_DigestFinal always terminates the active digest operation unless it // returns CKR_BUFFER_TOO_SMALL or is a successful call (i.e., one which returns CKR_OK) // to determine the length of the buffer needed to hold the message digest." digest_mgr_cleanup(ctx); } return rc; } opencryptoki+dfsg/usr/lib/pkcs11/common/utility.c0000755000175000017500000010503012630407154021121 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "pkcs32.h" #include "shared_memory.h" #include "trace.h" #include #include // Function: dlist_add_as_first() // // Adds the specified node to the start of the list // // Returns: pointer to the start of the list // DL_NODE *dlist_add_as_first(DL_NODE * list, void *data) { DL_NODE *node = NULL; if (!data) return list; node = (DL_NODE *) malloc(sizeof(DL_NODE)); if (!node) return NULL; node->data = data; node->prev = NULL; node->next = list; if (list) list->prev = node; return node; } // Function: dlist_add_as_last() // // Adds the specified node to the end of the list // // Returns: pointer to the start of the list // DL_NODE *dlist_add_as_last(DL_NODE * list, void *data) { DL_NODE *node = NULL; if (!data) return list; node = (DL_NODE *) malloc(sizeof(DL_NODE)); if (!node) return NULL; node->data = data; node->next = NULL; if (!list) { node->prev = NULL; return node; } else { DL_NODE *temp = dlist_get_last(list); temp->next = node; node->prev = temp; return list; } } // Function: dlist_find() // DL_NODE *dlist_find(DL_NODE * list, void *data) { DL_NODE *node = list; while (node && node->data != data) node = node->next; return node; } // Function: dlist_get_first() // // Returns the last node in the list or NULL if list is empty // DL_NODE *dlist_get_first(DL_NODE * list) { DL_NODE *temp = list; if (!list) return NULL; while (temp->prev != NULL) temp = temp->prev; return temp; } // Function: dlist_get_last() // // Returns the last node in the list or NULL if list is empty // DL_NODE *dlist_get_last(DL_NODE * list) { DL_NODE *temp = list; if (!list) return NULL; while (temp->next != NULL) temp = temp->next; return temp; } // // CK_ULONG dlist_length(DL_NODE * list) { DL_NODE *temp = list; CK_ULONG len = 0; while (temp) { len++; temp = temp->next; } return len; } // // DL_NODE *dlist_next(DL_NODE * node) { if (!node) return NULL; return node->next; } // // DL_NODE *dlist_prev(DL_NODE * node) { if (!node) return NULL; return node->prev; } // // void dlist_purge(DL_NODE * list) { DL_NODE *node; if (!list) return; do { node = list->next; free(list); list = node; } while (list); } // Function: dlist_remove_node() // // Attempts to remove the specified node from the list. The caller is // responsible for freeing the data associated with the node prior to // calling this routine // DL_NODE *dlist_remove_node(DL_NODE * list, DL_NODE * node) { DL_NODE *temp = list; if (!list || !node) return NULL; // special case: removing head of the list // if (list == node) { temp = list->next; if (temp) temp->prev = NULL; free(list); return temp; } // we have no guarantee that the node is in the list // so search through the list to find it // while ((temp != NULL) && (temp->next != node)) temp = temp->next; if (temp != NULL) { DL_NODE *next = node->next; temp->next = next; if (next) next->prev = temp; free(node); } return list; } // NOTE about Mutexes and cross process locking.... // // The code uses 2 types of locks... internal locks to prevent threads within the same // process space from stomping on each other (pthread_mutex's suffice for // this).... and Cross Process Locks.... // On AIX we use it's variation of Posix semaphores for this.... Idealy on other // platforms either POSIXSEMaphores or PTHREADXPL (pthreads xprocess lock) would // be used. On Linux unfortunatly neither of these are available so we need to // use the old standby of SYSV semaphores (YECH.... GAG....).... The only // pieces which have been tested are the AIX and SYSV portions although // we expect that the others work correctly. // // we use alot more mutexes in the redesign than we did in the original // design. so instead of just the single global "pkcs_mutex" we have to // deal with a number of mutexes. so we'll make the mutex routines a // bit more generic. // CK_RV _CreateMutex(MUTEX * mutex) { // on AIX we make this a no-op since we assume that // the mutex was created in the initialization pthread_mutex_init(mutex, NULL); return CKR_OK; } CK_RV _DestroyMutex(MUTEX * mutex) { // no-op in AIX pthread_mutex_destroy((pthread_mutex_t *) mutex); return CKR_OK; } CK_RV _LockMutex(MUTEX * mutex) { pthread_mutex_lock(mutex); return CKR_OK; } CK_RV _UnlockMutex(MUTEX * mutex) { pthread_mutex_unlock(mutex); return CKR_OK; } static int spinxplfd = -1; CK_RV CreateXProcLock(void) { CK_BYTE lockfile[PATH_MAX]; struct group *grp; struct stat statbuf; mode_t mode = (S_IRUSR | S_IRGRP); if (spinxplfd == -1) { if (token_specific.t_creatlock != NULL) { spinxplfd = token_specific.t_creatlock(); if (spinxplfd != -1) return CKR_OK; else return CKR_FUNCTION_FAILED; } /* create user lock file */ sprintf(lockfile, "%s/%s/LCK..%s", LOCKDIR_PATH, SUB_DIR, SUB_DIR); if (stat(lockfile, &statbuf) == 0) spinxplfd = open(lockfile, O_RDONLY, mode); else { spinxplfd = open(lockfile, O_CREAT | O_RDONLY, mode); if (spinxplfd != -1) { /* umask may prevent correct mode,so set it. */ if (fchmod(spinxplfd, mode) == -1) { OCK_SYSLOG(LOG_ERR, "fchmod(%s): %s\n", lockfile, strerror(errno)); goto err; } grp = getgrnam("pkcs11"); if (grp != NULL) { if (fchown(spinxplfd, -1, grp->gr_gid) == -1) { OCK_SYSLOG(LOG_ERR, "fchown(%s): %s\n", lockfile, strerror(errno)); goto err; } } else { OCK_SYSLOG(LOG_ERR, "getgrnam(): %s\n", strerror(errno)); goto err; } } } if (spinxplfd == -1) { OCK_SYSLOG(LOG_ERR, "open(%s): %s\n", lockfile, strerror(errno)); return CKR_FUNCTION_FAILED; } } return CKR_OK; err: if (spinxplfd != -1) close(spinxplfd); return CKR_FUNCTION_FAILED; } void CloseXProcLock(void) { if (spinxplfd != -1) close(spinxplfd); } CK_RV XProcLock(void) { if (spinxplfd != -1) flock(spinxplfd, LOCK_EX); else TRACE_DEVEL("No file descriptor to lock with.\n"); return CKR_OK; } CK_RV XProcUnLock(void) { if (spinxplfd != -1) flock(spinxplfd, LOCK_UN); else TRACE_DEVEL("No file descriptor to unlock with.\n"); return CKR_OK; } void XProcLock_Init(void) { spinxplfd = -1; } // // extern CK_CHAR manuf[]; extern CK_CHAR model[]; extern CK_CHAR descr[]; extern CK_CHAR label[]; // // void init_slotInfo(void) { memset(&slot_info.slotDescription, ' ', sizeof(slot_info.slotDescription)); memset(&slot_info.manufacturerID, ' ', sizeof(slot_info.manufacturerID)); memcpy(&slot_info.slotDescription, descr, strlen((char *)descr)); memcpy(&slot_info.manufacturerID, manuf, strlen((char *)manuf)); slot_info.hardwareVersion.major = 1; slot_info.hardwareVersion.minor = 0; slot_info.firmwareVersion.major = 1; slot_info.firmwareVersion.minor = 0; slot_info.flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT; } // // void init_tokenInfo(void) { CK_TOKEN_INFO_32 *token_info = NULL; token_info = &nv_token_data->token_info; memset(token_info->manufacturerID, ' ', sizeof(token_info->manufacturerID)); memset(token_info->model, ' ', sizeof(token_info->model)); memset(token_info->serialNumber, ' ', sizeof(token_info->serialNumber)); memcpy(token_info->label, nv_token_data->token_info.label, 32); memcpy(token_info->manufacturerID, manuf, strlen((char *)manuf)); memcpy(token_info->model, model, strlen((char *)model)); // use the 41-xxxxx serial number from the coprocessor // memcpy(token_info->serialNumber, "123", 3); // I don't see any API support for changing the clock so // we will use the system clock for the token's clock. // token_info->flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_CLOCK_ON_TOKEN | CKF_SO_PIN_TO_BE_CHANGED; // XXX New in v2.11 - KEY if (memcmp (nv_token_data->user_pin_sha, "00000000000000000000", SHA1_HASH_SIZE) != 0) token_info->flags |= CKF_USER_PIN_INITIALIZED; else token_info->flags |= CKF_USER_PIN_TO_BE_CHANGED; // XXX New in v2.11 - KEY // For the release, we made these // values as CK_UNAVAILABLE_INFORMATION // token_info->ulMaxSessionCount = (CK_ULONG_32) CK_UNAVAILABLE_INFORMATION; token_info->ulSessionCount = (CK_ULONG_32) CK_UNAVAILABLE_INFORMATION; token_info->ulMaxRwSessionCount = (CK_ULONG_32) CK_UNAVAILABLE_INFORMATION; token_info->ulRwSessionCount = (CK_ULONG_32) CK_UNAVAILABLE_INFORMATION; token_info->ulMaxPinLen = MAX_PIN_LEN; token_info->ulMinPinLen = MIN_PIN_LEN; token_info->ulTotalPublicMemory = (CK_ULONG_32) CK_UNAVAILABLE_INFORMATION; token_info->ulFreePublicMemory = (CK_ULONG_32) CK_UNAVAILABLE_INFORMATION; token_info->ulTotalPrivateMemory = (CK_ULONG_32) CK_UNAVAILABLE_INFORMATION; token_info->ulFreePrivateMemory = (CK_ULONG_32) CK_UNAVAILABLE_INFORMATION; token_info->hardwareVersion.major = 1; token_info->hardwareVersion.minor = 0; token_info->firmwareVersion.major = 1; token_info->firmwareVersion.minor = 0; memset(token_info->utcTime, ' ', sizeof(token_info->utcTime)); } // // CK_RV init_token_data(CK_SLOT_ID slot_id) { CK_RV rc; memset((char *)nv_token_data, 0, sizeof(nv_token_data)); // the normal USER pin is not set when the token is initialized // memcpy(nv_token_data->user_pin_sha, "00000000000000000000", SHA1_HASH_SIZE); memcpy(nv_token_data->so_pin_sha, default_so_pin_sha, SHA1_HASH_SIZE); memset(user_pin_md5, 0x0, MD5_HASH_SIZE); memcpy(so_pin_md5, default_so_pin_md5, MD5_HASH_SIZE); memcpy(nv_token_data->next_token_object_name, "00000000", 8); // generate the master key used for signing the Operation State information // ` memset(nv_token_data->token_info.label, ' ', sizeof(nv_token_data->token_info.label)); memcpy(nv_token_data->token_info.label, label, strlen((char *)label)); nv_token_data->tweak_vector.allow_weak_des = TRUE; nv_token_data->tweak_vector.check_des_parity = FALSE; nv_token_data->tweak_vector.allow_key_mods = TRUE; nv_token_data->tweak_vector.netscape_mods = TRUE; init_tokenInfo(); if (token_specific.t_init_token_data) { rc = token_specific.t_init_token_data(slot_id); if (rc != CKR_OK) return rc; } else { // // FIXME: erase the token object index file (and all token objects) // rc = generate_master_key(master_key); if (rc != CKR_OK) { TRACE_DEVEL("generate_master_key failed.\n"); return CKR_FUNCTION_FAILED; } rc = save_masterkey_so(); if (rc != CKR_OK) { TRACE_DEVEL("save_masterkey_so failed.\n"); return rc; } } rc = save_token_data(slot_id); return rc; } // Function: compute_next_token_obj_name() // // Given a token object name (8 bytes in the range [0-9A-Z]) increment by one // adjusting as necessary // // This gives us a namespace of 36^8 = 2,821,109,907,456 objects before wrapping around // CK_RV compute_next_token_obj_name(CK_BYTE * current, CK_BYTE * next) { int val[8]; int i; if (!current || !next) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } // Convert to integral base 36 // for (i = 0; i < 8; i++) { if (current[i] >= '0' && current[i] <= '9') val[i] = current[i] - '0'; if (current[i] >= 'A' && current[i] <= 'Z') val[i] = current[i] - 'A' + 10; } val[0]++; i = 0; while (val[i] > 35) { val[i] = 0; if (i + 1 < 8) { val[i + 1]++; i++; } else { val[0]++; i = 0; // start pass 2 } } // now, convert back to [0-9A-Z] // for (i = 0; i < 8; i++) { if (val[i] < 10) next[i] = '0' + val[i]; else next[i] = 'A' + val[i] - 10; } return CKR_OK; } // // CK_RV build_attribute(CK_ATTRIBUTE_TYPE type, CK_BYTE * data, CK_ULONG data_len, CK_ATTRIBUTE ** attrib) { CK_ATTRIBUTE *attr = NULL; attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + data_len); if (!attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } attr->type = type; attr->ulValueLen = data_len; if (data_len > 0) { attr->pValue = (CK_BYTE *) attr + sizeof(CK_ATTRIBUTE); memcpy(attr->pValue, data, data_len); } else attr->pValue = NULL; *attrib = attr; return CKR_OK; } /* * Find an attribute in an attribute array. * * Returns CKR_FUNCTION_FAILED when attribute is not found, * CKR_ATTRIBUTE_TYPE_INVALID when length doesn't match the expected and * CKR_OK when values is returned in the `value` argument. */ CK_RV find_bbool_attribute(CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, CK_ATTRIBUTE_TYPE type, CK_BBOOL *value) { CK_ULONG i; for (i = 0; i < attrs_len; i++) { if (attrs[i].type == type) { /* Check size */ if (attrs[i].ulValueLen != sizeof(*value)) return CKR_ATTRIBUTE_TYPE_INVALID; /* Get value */ *value = *((CK_BBOOL *) attrs[i].pValue); } } return CKR_FUNCTION_FAILED; } // // CK_RV add_pkcs_padding(CK_BYTE * ptr, CK_ULONG block_size, CK_ULONG data_len, CK_ULONG total_len) { CK_ULONG i, pad_len; CK_BYTE pad_value; pad_len = block_size - (data_len % block_size); pad_value = (CK_BYTE) pad_len; if (data_len + pad_len > total_len) { TRACE_ERROR("The total length is too small to add padding.\n"); return CKR_FUNCTION_FAILED; } for (i = 0; i < pad_len; i++) ptr[i] = pad_value; return CKR_OK; } // // CK_RV strip_pkcs_padding(CK_BYTE * ptr, CK_ULONG total_len, CK_ULONG * data_len) { CK_BYTE pad_value; pad_value = ptr[total_len - 1]; if (pad_value > total_len) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_INVALID)); return CKR_ENCRYPTED_DATA_INVALID; } // thus, we have 'pad_value' bytes of 'pad_value' appended to the end // *data_len = total_len - pad_value; return CKR_OK; } // // CK_BYTE parity_adjust(CK_BYTE b) { if (parity_is_odd(b) == FALSE) b = (b & 0xFE) | ((~b) & 0x1); return b; } // // CK_RV parity_is_odd(CK_BYTE b) { b = ((b >> 4) ^ b) & 0x0f; b = ((b >> 2) ^ b) & 0x03; b = ((b >> 1) ^ b) & 0x01; if (b == 1) return TRUE; else return FALSE; } CK_RV attach_shm(CK_SLOT_ID slot_id, LW_SHM_TYPE **shm) { CK_RV rc = CKR_OK; int ret; char buf[PATH_MAX]; if (token_specific.t_attach_shm != NULL) return token_specific.t_attach_shm(slot_id, shm); XProcLock(); /* * Attach to an existing shared memory region or create it if it doesn't * exists. When it's created (ret=0) the region is initialized with * zeros. */ ret = sm_open(get_pk_dir(buf), 0666, (void**) shm, sizeof(**shm), 0); if (ret < 0) { TRACE_DEVEL("sm_open failed.\n"); rc = CKR_FUNCTION_FAILED; goto done; } done: XProcUnLock(); return rc; } CK_RV detach_shm() { CK_RV rc = CKR_OK; XProcLock(); if (sm_close((void *)global_shm, 0)) { TRACE_DEVEL("sm_close failed.\n"); rc = CKR_FUNCTION_FAILED; } XProcUnLock(); return rc; } CK_RV get_sha_size(CK_ULONG mech, CK_ULONG *hsize) { switch(mech) { case CKM_SHA_1: *hsize = SHA1_HASH_SIZE; break; case CKM_SHA256: *hsize = SHA2_HASH_SIZE; break; case CKM_SHA384: *hsize = SHA3_HASH_SIZE; break; case CKM_SHA512: *hsize = SHA5_HASH_SIZE; break; default: return CKR_MECHANISM_INVALID; } return CKR_OK; } /* Compute specified SHA using either software or token implementation */ CK_RV compute_sha(CK_BYTE * data, CK_ULONG len, CK_BYTE *hash, CK_ULONG mech) { DIGEST_CONTEXT ctx; CK_ULONG hash_len; CK_RV rv; memset(&ctx, 0x0, sizeof(ctx)); ctx.mech.mechanism = mech; rv = get_sha_size(mech, &hash_len); if (rv != CKR_OK) return rv; rv = sha_init(NULL, &ctx, &ctx.mech); if (rv != CKR_OK) { TRACE_DEBUG("failed to create digest.\n"); return rv; } return sha_hash(NULL, FALSE, &ctx, data, len, hash, &hash_len); } /* Compute SHA1 using software implementation */ CK_RV compute_sha1(CK_BYTE * data, CK_ULONG len, CK_BYTE *hash) { // XXX KEY DIGEST_CONTEXT ctx; CK_ULONG hash_len = SHA1_HASH_SIZE; memset(&ctx, 0x0, sizeof(ctx)); sw_sha1_init(&ctx); if (ctx.context == NULL) return CKR_HOST_MEMORY; return sw_sha1_hash(&ctx, data, len, hash, &hash_len); } CK_RV compute_md5(CK_BYTE * data, CK_ULONG len, CK_BYTE * hash) { MD5_CONTEXT ctx; memset(&ctx, 0x0, sizeof(ctx)); ckm_md5_init(&ctx); ckm_md5_update(&ctx, data, len); ckm_md5_final(&ctx, hash, MD5_HASH_SIZE); return CKR_OK; } CK_RV get_keytype(CK_OBJECT_HANDLE hkey, CK_KEY_TYPE *keytype) { CK_RV rc; OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; rc = object_mgr_find_in_map1(hkey, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed.\n"); return rc; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } else { *keytype = *(CK_KEY_TYPE *)attr->pValue; return CKR_OK; } } CK_RV check_user_and_group() { int i; uid_t uid, euid; struct passwd *pw, *epw; struct group *grp; /* * Check for root user or Group PKCS#11 Membershp. * Only these are allowed. */ uid = getuid(); euid = geteuid(); /* Root or effective Root is ok */ if (uid == 0 && euid == 0) return CKR_OK; /* * Check for member of group. SAB get login seems to not work * with some instances of application invocations (particularly * when forked). So we need to get the group information. * Really need to take the uid and map it to a name. */ grp = getgrnam("pkcs11"); if (grp == NULL) { OCK_SYSLOG(LOG_ERR, "getgrnam() failed: %s\n", strerror(errno)); goto error; } if (getgid() == grp->gr_gid || getegid() == grp->gr_gid) return CKR_OK; /* Check if user or effective user is member of pkcs11 group */ pw = getpwuid(uid); epw = getpwuid(euid); for (i = 0; grp->gr_mem[i]; i++) { if ((pw && (strncmp(pw->pw_name, grp->gr_mem[i], strlen(pw->pw_name)) == 0)) || (epw && (strncmp(epw->pw_name, grp->gr_mem[i], strlen(epw->pw_name)) == 0))) return CKR_OK; } error: TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } void copy_token_contents_sensibly(CK_TOKEN_INFO_PTR pInfo, TOKEN_DATA *nv_token_data) { memcpy(pInfo, &nv_token_data->token_info, sizeof(CK_TOKEN_INFO_32)); pInfo->flags = nv_token_data->token_info.flags; pInfo->ulMaxPinLen = nv_token_data->token_info.ulMaxPinLen; pInfo->ulMinPinLen = nv_token_data->token_info.ulMinPinLen; if (nv_token_data->token_info.ulTotalPublicMemory == (CK_ULONG_32)CK_UNAVAILABLE_INFORMATION) pInfo->ulTotalPublicMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; else pInfo->ulTotalPublicMemory = nv_token_data->token_info.ulTotalPublicMemory; if (nv_token_data->token_info.ulFreePublicMemory == (CK_ULONG_32)CK_UNAVAILABLE_INFORMATION) pInfo->ulFreePublicMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; else pInfo->ulFreePublicMemory = nv_token_data->token_info.ulFreePublicMemory; if (nv_token_data->token_info.ulTotalPrivateMemory == (CK_ULONG_32)CK_UNAVAILABLE_INFORMATION) pInfo->ulTotalPrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; else pInfo->ulTotalPrivateMemory = nv_token_data->token_info.ulTotalPrivateMemory; if (nv_token_data->token_info.ulFreePrivateMemory == (CK_ULONG_32)CK_UNAVAILABLE_INFORMATION) pInfo->ulFreePrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; else pInfo->ulFreePrivateMemory = nv_token_data->token_info.ulFreePrivateMemory; pInfo->hardwareVersion = nv_token_data->token_info.hardwareVersion; pInfo->firmwareVersion = nv_token_data->token_info.firmwareVersion; pInfo->ulMaxSessionCount = ULONG_MAX - 1; /* pInfo->ulSessionCount is set at the API level */ pInfo->ulMaxRwSessionCount = ULONG_MAX - 1; pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; } opencryptoki+dfsg/usr/lib/pkcs11/common/h_extern.h0000755000175000017500000037630712630407154021260 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/lib/pkcs11/common/h_extern.h,v 1.10 2007/12/05 22:52:01 mhalcrow Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ #ifndef _H_EXTERN_H #define _H_EXTERN_H #include extern char * pk_dir; // global variables // extern CK_BBOOL initialized; extern char *card_function_names[]; extern char *total_function_names[]; extern MECH_LIST_ELEMENT mech_list[]; extern CK_ULONG mech_list_len; extern pthread_mutex_t native_mutex; extern MUTEX pkcs_mutex, obj_list_mutex, sess_list_mutex, login_mutex; extern struct btree sess_btree; extern struct btree sess_obj_btree; extern struct btree priv_token_obj_btree; extern struct btree publ_token_obj_btree; extern struct btree object_map_btree; extern CK_BYTE master_key[MAX_KEY_SIZE]; extern CK_BYTE so_pin_md5[MD5_HASH_SIZE]; extern CK_BYTE user_pin_md5[MD5_HASH_SIZE]; extern CK_BYTE default_user_pin_sha[SHA1_HASH_SIZE]; extern CK_BYTE default_so_pin_sha[SHA1_HASH_SIZE]; extern CK_BYTE default_so_pin_md5[MD5_HASH_SIZE]; extern LW_SHM_TYPE *global_shm; extern TOKEN_DATA *nv_token_data; extern CK_SLOT_INFO slot_info; // extern CK_ULONG next_object_handle; // extern CK_ULONG next_session_handle; extern CK_ULONG ro_session_count; extern CK_STATE global_login_state; extern CK_BYTE ber_AlgIdRSAEncryption[]; extern CK_ULONG ber_AlgIdRSAEncryptionLen; extern CK_BYTE ber_rsaEncryption[]; extern CK_ULONG ber_rsaEncryptionLen; extern CK_BYTE ber_idDSA[]; extern CK_ULONG ber_idDSALen; extern CK_BYTE ber_md2WithRSAEncryption[]; extern CK_ULONG ber_md2WithRSAEncryptionLen; extern CK_BYTE ber_md4WithRSAEncryption[]; extern CK_ULONG ber_md4WithRSAEncryptionLen; extern CK_BYTE ber_md5WithRSAEncryption[]; extern CK_ULONG ber_md5WithRSAEncryptionLen; extern CK_BYTE ber_sha1WithRSAEncryption[]; extern CK_ULONG ber_sha1WithRSAEncryptionLen; extern CK_BYTE ber_AlgMd2[]; extern CK_ULONG ber_AlgMd2Len; extern CK_BYTE ber_AlgMd5[]; extern CK_ULONG ber_AlgMd5Len; extern CK_BYTE ber_AlgSha1[]; extern CK_ULONG ber_AlgSha1Len; extern CK_BYTE ber_AlgSha256[]; extern CK_ULONG ber_AlgSha256Len; extern CK_BYTE ber_AlgSha384[]; extern CK_ULONG ber_AlgSha384Len; extern CK_BYTE ber_AlgSha512[]; extern CK_ULONG ber_AlgSha512Len; extern CK_ULONG des_weak_count; extern CK_ULONG des_semi_weak_count; extern CK_ULONG des_possibly_weak_count; extern CK_BYTE des_weak_keys[4][8]; extern CK_BYTE des_semi_weak_keys[12][8]; extern CK_BYTE des_possibly_weak_keys[48][8]; extern struct ST_FCN_LIST function_list; extern CK_C_INITIALIZE_ARGS cinit_args; // VACPP C runtime initialization/cleanup entry points // int _CRT_init(void); int _CRT_term(void); CK_RV DummyFunction( CK_SLOT_ID slot_id, int arg ); // General-purpose functions // CK_RV C_Initialize ( CK_VOID_PTR pInitArgs ); CK_RV C_Finalize ( CK_VOID_PTR pReserved ); CK_RV C_GetInfo ( CK_INFO_PTR pInfo ); CK_RV C_GetFunctionList ( CK_FUNCTION_LIST_PTR_PTR ppFunctionList ); // Slot and token management functions // CK_RV C_GetSlotList ( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount ); CK_RV C_GetSlotInfo ( CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo ); CK_RV C_GetTokenInfo ( CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo ); CK_RV C_WaitForSlotEvent ( CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved ); CK_RV C_GetMechanismList ( CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount ); CK_RV C_GetMechanismInfo ( CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo ); CK_RV C_InitToken ( CK_SLOT_ID slotID, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel ); CK_RV C_InitPIN ( CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen ); CK_RV C_SetPIN ( CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen ); // Session management functions // CK_RV C_OpenSession ( CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession ); CK_RV C_CloseSession ( CK_SESSION_HANDLE hSession ); CK_RV C_CloseAllSessions ( CK_SLOT_ID slotID ); CK_RV C_GetSessionInfo ( CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo ); CK_RV C_GetOperationState ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen ); CK_RV C_SetOperationState ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey ); CK_RV C_Login ( CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG uPinLen ); CK_RV C_Logout ( CK_SESSION_HANDLE hSession ); // Object management functions // CK_RV C_CreateObject ( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject ); CK_RV C_CopyObject ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject ); CK_RV C_DestroyObject ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject ); CK_RV C_GetObjectSize ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize ); CK_RV C_GetAttributeValue ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount ); CK_RV C_SetAttributeValue ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount ); CK_RV C_FindObjectsInit ( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount ); CK_RV C_FindObjects ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount ); CK_RV C_FindObjectsFinal ( CK_SESSION_HANDLE hSession ); // Encryption functions // CK_RV C_EncryptInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey ); CK_RV C_Encrypt ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen ); CK_RV C_EncryptUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen ); CK_RV C_EncryptFinal ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen); // Decryption functions // CK_RV C_DecryptInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey ); CK_RV C_Decrypt ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen ); CK_RV C_DecryptUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen ); CK_RV C_DecryptFinal ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen ); // Message digesting functions // CK_RV C_DigestInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism ); CK_RV C_Digest ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen ); CK_RV C_DigestUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen ); CK_RV C_DigestKey ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey ); CK_RV C_DigestFinal ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen ); // Signing and MAC functions // CK_RV C_SignInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey ); CK_RV C_Sign ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen ); CK_RV C_SignUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen ); CK_RV C_SignFinal ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen ); CK_RV C_SignRecoverInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey ); CK_RV C_SignRecover ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen ); // Signature/MAC verification functions // CK_RV C_VerifyInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey ); CK_RV C_Verify ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen ); CK_RV C_VerifyUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen ); CK_RV C_VerifyFinal ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen ); CK_RV C_VerifyRecoverInit ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey ); CK_RV C_VerifyRecover ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen ); // Dual-function cryptographics functions // CK_RV C_DigestEncryptUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen ); CK_RV C_DecryptDigestUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen ); CK_RV C_SignEncryptUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen ); CK_RV C_DecryptVerifyUpdate ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen ); // Key management functions // CK_RV C_GenerateKey ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey ); 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 ); CK_RV C_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 ); CK_RV C_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 ); CK_RV C_DeriveKey ( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey ); // Random number generation functions // CK_RV C_SeedRandom ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen ); CK_RV C_GenerateRandom ( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen ); // Parallel function management functions // CK_RV C_GetFunctionStatus ( CK_SESSION_HANDLE hSession ); CK_RV C_CancelFunction ( CK_SESSION_HANDLE hSession ); // // internal routines are below this point // CK_RV clock_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV clock_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV clock_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV counter_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV counter_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV counter_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV dp_dsa_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode); CK_RV dp_dsa_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dp_dsa_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV dp_dh_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode); CK_RV dp_dh_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dp_dh_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV dp_x9dh_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode); CK_RV dp_x9dh_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dp_x9dh_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode); CK_RV communicate( CK_ULONG cmd_id, CK_VOID_PTR pReq, CK_ULONG req_len, CK_VOID_PTR pRep, CK_ULONG_PTR repl_len, CK_BYTE_PTR pOut, CK_ULONG out_len, CK_BYTE_PTR pIn, CK_ULONG in_len ); CK_RV compute_next_token_obj_name( CK_BYTE *current, CK_BYTE *next ); CK_RV save_token_object ( OBJECT *obj ); CK_RV save_public_token_object ( OBJECT *obj ); CK_RV save_private_token_object( OBJECT *obj ); CK_RV load_public_token_objects ( void ); CK_RV load_private_token_objects( void ); CK_RV reload_token_object( OBJECT *obj ); CK_RV restore_private_token_object( CK_BYTE * data, CK_ULONG len, OBJECT * pObj ); CK_RV delete_token_object( OBJECT *ptr ); CK_RV delete_token_data(); CK_BYTE *get_pk_dir(char *); CK_RV init_token_data(CK_SLOT_ID); CK_RV load_token_data(CK_SLOT_ID); CK_RV save_token_data(CK_SLOT_ID); CK_RV load_masterkey_so ( void ); CK_RV load_masterkey_user( void ); CK_RV save_masterkey_so ( void ); CK_RV save_masterkey_user( void ); CK_RV generate_master_key(CK_BYTE *key); void init_data_store(char *directory); void copy_token_contents_sensibly(CK_TOKEN_INFO_PTR pInfo, TOKEN_DATA *nv_token_data); CK_RV compute_md5( CK_BYTE *data, CK_ULONG len, CK_BYTE *hash ); CK_RV compute_sha1(CK_BYTE *data, CK_ULONG len, CK_BYTE *hash); CK_RV compute_sha(CK_BYTE *data, CK_ULONG len, CK_BYTE *hash, CK_ULONG mech); CK_RV get_sha_size(CK_ULONG mech, CK_ULONG *hsize); CK_RV mgf1(CK_BYTE *seed, CK_ULONG seedlen, CK_BYTE *mask, CK_ULONG maskLen, CK_RSA_PKCS_MGF_TYPE mgf); CK_RV get_ecsiglen(OBJECT *key_obj, CK_ULONG *size); //CK_RV load_FCV( void ); //CK_RV save_FCV( FUNCTION_CTRL_VEC_RECORD *new_FCV ); //CK_RV update_tweak_values( void *attributes, CK_ULONG count ); //CK_RV query_tweak_values( CK_ATTRIBUTE_TYPE * attributes, // CK_ULONG count, // CK_BYTE ** reply, // CK_ULONG * reply_len ); void init_slotInfo(void); void init_tokenInfo(void); CK_BYTE parity_adjust( CK_BYTE b ); CK_RV parity_is_odd( CK_BYTE b ); CK_RV build_attribute( CK_ATTRIBUTE_TYPE type, CK_BYTE *data, CK_ULONG data_len, CK_ATTRIBUTE **attr ); CK_RV find_bbool_attribute(CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, CK_ATTRIBUTE_TYPE type, CK_BBOOL *value); CK_RV add_pkcs_padding( CK_BYTE * ptr, // where to start appending CK_ULONG block_size, CK_ULONG data_len, CK_ULONG total_len ); CK_RV strip_pkcs_padding( CK_BYTE * ptr, CK_ULONG total_len, CK_ULONG * data_len ); // RNG routines // CK_RV rng_generate( CK_BYTE *output, CK_ULONG bytes ); // SSL3 routines // CK_RV ssl3_mac_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV ssl3_mac_sign_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV ssl3_mac_sign_final( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV ssl3_mac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV ssl3_mac_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV ssl3_mac_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV ssl3_master_key_derive( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE * attributes, CK_ULONG count, CK_OBJECT_HANDLE * handle ); CK_RV ssl3_key_and_mac_derive( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE * attributes, CK_ULONG count ); CK_RV ckm_ssl3_pre_master_key_gen( TEMPLATE *tmpl, CK_MECHANISM *mech ); // RSA routines // CK_RV rsa_pkcs_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV rsa_pkcs_decrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV rsa_pkcs_sign ( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len ); CK_RV rsa_pkcs_verify ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV rsa_pkcs_verify_recover ( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len, CK_BYTE * out_data, CK_ULONG * out_len ); CK_RV rsa_oaep_crypt(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BBOOL encrypt); CK_RV rsa_x509_encrypt ( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV rsa_x509_decrypt ( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV rsa_x509_sign ( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len ); CK_RV rsa_x509_verify ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV rsa_x509_verify_recover( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len, CK_BYTE * out_data, CK_ULONG * out_len ); CK_RV rsa_hash_pkcs_sign ( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len ); CK_RV rsa_hash_pkcs_verify ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV rsa_hash_pkcs_sign_update ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV rsa_hash_pkcs_verify_update ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV rsa_hash_pkcs_sign_final ( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG * sig_len ); CK_RV rsa_hash_pkcs_verify_final ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV rsa_pss_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len); CK_RV rsa_hash_pss_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *sig, CK_ULONG *sig_len); CK_RV rsa_hash_pss_update(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV rsa_hash_pss_sign_final(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG *sig_len); CK_RV rsa_pss_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len); CK_RV rsa_hash_pss_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len); CK_RV rsa_hash_pss_verify_final(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG sig_len); CK_RV rsa_format_block( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len, CK_ULONG type ); CK_RV rsa_parse_block( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG type ); // RSA mechanisms // CK_RV ckm_rsa_key_pair_gen( TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl ); CK_RV ckm_rsa_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj ); CK_RV ckm_rsa_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj ); CK_RV ckm_rsa_compute_priv_exp( TEMPLATE *tmpl ); CK_RV ckm_rsa_sign( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key_obj ); CK_RV ckm_rsa_verify( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len, OBJECT * key_obj ); // RSA mechanism - EME-OAEP encoding // CK_RV encode_eme_oaep(CK_BYTE *mData, CK_ULONG mLen, CK_BYTE *emData, CK_ULONG modLength, CK_RSA_PKCS_MGF_TYPE mgf, CK_BYTE *hash, CK_ULONG hlen); CK_RV decode_eme_oaep(CK_BYTE *emData, CK_ULONG emLen, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_RSA_PKCS_MGF_TYPE mgf, CK_BYTE *hash, CK_ULONG hlen); CK_RV emsa_pss_encode(CK_RSA_PKCS_PSS_PARAMS_PTR pssParms, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *emData, CK_ULONG *modbytes); CK_RV emsa_pss_verify(CK_RSA_PKCS_PSS_PARAMS_PTR pssParms, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *sig, CK_ULONG modbytes); CK_RV check_pss_params(CK_MECHANISM *mechanism, CK_ULONG); #ifndef NODSA // DSA routines // CK_RV dsa_sign ( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len ); CK_RV dsa_verify ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); // DSA mechanisms // CK_RV ckm_dsa_key_pair_gen( TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl ); CK_RV ckm_dsa_sign( CK_BYTE *in_data, // must be 20 bytes CK_BYTE *signature, // must be 40 bytes OBJECT *priv_key ); CK_RV ckm_dsa_verify( CK_BYTE *signature, // must be 40 bytes CK_BYTE *data, // must be 20 bytes OBJECT *publ_key ); #endif /* Begin code contributed by Corrent corp. */ // DH routines // #ifndef NODH CK_RV dh_pkcs_derive( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle ) ; // DH mechanisms // CK_RV ckm_dh_pkcs_derive( CK_VOID_PTR other_pubkey, CK_ULONG other_pubkey_len, CK_OBJECT_HANDLE base_key, CK_BYTE *secret, CK_ULONG *secret_len ) ; CK_RV ckm_dh_key_pair_gen( TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl ); CK_RV ckm_dh_pkcs_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ); #endif /* End code contributed by Corrent corp. */ // DES routines - I have to provide two different versions of these // because encryption routines are also used internally // so we can't assume that external-to-external buffering // will be possible and combining them into a single // function is messy. // CK_RV pk_des_ecb_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_ecb_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV pk_des_cbc_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_pad_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_pad_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_ecb_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_ecb_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_pad_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_pad_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_ecb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_ecb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_pad_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_cbc_pad_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des_ecb_wrap_key( SESSION *sess, CK_BBOOL length_only, CK_MECHANISM *mech, OBJECT *key, OBJECT *encr_key, CK_BYTE *data, CK_ULONG *data_len ); // DES mechanisms // CK_RV ckm_des_key_gen ( TEMPLATE *tmpl ); CK_RV ckm_cdmf_key_gen( TEMPLATE *tmpl ); CK_RV ckm_des_ecb_encrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key ); CK_RV ckm_des_ecb_decrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key ); CK_RV ckm_des_cbc_encrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *init_v, OBJECT *key ); CK_RV ckm_des_cbc_decrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *init_v, OBJECT *key ); CK_RV ckm_des_wrap_format( CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ); // DES3 routines // CK_RV des3_ecb_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_ecb_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_pad_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_pad_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_ecb_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_ecb_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_pad_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_pad_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_ecb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_ecb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_pad_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cbc_pad_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_mac_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV des3_mac_sign_update ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV des3_mac_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV des3_mac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len); CK_RV des3_mac_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len); CK_RV des3_mac_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG signature_len); // DES3 mechanisms // CK_RV ckm_des3_key_gen( TEMPLATE *tmpl ); CK_RV ckm_des3_ecb_encrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key ); CK_RV ckm_des3_ecb_decrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key ); CK_RV ckm_des3_cbc_encrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *init_v, OBJECT *key ); CK_RV ckm_des3_cbc_decrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *init_v, OBJECT *key ); CK_RV des3_ofb_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG *out_data_len); CK_RV des3_ofb_decrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV des3_ofb_encrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV des3_ofb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_ofb_decrypt_update (SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV des3_ofb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV des3_cfb_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len); CK_RV des3_cfb_decrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len); CK_RV des3_cfb_encrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len); CK_RV des3_cfb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG cfb_len); CK_RV des3_cfb_decrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len); CK_RV des3_cfb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG cfb_len); // AES routines // CK_RV aes_ecb_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ecb_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_pad_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_pad_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ctr_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len); CK_RV aes_ctr_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len); CK_RV aes_ecb_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ecb_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_pad_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_pad_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ctr_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data,CK_ULONG *out_data_len ); CK_RV aes_ctr_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data,CK_ULONG *out_data_len ); CK_RV aes_ecb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ecb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_pad_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cbc_pad_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ctr_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ctr_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *context, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_mac_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV aes_mac_sign_update ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV aes_mac_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV aes_mac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len); CK_RV aes_mac_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len); CK_RV aes_mac_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG signature_len); // AES mechanisms // CK_RV ckm_aes_key_gen( TEMPLATE *tmpl ); CK_RV ckm_aes_ecb_encrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key ); CK_RV ckm_aes_ecb_decrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key ); CK_RV ckm_aes_cbc_encrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *init_v, OBJECT *key ); CK_RV ckm_aes_cbc_decrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *init_v, OBJECT *key ); CK_RV ckm_aes_ctr_encrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *counterblock,CK_ULONG counter_width, OBJECT *key ); CK_RV ckm_aes_ctr_decrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *counterblock,CK_ULONG counter_width, OBJECT *key ); CK_RV ckm_aes_wrap_format( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len ); CK_RV aes_gcm_init(SESSION *, ENCR_DECR_CONTEXT *, CK_MECHANISM *, CK_OBJECT_HANDLE, CK_BYTE); CK_RV aes_gcm_encrypt(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV aes_gcm_encrypt_update(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV aes_gcm_encrypt_final(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG *); CK_RV aes_gcm_decrypt(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV aes_gcm_decrypt_update(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *); CK_RV aes_gcm_decrypt_final(SESSION *, CK_BBOOL, ENCR_DECR_CONTEXT *, CK_BYTE *, CK_ULONG *); CK_RV aes_ofb_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV aes_ofb_encrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV aes_ofb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ofb_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_ofb_decrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len); CK_RV aes_ofb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV aes_cfb_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len ); CK_RV aes_cfb_encrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len); CK_RV aes_cfb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG cfb_len); CK_RV aes_cfb_decrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG* out_data_len, CK_ULONG cfb_len ); CK_RV aes_cfb_decrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len); CK_RV aes_cfb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG cfb_len); // SHA mechanisms // void sw_sha1_init(DIGEST_CONTEXT *ctx); CK_RV sw_sha1_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len); CK_RV sha_init(SESSION *sess, DIGEST_CONTEXT *ctx, CK_MECHANISM *mech); CK_RV sha_hash(SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len); CK_RV sha_hash_update(SESSION *sess, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV sha_hash_final(SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len); CK_RV hmac_sign_init(SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE key); CK_RV hmac_sign_update(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV hmac_sign_final(SESSION *sess, CK_BYTE *in_data, CK_ULONG *in_data_len); CK_RV hmac_verify_update(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV hmac_verify_final(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV hmac_verify_init(SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE key); CK_RV sha1_hmac_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV sha1_hmac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV sha2_hmac_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV sha2_hmac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV sha3_hmac_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len); CK_RV sha3_hmac_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len); CK_RV sha5_hmac_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len); CK_RV sha5_hmac_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len); //adding the hmac secret key generation here CK_RV ckm_generic_secret_key_gen(TEMPLATE *tmpl); // MD2 mechanisms // CK_RV md2_hash( SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV md2_hash_update( SESSION *sess, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len ); CK_RV md2_hash_final( SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV md2_hmac_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV md2_hmac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV ckm_md2_update( MD2_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len ); CK_RV ckm_md2_final( MD2_CONTEXT *context, CK_BYTE *out_data, CK_ULONG out_data_len ); void ckm_md2_transform( CK_BYTE *state, CK_BYTE *checksum, CK_BYTE *block ); // MD5 mechanisms // CK_RV md5_hash( SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV md5_hash_update( SESSION *sess, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len ); CK_RV md5_hash_final( SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV md5_hmac_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV md5_hmac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); void ckm_md5_init( MD5_CONTEXT *context ); CK_RV ckm_md5_update( MD5_CONTEXT *context, CK_BYTE *in_data, CK_ULONG in_data_len ); CK_RV ckm_md5_final( MD5_CONTEXT *context, CK_BYTE *out_data, CK_ULONG out_data_len ); void ckm_md5_transform( CK_ULONG *buf, CK_ULONG *in ); //Elliptic curve (EC) mechanisms // CK_RV ckm_ec_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ); CK_RV ckm_ec_sign( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj ); CK_RV ec_sign( SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV ckm_ec_verify( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG out_data_len, OBJECT *key_obj ); CK_RV ec_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len ); CK_RV ec_hash_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG * sig_len ); CK_RV ec_hash_sign_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV ec_hash_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG * sig_len ); CK_RV ec_hash_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV ec_hash_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV ec_hash_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len ); // linked-list routines // DL_NODE * dlist_add_as_first( DL_NODE *list, void *data ); DL_NODE * dlist_add_as_last( DL_NODE *list, void *data ); DL_NODE * dlist_find( DL_NODE *list, void *data ); DL_NODE * dlist_get_first( DL_NODE *list ); DL_NODE * dlist_get_last( DL_NODE *list ); CK_ULONG dlist_length( DL_NODE *list ); DL_NODE * dlist_next( DL_NODE *list ); DL_NODE * dlist_prev( DL_NODE *list ); void dlist_purge( DL_NODE *list ); DL_NODE * dlist_remove_node( DL_NODE *list, DL_NODE *node ); CK_RV _CreateMutex( MUTEX *mutex ); CK_RV _DestroyMutex( MUTEX *mutex ); CK_RV _LockMutex( MUTEX *mutex ); CK_RV _UnlockMutex( MUTEX *mutex ); CK_RV attach_shm(CK_SLOT_ID slot_id, LW_SHM_TYPE **shmem); CK_RV detach_shm(void); //get keytype CK_RV get_keytype(CK_OBJECT_HANDLE hkey, CK_KEY_TYPE *keytype); CK_RV check_user_and_group(); //lock and unlock routines CK_RV XProcLock(void); CK_RV XProcUnLock(void); void XProcLock_Init(void); void CloseXProcLock(void); //list mechanisms // void mechanism_list_transformations(CK_MECHANISM_TYPE_PTR mech_arr_ptr, CK_ULONG_PTR count_ptr); // encryption manager routines // CK_RV encr_mgr_init( SESSION * sess, ENCR_DECR_CONTEXT * ctx, CK_ULONG operation, CK_MECHANISM * mech, CK_OBJECT_HANDLE key_handle ); CK_RV encr_mgr_cleanup( ENCR_DECR_CONTEXT *ctx ); CK_RV encr_mgr_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV encr_mgr_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV encr_mgr_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); // decryption manager routines // CK_RV decr_mgr_init( SESSION * sess, ENCR_DECR_CONTEXT * ctx, CK_ULONG operation, CK_MECHANISM * mech, CK_OBJECT_HANDLE key_handle ); CK_RV decr_mgr_cleanup( ENCR_DECR_CONTEXT * ctx ); CK_RV decr_mgr_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV decr_mgr_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV decr_mgr_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV decr_mgr_update_des_ecb( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV decr_mgr_update_des_cbc( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV decr_mgr_update_des3_ecb( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); CK_RV decr_mgr_update_des3_cbc( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ); // digest manager routines // CK_RV digest_mgr_cleanup( DIGEST_CONTEXT *ctx ); CK_RV digest_mgr_init( SESSION *sess, DIGEST_CONTEXT *ctx, CK_MECHANISM *mech ); CK_RV digest_mgr_digest( SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *data, CK_ULONG data_len, CK_BYTE *hash, CK_ULONG *hash_len ); CK_RV digest_mgr_digest_update( SESSION *sess, DIGEST_CONTEXT *ctx, CK_BYTE *data, CK_ULONG data_len ); CK_RV digest_mgr_digest_key( SESSION *sess, DIGEST_CONTEXT *ctx, CK_OBJECT_HANDLE key_handle ); CK_RV digest_mgr_digest_final( SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *hash, CK_ULONG *hash_len ); // key manager routines // CK_RV key_mgr_generate_key( SESSION *sess, CK_MECHANISM *mech, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE *key_handle ); CK_RV key_mgr_generate_key_pair( SESSION *sess, CK_MECHANISM *mech, CK_ATTRIBUTE *publ_tmpl, CK_ULONG publ_count, CK_ATTRIBUTE *priv_tmpl, CK_ULONG priv_count, CK_OBJECT_HANDLE *publ_key_handle, CK_OBJECT_HANDLE *priv_key_handle ); CK_RV key_mgr_get_private_key_type( CK_BYTE *keydata, CK_ULONG keylen, CK_KEY_TYPE *keytype ); CK_RV key_mgr_derive_key( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_OBJECT_HANDLE * derived_key, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ); CK_RV key_mgr_wrap_key( SESSION *sess, CK_BBOOL length_only, CK_MECHANISM *mech, CK_OBJECT_HANDLE h_wrapping_key, CK_OBJECT_HANDLE h_key, CK_BYTE *wrapped_key, CK_ULONG *wrapped_key_len ); CK_RV key_mgr_unwrap_key( SESSION *sess, CK_MECHANISM *mech, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount, CK_BYTE *wrapped_key, CK_ULONG wrapped_key_len, CK_OBJECT_HANDLE unwrapping_key, CK_OBJECT_HANDLE *unwrapped_key ); CK_RV key_mgr_derive_prolog( SESSION *sess, CK_ATTRIBUTE *attributes, CK_ULONG attrcount, CK_OBJECT_HANDLE base_key, OBJECT *base_key_obj, CK_BYTE *base_key_value, CK_KEY_TYPE base_key_type, ATTRIBUTE_PARSE_LIST *parselist, CK_ULONG plcount ); // signature manager routines // CK_RV sign_mgr_init( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key_handle ); CK_RV sign_mgr_cleanup( SIGN_VERIFY_CONTEXT *ctx ); CK_RV sign_mgr_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV sign_mgr_sign_recover( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV sign_mgr_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len ); CK_RV sign_mgr_sign_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); // signature verify manager routines // CK_RV verify_mgr_init( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_MECHANISM * mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key_handle ); CK_RV verify_mgr_cleanup( SIGN_VERIFY_CONTEXT *ctx ); CK_RV verify_mgr_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ); CK_RV verify_mgr_verify_recover( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len, CK_BYTE * out_data, CK_ULONG * out_len ); CK_RV verify_mgr_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ); CK_RV verify_mgr_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len ); // session manager routines // CK_RV session_mgr_close_all_sessions( void ); CK_RV session_mgr_close_session( CK_SESSION_HANDLE ); CK_RV session_mgr_new( CK_ULONG flags, CK_SLOT_ID slot_id, CK_SESSION_HANDLE_PTR phSession ); SESSION * session_mgr_find( CK_SESSION_HANDLE handle ); CK_RV session_mgr_login_all ( CK_USER_TYPE user_type ); CK_RV session_mgr_logout_all( void ); CK_BBOOL session_mgr_readonly_session_exists( void ); CK_BBOOL session_mgr_so_session_exists ( void ); CK_BBOOL session_mgr_user_session_exists ( void ); CK_BBOOL session_mgr_public_session_exists( void ); CK_RV session_mgr_get_op_state( SESSION *sess, CK_BBOOL length_only, CK_BYTE *data, CK_ULONG *data_len ); CK_RV session_mgr_set_op_state( SESSION *sess, CK_OBJECT_HANDLE encr_key, CK_OBJECT_HANDLE auth_key, CK_BYTE *data, CK_ULONG data_len ); CK_BBOOL pin_expired(CK_SESSION_INFO *, CK_FLAGS); CK_BBOOL pin_locked(CK_SESSION_INFO *, CK_FLAGS); void set_login_flags(CK_USER_TYPE, CK_FLAGS_32 *); // object manager routines // CK_RV object_mgr_add( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle ); CK_RV object_mgr_add_to_map( SESSION * sess, OBJECT * obj, unsigned long obj_handle, CK_OBJECT_HANDLE * handle ); void object_mgr_add_to_shm ( OBJECT *obj ); CK_RV object_mgr_del_from_shm( OBJECT *obj ); CK_RV object_mgr_check_shm ( OBJECT *obj ); CK_RV object_mgr_search_shm_for_obj( TOK_OBJ_ENTRY * list, CK_ULONG lo, CK_ULONG hi, OBJECT * obj, CK_ULONG * index ); CK_RV object_mgr_sort_priv_shm( void ); CK_RV object_mgr_sort_publ_shm( void ); CK_RV object_mgr_update_from_shm( void ); CK_RV object_mgr_update_publ_tok_obj_from_shm(); CK_RV object_mgr_update_priv_tok_obj_from_shm(); CK_RV object_mgr_copy( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE old_obj, CK_OBJECT_HANDLE * new_obj ); CK_RV object_mgr_create_final( SESSION *sess, OBJECT *obj, CK_OBJECT_HANDLE *handle ); CK_RV object_mgr_create_skel( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_ULONG mode, CK_ULONG class, CK_ULONG subclass, OBJECT ** obj ); CK_RV object_mgr_destroy_object( SESSION * sess, CK_OBJECT_HANDLE handle ); CK_RV object_mgr_destroy_token_objects( void ); CK_RV object_mgr_find_in_map_nocache( CK_OBJECT_HANDLE handle, OBJECT ** ptr ); CK_RV object_mgr_find_in_map1( CK_OBJECT_HANDLE handle, OBJECT ** ptr ); CK_RV object_mgr_find_in_map2( OBJECT * ptr, CK_OBJECT_HANDLE * handle ); CK_RV object_mgr_find_init( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ); CK_RV object_mgr_find_build_list( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, DL_NODE * obj_list, CK_BBOOL public_only ); CK_RV object_mgr_find_final( SESSION *sess ); CK_RV object_mgr_get_attribute_values( SESSION * sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ); CK_RV object_mgr_get_object_size( CK_OBJECT_HANDLE handle, CK_ULONG * size ); CK_BBOOL object_mgr_purge_session_objects( SESSION * sess, SESS_OBJ_TYPE type ); CK_BBOOL object_mgr_purge_token_objects( void ); CK_BBOOL object_mgr_purge_private_token_objects( void ); CK_RV object_mgr_restore_obj( CK_BYTE *data, OBJECT *oldObj ); CK_RV object_mgr_restore_obj_withSize( CK_BYTE *data, OBJECT *oldObj, int data_size ); CK_RV object_mgr_set_attribute_values( SESSION * sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ); // SAB FIXME FIXME CK_BBOOL object_mgr_purge_map( SESSION * sess, SESS_OBJ_TYPE type ); /* structures used to hold arguments to callback functions triggered by either bt_for_each_node * or bt_node_free */ struct find_args { int done; OBJECT *obj; CK_OBJECT_HANDLE map_handle; }; struct find_by_name_args { int done; char *name; }; struct find_build_list_args { CK_ATTRIBUTE *pTemplate; SESSION *sess; CK_ULONG ulCount; CK_BBOOL hw_feature; CK_BBOOL hidden_object; CK_BBOOL public_only; }; struct purge_args { SESSION *sess; SESS_OBJ_TYPE type; }; struct update_tok_obj_args { TOK_OBJ_ENTRY *entries; CK_ULONG_32 *num_entries; struct btree *t; }; // object routines // CK_RV object_create( CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, OBJECT ** obj ); CK_RV object_create_skel( CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_ULONG mode, CK_ULONG class, CK_ULONG subclass, OBJECT ** key ); CK_RV object_copy( CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, OBJECT * old_obj, OBJECT ** new_obj ); CK_RV object_flatten( OBJECT * obj, CK_BYTE ** data, CK_ULONG * len ); void object_free( OBJECT *obj ); CK_RV object_get_attribute_values( OBJECT * obj, CK_ATTRIBUTE * pTemplate, CK_ULONG count ); CK_ULONG object_get_size( OBJECT *obj ); CK_RV object_restore( CK_BYTE * data, OBJECT ** obj, CK_BBOOL replace ); CK_RV object_restore_withSize( CK_BYTE * data, OBJECT ** obj, CK_BBOOL replace, int data_size ); CK_RV object_set_attribute_values( OBJECT * obj, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ); CK_BBOOL object_is_modifiable ( OBJECT * obj ); CK_BBOOL object_is_private ( OBJECT * obj ); CK_BBOOL object_is_public ( OBJECT * obj ); CK_BBOOL object_is_token_object ( OBJECT * obj ); CK_BBOOL object_is_session_object( OBJECT * obj ); // object attribute template routines // CK_RV template_add_attributes( TEMPLATE * tmpl, CK_ATTRIBUTE * attr, CK_ULONG ulCount ); CK_RV template_add_default_attributes( TEMPLATE * tmpl, TEMPLATE * basetmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode ); CK_BBOOL template_attribute_find( TEMPLATE * tmpl, CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE ** attr); void template_attribute_find_multiple( TEMPLATE *tmpl, ATTRIBUTE_PARSE_LIST *parselist, CK_ULONG plcount ); CK_BBOOL template_check_exportability( TEMPLATE *tmpl, CK_ATTRIBUTE_TYPE type ); CK_RV template_check_required_attributes( TEMPLATE * tmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode ); CK_RV template_check_required_base_attributes( TEMPLATE * tmpl, CK_ULONG mode ); CK_BBOOL template_compare( CK_ATTRIBUTE * t1, CK_ULONG ulCount, TEMPLATE * t2 ); CK_RV template_copy( TEMPLATE * dest, TEMPLATE * src ); CK_RV template_flatten( TEMPLATE * tmpl, CK_BYTE * dest ); CK_RV template_free( TEMPLATE *tmpl ); CK_BBOOL template_get_class( TEMPLATE * tmpl, CK_ULONG * class, CK_ULONG * subclass ); CK_ULONG template_get_count( TEMPLATE *tmpl ); CK_ULONG template_get_size( TEMPLATE *tmpl ); CK_ULONG template_get_compressed_size( TEMPLATE *tmpl ); CK_RV template_set_default_common_attributes( TEMPLATE *tmpl ); CK_RV template_merge( TEMPLATE *dest, TEMPLATE **src ); CK_RV template_update_attribute( TEMPLATE * tmpl, CK_ATTRIBUTE * attr ); CK_RV template_unflatten( TEMPLATE ** tmpl, CK_BYTE * data, CK_ULONG count ); CK_RV template_unflatten_withSize( TEMPLATE ** new_tmpl, CK_BYTE * buf, CK_ULONG count, int buf_size ); CK_RV template_validate_attribute( TEMPLATE * tmpl, CK_ATTRIBUTE * attr, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode ); CK_RV template_validate_attributes( TEMPLATE * tmpl, CK_ULONG class, CK_ULONG subclass, CK_ULONG mode ); CK_RV template_validate_base_attribute( TEMPLATE * tmpl, CK_ATTRIBUTE * attr, CK_ULONG mode ); // DATA OBJECT ROUTINES // CK_RV data_object_check_required_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV data_object_set_default_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV data_object_validate_attribute ( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // CERTIFICATE ROUTINES // CK_RV cert_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cert_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV cert_x509_check_required_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cert_x509_set_default_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cert_x509_validate_attribute ( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV cert_vendor_check_required_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cert_vendor_validate_attribute ( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // // KEY ROUTINES // CK_RV key_object_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV key_object_set_default_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV key_object_validate_attribute ( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV publ_key_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV publ_key_set_default_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV publ_key_validate_attribute ( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV priv_key_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV priv_key_set_default_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV priv_key_unwrap( TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL isopaque ); CK_RV priv_key_validate_attribute ( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_BBOOL secret_key_check_exportability( CK_ATTRIBUTE_TYPE type ); CK_RV secret_key_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV secret_key_set_default_attributes ( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV secret_key_unwrap( TEMPLATE *tmpl, CK_ULONG keytype, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ); CK_RV secret_key_validate_attribute ( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // rsa routines // CK_RV rsa_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rsa_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV rsa_publ_set_default_attributes( TEMPLATE *tmpl, TEMPLATE *basetmpl, CK_ULONG mode ); CK_BBOOL rsa_priv_check_exportability( CK_ATTRIBUTE_TYPE type ); CK_RV rsa_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rsa_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rsa_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV rsa_priv_wrap_get_data( TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ); CK_RV rsa_priv_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL isopaque ); // dsa routines // CK_RV dsa_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dsa_publ_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dsa_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_BBOOL dsa_priv_check_exportability( CK_ATTRIBUTE_TYPE type ); CK_RV dsa_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dsa_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dsa_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV dsa_priv_wrap_get_data( TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ); CK_RV dsa_priv_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len ); // ecdsa routines // CK_RV ecdsa_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV ecdsa_publ_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV ecdsa_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_BBOOL ecdsa_priv_check_exportability( CK_ATTRIBUTE_TYPE type ); CK_RV ecdsa_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV ecdsa_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV ecdsa_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // diffie-hellman routines // CK_RV dh_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dh_publ_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dh_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_BBOOL dh_priv_check_exportability( CK_ATTRIBUTE_TYPE type ); CK_RV dh_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dh_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV dh_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // KEA routines // CK_RV kea_publ_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV kea_publ_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV kea_publ_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_BBOOL kea_priv_check_exportability( CK_ATTRIBUTE_TYPE type ); CK_RV kea_priv_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV kea_priv_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV kea_priv_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // Generic secret key routines CK_RV generic_secret_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV generic_secret_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV generic_secret_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV generic_secret_wrap_get_data( TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ); CK_RV generic_secret_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ); // RC2 routines CK_RV rc2_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rc2_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rc2_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // RC4 routines CK_RV rc4_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rc4_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rc4_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // RC5 routines CK_RV rc5_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rc5_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV rc5_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // DES routines CK_RV des_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_BBOOL des_check_weak_key( CK_BYTE *key ); CK_RV des_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV des_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ); CK_RV des_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV des_wrap_get_data( TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ); // DES2 routines CK_RV des2_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV des2_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV des2_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // DES3 routines CK_RV des3_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV des3_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV des3_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ); CK_RV des3_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV des3_wrap_get_data( TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ); // AES routines CK_RV aes_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV aes_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV aes_unwrap( TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG data_len, CK_BBOOL fromend, CK_BBOOL isopaque ); CK_RV aes_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); CK_RV aes_wrap_get_data( TEMPLATE *tmpl, CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len ); // CAST routines CK_RV cast_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cast_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cast_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // CAST3 routines CK_RV cast3_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cast3_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cast3_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // CAST5 routines CK_RV cast5_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cast5_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cast5_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // IDEA routines CK_RV idea_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV idea_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV idea_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // CDMF routines CK_RV cdmf_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cdmf_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV cdmf_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // SKIPJACK routines CK_RV skipjack_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV skipjack_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV skipjack_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // BATON routines CK_RV baton_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV baton_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV baton_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // JUNIPER routines CK_RV juniper_check_required_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV juniper_set_default_attributes( TEMPLATE *tmpl, CK_ULONG mode ); CK_RV juniper_validate_attribute( TEMPLATE *tmpl, CK_ATTRIBUTE *attr, CK_ULONG mode ); // modular math routines // CK_RV mp_subtract( CK_BYTE *bigint, CK_ULONG val, CK_ULONG len ); CK_RV mp_mult( CK_BYTE *bigint_a, CK_ULONG a_len, CK_BYTE *bigint_b, CK_ULONG b_len, CK_BYTE *bigint_c, CK_ULONG c_len, CK_BYTE *result, CK_ULONG *result_len ); CK_RV mp_exp( CK_BYTE *bigint_a, CK_ULONG a_len, CK_BYTE *bigint_b, CK_ULONG b_len, CK_BYTE *bigint_c, CK_ULONG c_len, CK_BYTE *result, CK_ULONG *result_len ); // ASN.1 routines // CK_ULONG ber_encode_INTEGER( CK_BBOOL length_only, CK_BYTE ** ber_int, CK_ULONG * ber_int_len, CK_BYTE * data, CK_ULONG data_len ); CK_RV ber_decode_INTEGER( CK_BYTE * ber_int, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len ); CK_RV ber_encode_OCTET_STRING( CK_BBOOL length_only, CK_BYTE ** str, CK_ULONG * str_len, CK_BYTE * data, CK_ULONG data_len ); CK_RV ber_decode_OCTET_STRING( CK_BYTE * str, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len ); CK_RV ber_encode_SEQUENCE( CK_BBOOL length_only, CK_BYTE ** seq, CK_ULONG * seq_len, CK_BYTE * data, CK_ULONG data_len ); CK_RV ber_decode_SEQUENCE( CK_BYTE * seq, CK_BYTE ** data, CK_ULONG * data_len, CK_ULONG * field_len ); CK_RV ber_encode_PrivateKeyInfo( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len, CK_BYTE * algorithm_id, CK_ULONG algorithm_id_len, CK_BYTE * priv_key, CK_ULONG priv_key_len ); CK_RV ber_decode_PrivateKeyInfo( CK_BYTE * data, CK_ULONG data_len, CK_BYTE ** algorithm_id, CK_ULONG * alg_len, CK_BYTE ** priv_key ); CK_RV ber_encode_RSAPrivateKey( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len, CK_ATTRIBUTE * modulus, CK_ATTRIBUTE * publ_exp, CK_ATTRIBUTE * priv_exp, CK_ATTRIBUTE * prime1, CK_ATTRIBUTE * prime2, CK_ATTRIBUTE * exponent1, CK_ATTRIBUTE * exponent2, CK_ATTRIBUTE * coeff, CK_ATTRIBUTE * opaque ); CK_RV ber_decode_RSAPrivateKey( CK_BYTE * data, CK_ULONG data_len, CK_ATTRIBUTE ** modulus, CK_ATTRIBUTE ** publ_exp, CK_ATTRIBUTE ** priv_exp, CK_ATTRIBUTE ** prime1, CK_ATTRIBUTE ** prime2, CK_ATTRIBUTE ** exponent1, CK_ATTRIBUTE ** exponent2, CK_ATTRIBUTE ** coeff, CK_ATTRIBUTE ** opaque, CK_BBOOL isopaque ); CK_RV ber_encode_DSAPrivateKey( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len, CK_ATTRIBUTE * prime1, CK_ATTRIBUTE * prime2, CK_ATTRIBUTE * base, CK_ATTRIBUTE * priv_key ); CK_RV ber_decode_DSAPrivateKey( CK_BYTE * data, CK_ULONG data_len, CK_ATTRIBUTE ** prime, CK_ATTRIBUTE ** subprime, CK_ATTRIBUTE ** base, CK_ATTRIBUTE ** priv_key ); #include "tok_spec_struct.h" extern token_spec_t token_specific; /* logging */ #define OCK_SYSLOG(priority, fmt, ...) \ syslog(priority, "%s " fmt, __FILE__, ##__VA_ARGS__); /* CKA_HIDDEN will be used to filter return results on a C_FindObjects call. * Used for objects internal to a token for management of that token */ #define CKA_HIDDEN CKA_VENDOR_DEFINED + 0x01000000 #endif opencryptoki+dfsg/usr/lib/pkcs11/common/mech_ssl3.c0000755000175000017500000023264312630407154021311 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: mech_ssl3.c // // Mechanisms for SSL v3 support // #include #include // for memcmp() et al #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" CK_RV ssl3_kmd_process_mac_keys( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * client_handle, CK_BYTE * client_value, CK_OBJECT_HANDLE * server_handle, CK_BYTE * server_value, CK_ULONG mac_len ); CK_RV ssl3_kmd_process_write_keys( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_KEY_TYPE keytype, CK_OBJECT_HANDLE * client_handle, CK_BYTE * client_value, CK_OBJECT_HANDLE * server_handle, CK_BYTE * server_value, CK_ULONG write_len ); // The 'ssl3_mac_*' routines are used with the following mechanisms // // CKM_SSL3_MD5_MAC // CKM_SSL3_SHA1_MAC // // // CK_RV ssl3_mac_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE hash[SHA1_HASH_SIZE]; CK_BYTE * key_data = NULL; CK_BYTE inner[48], outer[48]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_ULONG key_bytes, hash_len, mac_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } mac_len = *(CK_ULONG *)ctx->mech.pParameter; if (length_only == TRUE) { *out_data_len = mac_len; return CKR_OK; } if (*out_data_len < mac_len) { *out_data_len = mac_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else { key_bytes = attr->ulValueLen; key_data = attr->pValue; } // unlike an HMAC operation, we don't XOR the key with the 0x36 or 0x5C. // we just append 48 bytes to the key data // memset( inner, 0x36, 48 ); memset( outer, 0x5C, 48 ); if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) digest_mech.mechanism = CKM_MD5; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, key_data, key_bytes ); if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC){ rc = digest_mgr_digest_update( sess, &digest_ctx, inner, 48 ); } else { rc = digest_mgr_digest_update( sess, &digest_ctx, inner, 40 ); } if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest final failed.\n"); return rc; } memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); // outer hash // rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, key_data, key_bytes ); if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) rc = digest_mgr_digest_update( sess, &digest_ctx, outer, 48 ); else rc = digest_mgr_digest_update( sess, &digest_ctx, outer, 40 ); if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, hash, hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest final failed.\n"); return rc; } memcpy( out_data, hash, mac_len ); *out_data_len = mac_len; return rc; } // // CK_RV ssl3_mac_sign_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * key_data = NULL; SSL3_MAC_CONTEXT * context = NULL; CK_BYTE inner[48]; CK_MECHANISM digest_mech; CK_ULONG key_bytes; CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (SSL3_MAC_CONTEXT *)ctx->context; if (context->flag == FALSE) { rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else { key_bytes = attr->ulValueLen; key_data = attr->pValue; } // unlike an HMAC operation, we don't XOR the key with the 0x36 or 0x5C. // we just append 48 bytes to the key data // memset( inner, 0x36, 48 ); if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) digest_mech.mechanism = CKM_MD5; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init( sess, &context->hash_context, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &context->hash_context, key_data, key_bytes ); if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) rc = digest_mgr_digest_update( sess, &context->hash_context, inner, 48 ); else rc = digest_mgr_digest_update( sess, &context->hash_context, inner, 40 ); if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } context->flag = TRUE; } rc = digest_mgr_digest_update( sess, &context->hash_context, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest update failed.\n"); return rc; } return CKR_OK; } // // CK_RV ssl3_mac_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * key_data = NULL; CK_BYTE hash[SHA1_HASH_SIZE]; SSL3_MAC_CONTEXT * context = NULL; CK_BYTE outer[48]; CK_MECHANISM digest_mech; CK_ULONG key_bytes, hash_len, mac_len; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } mac_len = *(CK_ULONG *)ctx->mech.pParameter; if (length_only == TRUE) { *out_data_len = mac_len; return CKR_OK; } if (*out_data_len < mac_len) { *out_data_len = mac_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } context = (SSL3_MAC_CONTEXT *)ctx->context; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else { key_bytes = attr->ulValueLen; key_data = attr->pValue; } // finish the inner hash // hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &context->hash_context, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Final failed.\n"); return rc; } // now, do the outer hash // memset( &context->hash_context, 0x0, sizeof(SSL3_MAC_CONTEXT) ); memset( outer, 0x5C, 48 ); if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) digest_mech.mechanism = CKM_MD5; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &context->hash_context, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &context->hash_context, key_data, key_bytes ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) rc = digest_mgr_digest_update( sess, &context->hash_context, outer, 48 ); else rc = digest_mgr_digest_update( sess, &context->hash_context, outer, 40 ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &context->hash_context, hash, hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &context->hash_context, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Final failed.\n"); return rc; } memcpy( out_data, hash, mac_len ); *out_data_len = mac_len; return rc; } // This routine could replace the HMAC verification routines // CK_RV ssl3_mac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { CK_BYTE mac[SHA1_HASH_SIZE]; SIGN_VERIFY_CONTEXT mac_ctx; CK_ULONG mac_len, len; CK_RV rc; if (!sess || !ctx || !in_data || !signature){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } mac_len = *(CK_ULONG *)ctx->mech.pParameter; memset( &mac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT) ); rc = sign_mgr_init( sess, &mac_ctx, &ctx->mech, FALSE, ctx->key ); if (rc != CKR_OK){ TRACE_DEVEL("Sign Init failed.\n"); goto error; } len = sizeof(mac); rc = sign_mgr_sign( sess, FALSE, &mac_ctx, in_data, in_data_len, mac, &len ); if (rc != CKR_OK){ TRACE_DEVEL("Sign failed.\n"); goto error; } if ((len != mac_len) || (len != sig_len)) { rc = CKR_SIGNATURE_LEN_RANGE; TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); goto error; } if (memcmp(mac, signature, mac_len) != 0){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rc = CKR_SIGNATURE_INVALID; } error: sign_mgr_cleanup( &mac_ctx ); return rc; } // // CK_RV ssl3_mac_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * key_data = NULL; SSL3_MAC_CONTEXT * context = NULL; CK_BYTE inner[48]; CK_MECHANISM digest_mech; CK_ULONG key_bytes; CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (SSL3_MAC_CONTEXT *)ctx->context; if (context->flag == FALSE) { rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else { key_bytes = attr->ulValueLen; key_data = attr->pValue; } // unlike an HMAC operation, we don't XOR the key with the 0x36 or 0x5C. // we just append 48 bytes to the key data // memset( inner, 0x36, 48 ); if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) digest_mech.mechanism = CKM_MD5; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init( sess, &context->hash_context, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &context->hash_context, key_data, key_bytes ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) rc = digest_mgr_digest_update( sess, &context->hash_context, inner, 48 ); else rc = digest_mgr_digest_update( sess, &context->hash_context, inner, 40 ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } context->flag = TRUE; } rc = digest_mgr_digest_update( sess, &context->hash_context, in_data, in_data_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } return CKR_OK; } // // CK_RV ssl3_mac_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG sig_len ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * key_data = NULL; SSL3_MAC_CONTEXT * context = NULL; CK_BYTE hash[SHA1_HASH_SIZE]; CK_BYTE outer[48]; CK_MECHANISM digest_mech; CK_ULONG key_bytes, hash_len, mac_len; CK_RV rc; if (!sess || !ctx || !signature){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } mac_len = *(CK_ULONG *)ctx->mech.pParameter; context = (SSL3_MAC_CONTEXT *)ctx->context; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find( key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else { key_bytes = attr->ulValueLen; key_data = attr->pValue; } // finish the inner hash // hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &context->hash_context, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Final failed.\n"); return rc; } // now, do the outer hash // memset( &context->hash_context, 0x0, sizeof(SSL3_MAC_CONTEXT) ); memset( outer, 0x5C, 48 ); if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) digest_mech.mechanism = CKM_MD5; else digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &context->hash_context, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &context->hash_context, key_data, key_bytes ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } if (ctx->mech.mechanism == CKM_SSL3_MD5_MAC) rc = digest_mgr_digest_update( sess, &context->hash_context, outer, 48 ); else rc = digest_mgr_digest_update( sess, &context->hash_context, outer, 40 ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &context->hash_context, hash, hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &context->hash_context, hash, &hash_len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Final failed.\n"); return rc; } if ((mac_len != sig_len) || (mac_len > hash_len)){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rc = CKR_SIGNATURE_INVALID; } else if (memcmp(signature, hash, sig_len) != 0){ rc = CKR_SIGNATURE_INVALID; TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); } return rc; } // // CK_RV ckm_ssl3_pre_master_key_gen( TEMPLATE * tmpl, CK_MECHANISM * mech ) { CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * value_len_attr = NULL; CK_ATTRIBUTE * key_type_attr = NULL; CK_ATTRIBUTE * class_attr = NULL; CK_ATTRIBUTE * local_attr = NULL; CK_ATTRIBUTE * derive_attr = NULL; CK_VERSION * version = NULL; CK_BYTE key[48]; CK_ULONG rc; rc = rng_generate( key, 48 ); if (rc != CKR_OK){ TRACE_DEVEL("rng_generate failed.\n"); return rc; } value_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + 48 ); value_len_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); key_type_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); class_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); local_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); derive_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!value_attr || !value_len_attr || !key_type_attr || !class_attr || !local_attr || !derive_attr) { if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); if (key_type_attr) free( key_type_attr ); if (class_attr) free( class_attr ); if (local_attr) free( local_attr ); if (derive_attr) free( derive_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } version = (CK_VERSION *)mech->pParameter; key[0] = version->major; key[1] = version->minor; value_attr->type = CKA_VALUE; value_attr->ulValueLen = 48; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); memcpy( value_attr->pValue, key, 48 ); value_len_attr->type = CKA_VALUE_LEN; value_len_attr->ulValueLen = sizeof(CK_ULONG); value_len_attr->pValue = (CK_BYTE *)value_len_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_len_attr->pValue = 48; key_type_attr->type = CKA_KEY_TYPE; key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE); key_type_attr->pValue = (CK_BYTE *)key_type_attr + sizeof(CK_ATTRIBUTE); *(CK_ATTRIBUTE_TYPE *)key_type_attr = CKK_GENERIC_SECRET; class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY; local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = TRUE; derive_attr->type = CKA_DERIVE; derive_attr->ulValueLen = sizeof(CK_BBOOL); derive_attr->pValue = (CK_BYTE *)derive_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)derive_attr->pValue = TRUE; template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, value_len_attr ); template_update_attribute( tmpl, key_type_attr ); template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, local_attr ); template_update_attribute( tmpl, derive_attr ); return CKR_OK; } // // static CK_RV ssl3_sha_then_md5( SESSION * sess, CK_BYTE * secret, CK_BYTE * firstRandom, CK_ULONG firstRandomLen, CK_BYTE * secondRandom, CK_ULONG secondRandomLen, CK_BYTE * variableData, CK_ULONG variableDataLen, CK_BYTE * outBuff ) { DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE hash[SHA1_HASH_SIZE]; CK_ULONG len; CK_RV rc; // SHA(variableData + secret + firstRandom + secondRandom) // memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, variableData, variableDataLen ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, secret, 48 ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, firstRandom, firstRandomLen ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, secondRandom, secondRandomLen ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Final failed.\n"); return rc; } // MD5(secret + SHA(...)) // memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); digest_mech.mechanism = CKM_MD5; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, secret, 48 ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, hash, len ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &len ); if (rc == CKR_OK){ memcpy( outBuff, hash, len ); } else TRACE_DEVEL("Digest Final failed.\n"); return rc; } // // static CK_RV ssl3_md5_only( SESSION * sess, CK_BYTE * firstString, CK_ULONG firstStringLen, CK_BYTE * secondString, CK_ULONG secondStringLen, CK_BYTE * thirdString, CK_ULONG thirdStringLen, CK_BYTE * outBuff ) { DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE hash[MD5_HASH_SIZE]; CK_ULONG len; CK_RV rc; // If firstString is not NULL, // // MD5(firstString + secondString + thirdString) // // If firstString is NULL // // MD5(secondString + thirdString) // memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); digest_mech.mechanism = CKM_MD5; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init( sess, &digest_ctx, &digest_mech ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Init failed.\n"); return rc; } if (firstString != NULL) { rc = digest_mgr_digest_update( sess, &digest_ctx, firstString, firstStringLen ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } } rc = digest_mgr_digest_update( sess, &digest_ctx, secondString, secondStringLen ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } rc = digest_mgr_digest_update( sess, &digest_ctx, thirdString, thirdStringLen ); if (rc != CKR_OK){ TRACE_DEVEL("Digest Update failed.\n"); return rc; } len = sizeof(hash); rc = digest_mgr_digest_final( sess, FALSE, &digest_ctx, hash, &len ); if (rc == CKR_OK){ TRACE_DEVEL("Digest Final failed.\n"); memcpy( outBuff, hash, len ); } return rc; } // // CK_RV ssl3_master_key_derive( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle ) { OBJECT * derived_key_obj = NULL; OBJECT * base_key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * value_len_attr = NULL; CK_ATTRIBUTE * always_sens_attr = NULL; CK_ATTRIBUTE * extract_attr = NULL; CK_BYTE * base_key_value = NULL; CK_BYTE key_data[48]; CK_ULONG i, base_key_len; CK_BBOOL flag; CK_RV rc; CK_SSL3_MASTER_KEY_DERIVE_PARAMS * params = NULL; CK_SSL3_RANDOM_DATA * random_data = NULL; if (!sess || !mech){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } params = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)mech->pParameter; rc = object_mgr_find_in_map1( base_key, &base_key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find( base_key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find in the template\n"); return CKR_FUNCTION_FAILED; } else { base_key_len = attr->ulValueLen; base_key_value = attr->pValue; if (base_key_len != 48){ TRACE_ERROR("The base key's length is not 48.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } // this mechanism implies the following attributes: // CKA_CLASS : CKO_SECRET_KEY // CKA_KEY_TYPE : CKK_GENERIC_SECRET // CKA_VALUE_LEN : 48 // but we need to make sure the caller didn't specify any // wacky values. it would have been better if Cryptoki had forbidden // these attributes from appearing in the template // for (i=0, attr = pTemplate; i < ulCount; i++, attr++) { CK_OBJECT_CLASS class; CK_KEY_TYPE keytype; CK_ULONG value_len; if (attr->type == CKA_CLASS) { class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_SECRET_KEY){ TRACE_ERROR("This operation requires a secret key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } else if (attr->type == CKA_KEY_TYPE) { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_GENERIC_SECRET){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } else if (attr->type == CKA_VALUE_LEN) { value_len = *(CK_ULONG *)attr->pValue; if (value_len != 48){ TRACE_ERROR("The derived key's length is not 48.\n"); return CKR_TEMPLATE_INCONSISTENT; } } } memset( key_data, 0x0, sizeof(key_data) ); random_data = (CK_SSL3_RANDOM_DATA *)(¶ms->RandomInfo); // derive the master key data // rc = ssl3_sha_then_md5( sess, base_key_value, random_data->pClientRandom, random_data->ulClientRandomLen, random_data->pServerRandom, random_data->ulServerRandomLen, (unsigned char *)"A", 1, key_data ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_sha_then_md5 failed.\n"); goto error; } rc = ssl3_sha_then_md5( sess, base_key_value, random_data->pClientRandom, random_data->ulClientRandomLen, random_data->pServerRandom, random_data->ulServerRandomLen, (unsigned char *)"BB", 2, &key_data[16] ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_sha_then_md5 failed.\n"); goto error; } rc = ssl3_sha_then_md5( sess, base_key_value, random_data->pClientRandom, random_data->ulClientRandomLen, random_data->pServerRandom, random_data->ulServerRandomLen, (unsigned char *)"CCC", 3, &key_data[32] ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_sha_then_md5 failed.\n"); goto error; } // build the key skeleton // rc = object_mgr_create_skel( sess, pTemplate, ulCount, MODE_DERIVE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, &derived_key_obj ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Skeleton failed.\n"); goto error; } rc = build_attribute( CKA_VALUE, key_data, 48, &value_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_VALUE attribute.\n"); goto error; } rc = build_attribute( CKA_VALUE_LEN, (CK_BYTE *)&base_key_len, sizeof(CK_ULONG), &value_len_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_VALUE_LEN attribute.\n"); goto error; } // // now, adjust the CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE // attributes based on the corresponding values from the base key // // if base key has ALWAYS_SENSITIVE = FALSE, then new key does too // otherwise, the value of CKA_ALWAYS_SENSITIVE = CKA_SENSITIVE // rc = template_attribute_find( base_key_obj->template, CKA_ALWAYS_SENSITIVE, &attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_ALWAYS_SENSITIVE in the template\n"); rc = CKR_FUNCTION_FAILED; goto error; } flag = *(CK_BBOOL *)attr->pValue; if (flag == TRUE) { rc = template_attribute_find( derived_key_obj->template, CKA_SENSITIVE, &attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_SENSITIVE in the template\n"); rc = CKR_FUNCTION_FAILED; goto error; } flag = *(CK_BBOOL *)attr->pValue; } rc = build_attribute( CKA_ALWAYS_SENSITIVE, &flag, sizeof(CK_BBOOL), &always_sens_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_ALWAYS_SENSITIVE attribute.\n"); goto error; } // if base key has NEVER_EXTRACTABLE = FASE, the new key does too // otherwise, the value of CKA_NEVER_EXTRACTABLE = !CKA_EXTRACTABLE // rc = template_attribute_find( base_key_obj->template, CKA_NEVER_EXTRACTABLE, &attr ); if (rc == FALSE) { TRACE_DEVEL("Failed to build CKA_NEVER_EXTRACTABLE attribute.\n"); rc = CKR_FUNCTION_FAILED; goto error; } flag = *(CK_BBOOL *)attr->pValue; if (flag == TRUE) { rc = template_attribute_find( derived_key_obj->template, CKA_EXTRACTABLE, &attr ); if (rc == FALSE) { TRACE_DEVEL("Failed to build CKA_EXTRACTABLE attribute.\n"); rc = CKR_FUNCTION_FAILED; goto error; } flag = *(CK_BBOOL *)attr->pValue; flag = (~flag) & 0x1; } rc = build_attribute( CKA_NEVER_EXTRACTABLE, &flag, sizeof(CK_BBOOL), &extract_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_NEVER_EXTRACTABLE attribute.\n"); goto error; } template_update_attribute( derived_key_obj->template, value_attr ); template_update_attribute( derived_key_obj->template, value_len_attr ); template_update_attribute( derived_key_obj->template, always_sens_attr ); template_update_attribute( derived_key_obj->template, extract_attr ); // at this point, the derived key is fully constructed...assign an // object handle and store the key // rc = object_mgr_create_final( sess, derived_key_obj, handle ); if (rc != CKR_OK) { TRACE_DEVEL("Object Mgr create final failed.\n"); object_free( derived_key_obj ); return rc; // do NOT goto error } // should we destroy the base key? SSL3 says yes but that might // occur in a separate call to C_DestroyObject // return CKR_OK; error: if (value_attr) free( value_attr ); if (value_len_attr) free( value_len_attr ); if (always_sens_attr) free( always_sens_attr ); if (extract_attr) free( extract_attr ); return rc; } // // CK_RV ssl3_key_and_mac_derive( SESSION * sess, CK_MECHANISM * mech, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ) { OBJECT * base_key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * client_MAC_key_value = NULL; CK_BYTE * server_MAC_key_value = NULL; CK_BYTE * client_write_key_value = NULL; CK_BYTE * server_write_key_value = NULL; CK_BYTE * client_IV = NULL; CK_BYTE * server_IV = NULL; CK_KEY_TYPE keytype = 0xFFFFFFFF; CK_BYTE variable_data[26]; CK_BYTE key_block[(16*26) + (4*16)]; CK_ULONG i, key_material_loop_count; CK_ULONG iv_len = 0, MAC_len, write_len; CK_RV rc; CK_BYTE * base_key_value = NULL; CK_BBOOL base_sensitive; CK_BBOOL base_always_sensitive; CK_BBOOL base_extractable; CK_BBOOL base_never_extractable; CK_OBJECT_HANDLE client_MAC_handle = 0; CK_OBJECT_HANDLE server_MAC_handle = 0; CK_OBJECT_HANDLE client_write_handle = 0; CK_OBJECT_HANDLE server_write_handle = 0; CK_SSL3_KEY_MAT_PARAMS * params = NULL; ATTRIBUTE_PARSE_LIST base_attrs[] = { {CKA_SENSITIVE , &base_sensitive , sizeof(CK_BBOOL), FALSE}, {CKA_EXTRACTABLE , &base_extractable , sizeof(CK_BBOOL), FALSE}, {CKA_ALWAYS_SENSITIVE , &base_always_sensitive , sizeof(CK_BBOOL), FALSE}, {CKA_NEVER_EXTRACTABLE, &base_never_extractable, sizeof(CK_BBOOL), FALSE}, }; if (!sess || !mech){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } params = (CK_SSL3_KEY_MAT_PARAMS *)mech->pParameter; rc = object_mgr_find_in_map1( base_key, &base_key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find( base_key_obj->template, CKA_VALUE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else base_key_value = attr->pValue; template_attribute_find_multiple( base_key_obj->template, base_attrs, 4 ); for (i=0; i < 4; i++) { if (base_attrs[i].found == FALSE){ TRACE_ERROR("Could not find attribute in the template\n"); return CKR_FUNCTION_FAILED; } } // The SSL3 spec says the IVs are 16 bytes long in the exportable case. // For now, we'll barf if someone asks for an exportable output and asks // for more than 128 bits of IV... // if (params->bIsExport != FALSE && params->ulIVSizeInBits > 128){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // the template must specify the key type for the client and server keys // // also, CKA_SENSITIVE, CKA_ALWAYS_SENSITIVE, CKA_EXTRACTABLE and // CKA_NEVER_EXTRACTABLE, if present, are not allowed to differ from // the base key. We also check for stupid stuff. // for (i=0, attr = pTemplate; i < ulCount; i++, attr++) { CK_BBOOL tmp; if (attr->type == CKA_KEY_TYPE) keytype = *(CK_KEY_TYPE *)attr->pValue; else if (attr->type == CKA_SENSITIVE) { tmp = *(CK_BBOOL *)attr->pValue; if (tmp != base_sensitive){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } else if (attr->type == CKA_ALWAYS_SENSITIVE) { tmp = *(CK_BBOOL *)attr->pValue; if (tmp != base_always_sensitive){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } else if (attr->type == CKA_EXTRACTABLE) { tmp = *(CK_BBOOL *)attr->pValue; if (tmp != base_extractable){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } else if (attr->type == CKA_NEVER_EXTRACTABLE) { tmp = *(CK_BBOOL *)attr->pValue; if (tmp != base_never_extractable){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } else if (attr->type == CKA_CLASS) { CK_OBJECT_CLASS cl = *(CK_OBJECT_CLASS *)attr->pValue; if (cl != CKO_SECRET_KEY){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } } } // a key type must be specified for the client and server write keys // if (keytype == 0xFFFFFFFF){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } // figure out how much key material we need to generate // key_material_loop_count = 2 * ((params->ulMacSizeInBits + 7) / 8) + 2 * ((params->ulKeySizeInBits + 7) / 8); if (params->bIsExport == FALSE) key_material_loop_count += 2 * ((params->ulIVSizeInBits + 7) / 8); // we stop at 'ZZZZ....' presumably this is enough for all cases? // if (key_material_loop_count > 26 * 16){ TRACE_DEVEL("key_material_loop_count is too big.\n"); return CKR_FUNCTION_FAILED; } key_material_loop_count = (key_material_loop_count + 15) / 16; // generate the key material // for (i=0; i < key_material_loop_count; i++) { memset( variable_data, ('A' + i), i+1 ); rc = ssl3_sha_then_md5( sess, base_key_value, params->RandomInfo.pServerRandom, params->RandomInfo.ulServerRandomLen, params->RandomInfo.pClientRandom, params->RandomInfo.ulClientRandomLen, variable_data, i+1, &(key_block[i*16]) ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_sha_then_md5 failed.\n"); goto error; } } // Break key material into pieces // MAC_len = (params->ulMacSizeInBits + 7) / 8; write_len = (params->ulKeySizeInBits + 7) / 8; // check this client_MAC_key_value = key_block; server_MAC_key_value = client_MAC_key_value + MAC_len; client_write_key_value = server_MAC_key_value + MAC_len; server_write_key_value = client_write_key_value + (params->ulKeySizeInBits + 7)/8; if (params->ulIVSizeInBits != 0) { iv_len = (params->ulIVSizeInBits + 7) / 8; client_IV = server_write_key_value + write_len; server_IV = client_IV + iv_len; } // Exportable ciphers require additional processing // if (params->bIsExport == TRUE) { rc = ssl3_md5_only( sess, client_write_key_value, (params->ulKeySizeInBits + 7)/8, params->RandomInfo.pClientRandom, params->RandomInfo.ulClientRandomLen, params->RandomInfo.pServerRandom, params->RandomInfo.ulServerRandomLen, &(key_block[16*26]) ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_md5_only failed.\n"); goto error; } client_write_key_value = &(key_block[16*26]); rc = ssl3_md5_only( sess, server_write_key_value, (params->ulKeySizeInBits + 7)/8, params->RandomInfo.pServerRandom, params->RandomInfo.ulServerRandomLen, params->RandomInfo.pClientRandom, params->RandomInfo.ulClientRandomLen, &(key_block[16*26+16]) ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_md5_only failed.\n"); goto error; } server_write_key_value = &(key_block[16*26+16]); if (params->ulIVSizeInBits != 0) { rc = ssl3_md5_only( sess, NULL, 0, params->RandomInfo.pClientRandom, params->RandomInfo.ulClientRandomLen, params->RandomInfo.pServerRandom, params->RandomInfo.ulServerRandomLen, &(key_block[16*26+2*16]) ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_md5_only failed.\n"); goto error; } client_IV = &(key_block[16*26+2*16]); rc = ssl3_md5_only( sess, NULL, 0, params->RandomInfo.pServerRandom, params->RandomInfo.ulServerRandomLen, params->RandomInfo.pClientRandom, params->RandomInfo.ulClientRandomLen, &(key_block[16*26+3*16]) ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_md5_only failed.\n"); goto error; } server_IV = &(key_block[16*26+3*16]); } } rc = ssl3_kmd_process_mac_keys( sess, pTemplate, ulCount, &client_MAC_handle, client_MAC_key_value, &server_MAC_handle, server_MAC_key_value, MAC_len ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_kmd_process_mac_keys failed.\n"); goto error; } rc = ssl3_kmd_process_write_keys( sess, pTemplate, ulCount, keytype, &client_write_handle, client_write_key_value, &server_write_handle, server_write_key_value, write_len ); if (rc != CKR_OK){ TRACE_DEVEL("ssl3_kmd_process_write_keys failed.\n"); goto error; } params->pReturnedKeyMaterial->hClientMacSecret = client_MAC_handle; params->pReturnedKeyMaterial->hServerMacSecret = server_MAC_handle; params->pReturnedKeyMaterial->hClientKey = client_write_handle; params->pReturnedKeyMaterial->hServerKey = server_write_handle; if (params->ulIVSizeInBits != 0) { if (params->pReturnedKeyMaterial->pIVClient) memcpy( params->pReturnedKeyMaterial->pIVClient, client_IV, iv_len ); if (params->pReturnedKeyMaterial->pIVServer) memcpy( params->pReturnedKeyMaterial->pIVServer, server_IV, iv_len ); #if 0 CK_BYTE *p1, *p2; p1 = (CK_BYTE *)malloc( iv_len ); p2 = (CK_BYTE *)malloc( iv_len ); if (!p1 || !p2) { rc = CKR_HOST_MEMORY; goto error; } memcpy( p1, client_IV, iv_len ); memcpy( p2, server_IV, iv_len ); params->pReturnedKeyMaterial->pIVClient = p1; params->pReturnedKeyMaterial->pIVServer = p2; #endif } error: return rc; } CK_RV ssl3_kmd_process_mac_keys( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * client_handle, CK_BYTE * client_value, CK_OBJECT_HANDLE * server_handle, CK_BYTE * server_value, CK_ULONG mac_len ) { OBJECT * client_obj = NULL; OBJECT * server_obj = NULL; CK_ATTRIBUTE * client_val_attr = NULL; CK_ATTRIBUTE * client_val_len_attr = NULL; CK_ATTRIBUTE * server_val_attr = NULL; CK_ATTRIBUTE * server_val_len_attr = NULL; CK_ATTRIBUTE * attr = NULL; CK_ATTRIBUTE * new_attrs = NULL; CK_ULONG i, cnt; CK_ULONG true_vals[] = { CKA_SIGN, CKA_VERIFY, CKA_DERIVE }; CK_ULONG false_vals[] = { CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP }; CK_RV rc = 0; // for the MAC keys, we want the following default values: // CKA_SIGN, CKA_VERIFY, CKA_DERIVE = TRUE // CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP = FALSE // // attributes are added in sequential order so we stick the defaults // at the beginning so that they may be overridden by caller-specified // values. // new_attrs = (CK_ATTRIBUTE *)malloc((ulCount + 7) * (sizeof(CK_ATTRIBUTE))); if (!new_attrs) goto error; // we have to treat these attributes a bit differently. normally, we allocate // the CK_ATTRIBUTE and the value with a single malloc and just point the pValue // member to the extra space. we can't do that here because we have to "emulate" // the way attributes are passed in from the cryptoki application...as an array // of CK_ATTRIBUTEs with no extra space (that is, pValue must be allocated // separately). // attr = new_attrs; for (i=0; i < sizeof(true_vals) / sizeof(CK_ULONG); i++, attr++) { attr->type = true_vals[i]; attr->ulValueLen = sizeof(CK_BBOOL); attr->pValue = (CK_BBOOL *)malloc(sizeof(CK_BBOOL)); if (!attr->pValue) { rc = CKR_HOST_MEMORY; TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto error; } *(CK_BBOOL *)attr->pValue = TRUE; } for (i=0; i < sizeof(false_vals) / sizeof(CK_ULONG); i++, attr++) { attr->type = false_vals[i]; attr->ulValueLen = sizeof(CK_BBOOL); attr->pValue = (CK_BBOOL *)malloc(sizeof(CK_BBOOL)); if (!attr->pValue) { rc = CKR_HOST_MEMORY; TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto error; } *(CK_BBOOL *)attr->pValue = FALSE; } for (i=0, cnt=0; i < ulCount; i++) { if (pTemplate[i].type != CKA_KEY_TYPE && pTemplate[i].type != CKA_VALUE && pTemplate[i].type != CKA_VALUE_LEN) { attr->type = pTemplate[i].type; attr->ulValueLen = pTemplate[i].ulValueLen; attr->pValue = (char *)malloc(attr->ulValueLen); if (!attr->pValue) { rc = CKR_HOST_MEMORY; TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto error; } memcpy( attr->pValue, pTemplate[i].pValue, attr->ulValueLen ); cnt++; attr++; } } ulCount = 7 + cnt; // create the key skeletons // rc = object_mgr_create_skel( sess, new_attrs, ulCount, MODE_DERIVE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, &client_obj ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Skeleton failed.\n"); goto error; } rc = object_mgr_create_skel( sess, new_attrs, ulCount, MODE_DERIVE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, &server_obj ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Skeleton failed.\n"); goto error; } for (i=0; i < ulCount; i++) if (new_attrs[i].pValue) free( new_attrs[i].pValue ); free( new_attrs ); new_attrs = NULL; rc = build_attribute( CKA_VALUE, client_value, mac_len, &client_val_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_VALUE attribute.\n"); goto error; } rc = build_attribute( CKA_VALUE, server_value, mac_len, &server_val_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_VALUE attribute.\n"); goto error; } rc = build_attribute( CKA_VALUE_LEN, (CK_BYTE *)&mac_len, sizeof(CK_ULONG), &client_val_len_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_VALUE_LEN attribute.\n"); goto error; } rc = build_attribute( CKA_VALUE_LEN, (CK_BYTE *)&mac_len, sizeof(CK_ULONG), &server_val_len_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_VALUE_LEN attribute.\n"); goto error; } template_update_attribute( client_obj->template, client_val_attr ); template_update_attribute( client_obj->template, client_val_len_attr ); template_update_attribute( server_obj->template, server_val_attr ); template_update_attribute( server_obj->template, server_val_len_attr ); rc = object_mgr_create_final( sess, client_obj, client_handle ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Final failed.\n"); goto error; } rc = object_mgr_create_final( sess, server_obj, server_handle ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Final failed.\n"); goto error; } return CKR_OK; error: *client_handle = 0; *server_handle = 0; if (client_obj) { object_free( client_obj ); client_val_attr = NULL; // these get freed with the object client_val_len_attr = NULL; } if (server_obj) { object_free( server_obj ); server_val_attr = NULL; // these get freed with the object server_val_len_attr = NULL; } if (client_val_attr) free( client_val_attr ); if (client_val_len_attr) free( client_val_len_attr ); if (server_val_attr) free( server_val_attr ); if (server_val_len_attr) free( server_val_len_attr ); if (new_attrs) { for (i=0; i < ulCount; i++) { if (new_attrs[i].pValue) free( new_attrs[i].pValue ); } free( new_attrs ); } return rc; } CK_RV ssl3_kmd_process_write_keys( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_KEY_TYPE keytype, CK_OBJECT_HANDLE * client_handle, CK_BYTE * client_value, CK_OBJECT_HANDLE * server_handle, CK_BYTE * server_value, CK_ULONG write_len ) { CK_ATTRIBUTE * client_val_attr = NULL; CK_ATTRIBUTE * client_val_len_attr = NULL; CK_ATTRIBUTE * server_val_attr = NULL; CK_ATTRIBUTE * server_val_len_attr = NULL; CK_ATTRIBUTE * new_attrs = NULL; CK_ATTRIBUTE * attr = NULL; OBJECT * client_obj = NULL; OBJECT * server_obj = NULL; CK_ULONG i, cnt; CK_ULONG true_vals[] = { CKA_ENCRYPT, CKA_DECRYPT, CKA_DERIVE }; CK_ULONG false_vals[] = { CKA_SIGN, CKA_VERIFY, CKA_WRAP, CKA_UNWRAP }; CK_RV rc = CKR_HOST_MEMORY; // for the write keys, we want the following default values: // CKA_ENCRYPT, CKA_DECRYPT, CKA_DERIVE = TRUE // CKA_SIGN, CKA_VERIFY, CKA_WRAP, CKA_UNWRAP = FALSE // // attributes are added in sequential order so we stick the defaults // at the beginning so that they may be overridden by caller-specified // values. // new_attrs = (CK_ATTRIBUTE *)malloc((ulCount + 7) * (sizeof(CK_ATTRIBUTE))); if (!new_attrs) goto error; // we have to treat these attributes a bit differently. normally, we allocate // the CK_ATTRIBUTE and the value with a single malloc and just point the pValue // member to the extra space. we can't do that here because we have to "emulate" // the way attributes are passed in from the cryptoki application...as an array // of CK_ATTRIBUTEs with no extra space (that is, pValue must be allocated // separately). // attr = new_attrs; for (i=0; i < sizeof(true_vals) / sizeof(CK_ULONG); i++, attr++) { attr->type = true_vals[i]; attr->ulValueLen = sizeof(CK_BBOOL); attr->pValue = (CK_BBOOL *)malloc(sizeof(CK_BBOOL)); if (!attr->pValue) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto error; } *(CK_BBOOL *)attr->pValue = TRUE; } for (i=0; i < sizeof(false_vals) / sizeof(CK_ULONG); i++, attr++) { attr->type = false_vals[i]; attr->ulValueLen = sizeof(CK_BBOOL); attr->pValue = (CK_BBOOL *)malloc(sizeof(CK_BBOOL)); if (!attr->pValue) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto error; } *(CK_BBOOL *)attr->pValue = FALSE; } for (i=0, cnt=0; i < ulCount; i++) { if (pTemplate[i].type != CKA_KEY_TYPE && pTemplate[i].type != CKA_VALUE && pTemplate[i].type != CKA_VALUE_LEN) { attr->type = pTemplate[i].type; attr->ulValueLen = pTemplate[i].ulValueLen; attr->pValue = (char *)malloc(attr->ulValueLen); if (!attr->pValue) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto error; } memcpy( attr->pValue, pTemplate[i].pValue, attr->ulValueLen ); cnt++; attr++; } } ulCount = 7 + cnt; rc = object_mgr_create_skel( sess, new_attrs, ulCount, MODE_DERIVE, CKO_SECRET_KEY, keytype, &client_obj ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Skeleton failed.\n"); goto error; } rc = object_mgr_create_skel( sess, new_attrs, ulCount, MODE_DERIVE, CKO_SECRET_KEY, keytype, &server_obj ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Skeleton failed.\n"); goto error; } for (i=0; i < ulCount; i++) { if (new_attrs[i].pValue) free( new_attrs[i].pValue ); } free( new_attrs ); new_attrs = NULL; rc = build_attribute( CKA_VALUE, client_value, write_len, &client_val_attr ); rc |= build_attribute( CKA_VALUE, server_value, write_len, &server_val_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_VALUE attribute.\n"); goto error; } switch (keytype) { case CKK_GENERIC_SECRET: case CKK_DES: case CKK_DES2: case CKK_DES3: case CKK_RC2: case CKK_RC4: case CKK_RC5: case CKK_CAST: case CKK_CAST3: case CKK_CAST5: { rc = build_attribute( CKA_VALUE_LEN, (CK_BYTE *)&write_len, sizeof(CK_ULONG), &client_val_len_attr ); rc |= build_attribute( CKA_VALUE_LEN, (CK_BYTE *)&write_len, sizeof(CK_ULONG), &server_val_len_attr ); if (rc != CKR_OK){ TRACE_DEVEL("Failed to build CKA_VALUE_LEN attribute.\n"); goto error; } rc = template_validate_attribute( client_obj->template, client_val_len_attr, CKO_SECRET_KEY, keytype, MODE_DERIVE ); rc |= template_validate_attribute( server_obj->template, server_val_len_attr, CKO_SECRET_KEY, keytype, MODE_DERIVE ); // for these I use MODE_CREATE because I want to validate the value/length. // no othe modes are allowed to mess wiht CKA_VALUE (see for instance, // des_validate_attribute()) // rc |= template_validate_attribute( client_obj->template, client_val_attr, CKO_SECRET_KEY, keytype, MODE_CREATE ); rc |= template_validate_attribute( server_obj->template, server_val_attr, CKO_SECRET_KEY, keytype, MODE_CREATE ); if (rc != CKR_OK){ TRACE_DEVEL("template_validate_attribute failed.\n"); goto error; } template_update_attribute( client_obj->template, client_val_attr ); template_update_attribute( server_obj->template, server_val_attr ); template_update_attribute( client_obj->template, client_val_len_attr ); template_update_attribute( server_obj->template, server_val_len_attr ); // the object owns the attributes now... // client_val_attr = NULL; server_val_attr = NULL; client_val_len_attr = NULL; server_val_len_attr = NULL; } break; default: { rc = template_validate_attribute( client_obj->template, client_val_attr, CKO_SECRET_KEY, keytype, MODE_CREATE ); rc |= template_validate_attribute( server_obj->template, server_val_attr, CKO_SECRET_KEY, keytype, MODE_CREATE ); if (rc != CKR_OK){ TRACE_DEVEL("template_validate_attribute failed.\n"); goto error; } template_update_attribute( client_obj->template, client_val_attr ); template_update_attribute( server_obj->template, server_val_attr ); // the object owns the attributes now... // client_val_attr = NULL; server_val_attr = NULL; } } // finally, assign a handle to each key // rc = object_mgr_create_final( sess, client_obj, client_handle ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Final failed.\n"); goto error; } rc = object_mgr_create_final( sess, server_obj, server_handle ); if (rc != CKR_OK){ TRACE_DEVEL("Object Mgr Create Final failed.\n"); goto error; } return CKR_OK; error: *client_handle = 0; *server_handle = 0; if (client_obj) object_free( client_obj ); if (server_obj) object_free( server_obj ); // the only way these guys are non-NULL is if they were created but // not yet to added to an object // if (client_val_attr) free( client_val_attr ); if (client_val_len_attr) free( client_val_len_attr ); if (server_val_attr) free( server_val_attr ); if (server_val_len_attr) free( server_val_len_attr ); if (new_attrs) { for (i=0; i < ulCount; i++) { if (new_attrs[i].pValue) free( new_attrs[i].pValue ); } free( new_attrs ); } return rc; } opencryptoki+dfsg/usr/lib/pkcs11/common/obj_mgr.c0000755000175000017500000022421312630407154021042 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: obj_mgr.c // // Object manager related functions // #include #include #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" #include "../api/apiproto.h" pthread_rwlock_t obj_list_rw_mutex = PTHREAD_RWLOCK_INITIALIZER; CK_RV object_mgr_add( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE * handle ) { OBJECT * o = NULL; CK_BBOOL priv_obj, sess_obj; CK_BBOOL locked = FALSE; CK_RV rc; unsigned long obj_handle; if (!sess || !pTemplate || !handle){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK) { TRACE_ERROR("Mutex lock failed.\n"); return rc; } locked = TRUE; rc = object_create( pTemplate, ulCount, &o ); if (rc != CKR_OK){ TRACE_DEVEL("Object Create failed.\n"); goto done; } if (token_specific.t_object_add != NULL) { rc = token_specific.t_object_add(o); if (rc != CKR_OK) { TRACE_DEVEL("Token Specific object add failed.\n"); goto done; } } // check whether session has permissions to create the object, etc // // Object R/O R/W R/O R/W R/W // Type Public Public User User SO // ------------------------------------------------------------- // Public session R/W R/W R/W R/W R/W // Private session R/W R/W // Public token R/O R/W R/O R/W R/W // Private token R/O R/W // sess_obj = object_is_session_object( o ); priv_obj = object_is_private( o ); if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } if (!sess_obj) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (!sess_obj) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } } // okay, object is created and the session permissions look okay. // add the object to the appropriate list and assign an object handle // if (sess_obj) { o->session = sess; memset( o->name, 0x00, sizeof(CK_BYTE) * 8 ); if ((obj_handle = bt_node_add(&sess_obj_btree, o)) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } else { CK_BYTE current[8]; CK_BYTE next[8]; // we'll be modifying nv_token_data so we should protect this part with // the 'pkcs_mutex' // rc = XProcLock(); if (rc != CKR_OK){ TRACE_ERROR("Failed to get Process Lock.\n"); goto done; } else { // Determine if we have already reached our Max Token Objects // if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { rc = CKR_HOST_MEMORY; TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); XProcUnLock(); goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { rc = CKR_HOST_MEMORY; TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); XProcUnLock(); goto done; } } memcpy( current, &nv_token_data->next_token_object_name, 8 ); o->session = NULL; memcpy( &o->name, current, 8 ); rc = compute_next_token_obj_name( current, next ); if (rc != CKR_OK) { // TODO: handle error, check if rc is a valid per spec XProcUnLock(); goto done; } memcpy( &nv_token_data->next_token_object_name, next, 8 ); rc = save_token_object( o ); if (rc != CKR_OK) { // TODO: handle error, check if rc is a valid per spec XProcUnLock(); goto done; } // add the object identifier to the shared memory segment // object_mgr_add_to_shm( o ); XProcUnLock(); // save_token_data has to lock the mutex itself because it's used elsewhere // rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) { // TODO: handle error, check if rc is a valid per spec XProcUnLock(); goto done; } } // now, store the object in the appropriate btree // if (priv_obj) obj_handle = bt_node_add(&priv_token_obj_btree, o); else obj_handle = bt_node_add(&publ_token_obj_btree, o); if (!obj_handle) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } rc = object_mgr_add_to_map( sess, o, obj_handle, handle ); if (rc != CKR_OK) { // we need to remove the object from whatever btree we just added it to if (sess_obj) { // put the binary tree node which holds o on the free list, but pass NULL here, so that // o (the binary tree node's value pointer) isn't touched. It is free'd below bt_node_free(&sess_obj_btree, obj_handle, NULL); } else { // we'll want to delete the token object file too! // delete_token_object( o ); if (priv_obj) { // put the binary tree node which holds o on the free list, but pass NULL here, so that // o (the binary tree node's value pointer) isn't touched. It is free'd below bt_node_free(&priv_token_obj_btree, obj_handle, NULL); } else { // put the binary tree node which holds o on the free list, but pass NULL here, so that // o (the binary tree node's value pointer) isn't touched. It is free'd below bt_node_free(&publ_token_obj_btree, obj_handle, NULL); } rc = XProcLock(); if (rc != CKR_OK){ TRACE_ERROR("Failed to get Process Lock.\n"); goto done; } object_mgr_del_from_shm( o ); XProcUnLock(); } } done: if (locked) MY_UnlockMutex( &obj_list_mutex ); if ((rc != CKR_OK) && (o != NULL)) object_free( o ); return rc; } // object_mgr_add_to_map() // CK_RV object_mgr_add_to_map( SESSION * sess, OBJECT * obj, unsigned long obj_handle, CK_OBJECT_HANDLE * map_handle ) { OBJECT_MAP *map_node = NULL; if (!sess || !obj || !map_handle){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } // // this guy doesn't lock a mutex because it's calling routines should have // already locked it // map_node = (OBJECT_MAP *)malloc(sizeof(OBJECT_MAP)); if (!map_node){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } map_node->session = sess; if (obj->session != NULL) map_node->is_session_obj = TRUE; else map_node->is_session_obj = FALSE; map_node->is_private = object_is_private( obj ); // add the new map entry to the list if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { free(map_node); TRACE_DEVEL("Failed to acqquire mutex lock.\n"); return CKR_FUNCTION_FAILED; } // map_node->obj_handle will store the index of the btree node in one of these lists: // publ_token_obj_btree - for public token object // priv_token_obj_btree - for private token objects // sess_obj_btree - for session objects // // *map_handle, the application's CK_OBJECT_HANDLE, will then be the index of the btree node // in the object_map_btree // map_node->obj_handle = obj_handle; *map_handle = bt_node_add(&object_map_btree, map_node); pthread_rwlock_unlock(&obj_list_rw_mutex); if (*map_handle == 0) { free(map_node); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } obj->map_handle = *map_handle; return CKR_OK; } // object_mgr_copy() // // algorithm: // 1) find the old object // 2) get the template from the old object // 3) merge in the new object's template // 4) perform class-specific sanity checks // CK_RV object_mgr_copy( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE old_handle, CK_OBJECT_HANDLE * new_handle ) { OBJECT *old_obj = NULL; OBJECT *new_obj = NULL; CK_BBOOL priv_obj; CK_BBOOL sess_obj; CK_BBOOL locked = FALSE; CK_RV rc; unsigned long obj_handle; if (!sess || !pTemplate || !new_handle){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex lock failed.\n"); return rc; } locked = TRUE; rc = object_mgr_find_in_map1( old_handle, &old_obj ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_find_in_map1 failed.\n"); goto done; } rc = object_copy( pTemplate, ulCount, old_obj, &new_obj ); if (rc != CKR_OK){ TRACE_DEVEL("Object Copy failed.\n"); goto done; } // check whether session has permissions to create the object, etc // // Object R/O R/W R/O R/W R/W // Type Public Public User User SO // ------------------------------------------------------------- // Public session R/W R/W R/W R/W R/W // Private session R/W R/W // Public token R/O R/W R/O R/W R/W // Private token R/O R/W // sess_obj = object_is_session_object( new_obj ); priv_obj = object_is_private( new_obj ); if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } if (!sess_obj) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (!sess_obj) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; goto done; } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } } // okay, object is created and the session permissions look okay. // add the object to the appropriate list and assign an object handle // if (sess_obj) { new_obj->session = sess; memset( &new_obj->name, 0x00, sizeof(CK_BYTE) * 8 ); if ((obj_handle = bt_node_add(&sess_obj_btree, new_obj)) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } else { CK_BYTE current[8]; CK_BYTE next[8]; // we'll be modifying nv_token_data so we should protect this part // with 'pkcs_mutex' // rc = XProcLock(); if (rc != CKR_OK){ TRACE_ERROR("Failed to get Process Lock.\n"); goto done; } else { // Determine if we have already reached our Max Token Objects // if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { XProcUnLock(); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { XProcUnLock(); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } memcpy( current, &nv_token_data->next_token_object_name, 8 ); new_obj->session = NULL; memcpy( &new_obj->name, current, 8 ); compute_next_token_obj_name( current, next ); memcpy( &nv_token_data->next_token_object_name, next, 8 ); save_token_object( new_obj ); // add the object identifier to the shared memory segment // object_mgr_add_to_shm( new_obj ); XProcUnLock(); save_token_data(sess->session_info.slotID); } // now, store the object in the token object btree // if (priv_obj) obj_handle = bt_node_add(&priv_token_obj_btree, new_obj); else obj_handle = bt_node_add(&publ_token_obj_btree, new_obj); if (!obj_handle) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } rc = object_mgr_add_to_map( sess, new_obj, obj_handle, new_handle ); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_add_to_map failed.\n"); // this is messy but we need to remove the object from whatever // list we just added it to // if (sess_obj) { // put the binary tree node which holds new_obj on the free list, but pass NULL here, so // that new_obj (the binary tree node's value pointer) isn't touched. It is free'd below bt_node_free(&sess_obj_btree, obj_handle, NULL); } else { // FIXME - need to destroy the token object file too // delete_token_object( new_obj ); if (priv_obj) { // put the binary tree node which holds new_obj on the free list, but pass NULL here, // so that new_obj (the binary tree node's value pointer) isn't touched. It is free'd // below bt_node_free(&priv_token_obj_btree, obj_handle, NULL); } else { // put the binary tree node which holds new_obj on the free list, but pass NULL here, // so that new_obj (the binary tree node's value pointer) isn't touched. It is free'd // below bt_node_free(&publ_token_obj_btree, obj_handle, NULL); } rc = XProcLock(); if (rc != CKR_OK){ TRACE_ERROR("Failed to get Process Lock.\n"); goto done; } object_mgr_del_from_shm( new_obj ); XProcUnLock(); } } done: if (locked) MY_UnlockMutex( &obj_list_mutex ); if ((rc != CKR_OK) && (new_obj != NULL)) object_free( new_obj ); return rc; } // determines whether the session is allowed to create an object. creates // the object but doesn't add the object to any object lists or to the // process' object map. // CK_RV object_mgr_create_skel( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount, CK_ULONG mode, CK_ULONG obj_type, CK_ULONG sub_class, OBJECT ** obj ) { OBJECT *o = NULL; CK_RV rc; CK_BBOOL priv_obj; CK_BBOOL sess_obj; if (!sess || !obj){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (!pTemplate && (ulCount != 0)){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } // // we don't need to lock mutex for this routine // rc = object_create_skel( pTemplate, ulCount, mode, obj_type, sub_class, &o ); if (rc != CKR_OK){ TRACE_DEVEL("object_create_skel failed.\n"); return rc; } sess_obj = object_is_session_object( o ); priv_obj = object_is_private( o ); if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj) { object_free( o ); TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); return CKR_USER_NOT_LOGGED_IN; } if (!sess_obj) { object_free( o ); TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); return CKR_SESSION_READ_ONLY; } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (!sess_obj) { object_free( o ); TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); return CKR_SESSION_READ_ONLY; } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj) { object_free( o ); TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); return CKR_USER_NOT_LOGGED_IN; } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj) { object_free( o ); TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); return CKR_USER_NOT_LOGGED_IN; } } *obj = o; return CKR_OK; } CK_RV object_mgr_create_final( SESSION * sess, OBJECT * obj, CK_OBJECT_HANDLE * handle ) { CK_BBOOL sess_obj; CK_BBOOL priv_obj; CK_BBOOL locked = FALSE; CK_RV rc; unsigned long obj_handle; if (!sess || !obj || !handle){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex lock failed.\n"); return rc; } locked = TRUE; sess_obj = object_is_session_object( obj ); priv_obj = object_is_private( obj ); if (sess_obj) { obj->session = sess; memset( obj->name, 0x0, sizeof(CK_BYTE) * 8 ); if ((obj_handle = bt_node_add(&sess_obj_btree, obj)) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } else { CK_BYTE current[8]; CK_BYTE next[8]; // we'll be modifying nv_token_data so we should protect this part // with 'pkcs_mutex' // rc = XProcLock(); if (rc != CKR_OK){ TRACE_ERROR("Failed to get Process Lock.\n"); goto done; } else { // Determine if we have already reached our Max Token Objects // if (priv_obj) { if (global_shm->num_priv_tok_obj >= MAX_TOK_OBJS) { XProcUnLock(); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } else { if (global_shm->num_publ_tok_obj >= MAX_TOK_OBJS) { XProcUnLock(); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } memcpy( current, &nv_token_data->next_token_object_name, 8 ); obj->session = NULL; memcpy( &obj->name, current, 8 ); compute_next_token_obj_name( current, next ); memcpy( &nv_token_data->next_token_object_name, next, 8 ); save_token_object( obj ); // add the object identifier to the shared memory segment // object_mgr_add_to_shm( obj ); XProcUnLock(); save_token_data(sess->session_info.slotID); } // now, store the object in the token object btree // if (priv_obj) obj_handle = bt_node_add(&priv_token_obj_btree, obj); else obj_handle = bt_node_add(&publ_token_obj_btree, obj); if (!obj_handle) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } } rc = object_mgr_add_to_map( sess, obj, obj_handle, handle ); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_add_to_map failed.\n"); // this is messy but we need to remove the object from whatever // list we just added it to // if (sess_obj) { // put the binary tree node which holds obj on the free list, but pass NULL here, so // that obj (the binary tree node's value pointer) isn't touched. It is free'd below bt_node_free(&sess_obj_btree, obj_handle, NULL); } else { // FIXME - need to destroy the token object file too // delete_token_object( obj ); if (priv_obj) { // put the binary tree node which holds obj on the free list, but pass NULL here, // so that obj (the binary tree node's value pointer) isn't touched. It is free'd // below bt_node_free(&priv_token_obj_btree, obj_handle, NULL); } else { // put the binary tree node which holds obj on the free list, but pass NULL here, // so that obj (the binary tree node's value pointer) isn't touched. It is free'd // below bt_node_free(&publ_token_obj_btree, obj_handle, NULL); } rc = XProcLock(); if (rc != CKR_OK){ TRACE_ERROR("Failed to get Process Lock.\n"); goto done; } object_mgr_del_from_shm( obj ); XProcUnLock(); } } done: if (locked) MY_UnlockMutex( &obj_list_mutex ); return rc; } /* destroy_object_cb * * Callback used to delete an object from the object map btree and whichever other btree its * in (based on its type) */ void destroy_object_cb(void *node) { OBJECT_MAP *map = (OBJECT_MAP *)node; OBJECT *o; if (map->is_session_obj) bt_node_free(&sess_obj_btree, map->obj_handle, object_free); else { if (map->is_private) o = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); else o = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); if (!o) return; delete_token_object(o); /* Use the same calling convention as the old code, if XProcLock fails, don't * delete from shm and don't free the object in its other btree */ if (XProcLock()) { TRACE_ERROR("Failed to get Process Lock.\n"); goto done; } DUMP_SHM("before"); object_mgr_del_from_shm(o); DUMP_SHM("after"); XProcUnLock(); if (map->is_private) bt_node_free(&priv_token_obj_btree, map->obj_handle, object_free); else bt_node_free(&publ_token_obj_btree, map->obj_handle, object_free); } done: free(map); } // XXX Why does this function take @sess as an argument? // CK_RV object_mgr_destroy_object( SESSION * sess, CK_OBJECT_HANDLE handle ) { CK_BBOOL locked = FALSE; CK_RV rc; if (!sess){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); goto done; } locked = TRUE; if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Lock failed.\n"); rc = CKR_FUNCTION_FAILED; goto done; } if (!bt_node_free(&object_map_btree, handle, destroy_object_cb)) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); rc = CKR_OBJECT_HANDLE_INVALID; } pthread_rwlock_unlock(&obj_list_rw_mutex); done: if (locked) MY_UnlockMutex( &obj_list_mutex ); return rc; } /* delete_token_obj_cb * * Callback to delete an object if its a token object */ void delete_token_obj_cb(void *node, unsigned long map_handle, void *p3) { OBJECT_MAP *map = (OBJECT_MAP *)node; OBJECT *o; if (!(map->is_session_obj)) { if (map->is_private) o = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); else o = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); if (!o) goto done; delete_token_object(o); /* Use the same calling convention as the old code, if * XProcLock fails, don't delete from shm and don't free * the object in its other btree */ if (XProcLock()) { TRACE_ERROR("Failed to get Process Lock.\n"); goto done; } object_mgr_del_from_shm(o); XProcUnLock(); if (map->is_private) bt_node_free(&priv_token_obj_btree, map->obj_handle, object_free); else bt_node_free(&publ_token_obj_btree, map->obj_handle, object_free); } done: /* delete @node from this btree */ bt_node_free(&object_map_btree, map_handle, free); } // this routine will destroy all token objects in the system // CK_RV object_mgr_destroy_token_objects( void ) { CK_BBOOL locked1 = FALSE, locked2 = FALSE; CK_RV rc; rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); goto done; } else locked1 = TRUE; bt_for_each_node(&object_map_btree, delete_token_obj_cb, NULL); // now we want to purge the token object list in shared memory // rc = XProcLock(); if (rc == CKR_OK) { locked2 = TRUE; global_shm->num_priv_tok_obj = 0; global_shm->num_publ_tok_obj = 0; memset( &global_shm->publ_tok_objs, 0x0, MAX_TOK_OBJS * sizeof(TOK_OBJ_ENTRY) ); memset( &global_shm->priv_tok_objs, 0x0, MAX_TOK_OBJS * sizeof(TOK_OBJ_ENTRY) ); } else TRACE_ERROR("Failed to get Process Lock.\n"); done: if (locked1 == TRUE) MY_UnlockMutex( &obj_list_mutex ); /* if (locked2 == TRUE) XProcUnLock(); */ if (locked2 == TRUE) { XProcUnLock(); } return rc; } // object_mgr_find_in_map_nocache() // // Locates the specified object in the map // without going and checking for cache update // CK_RV object_mgr_find_in_map_nocache( CK_OBJECT_HANDLE handle, OBJECT ** ptr ) { OBJECT_MAP * map = NULL; OBJECT * obj = NULL; CK_RV rc = CKR_OK; if (!ptr){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (!handle) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); return CKR_OBJECT_HANDLE_INVALID; } // // no mutex here. the calling function should have locked the mutex // if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Lock failed.\n"); return CKR_FUNCTION_FAILED; } map = bt_get_node_value(&object_map_btree, handle); if (!map) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); rc = CKR_OBJECT_HANDLE_INVALID; goto done; } if (map->is_session_obj) obj = bt_get_node_value(&sess_obj_btree, map->obj_handle); else if (map->is_private) obj = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); else obj = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); if (!obj) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); rc = CKR_OBJECT_HANDLE_INVALID; goto done; } *ptr = obj; done: pthread_rwlock_unlock(&obj_list_rw_mutex); return rc; } // object_mgr_find_in_map1() // // Locates the specified object in the map // CK_RV object_mgr_find_in_map1( CK_OBJECT_HANDLE handle, OBJECT ** ptr ) { OBJECT_MAP * map = NULL; OBJECT * obj = NULL; CK_RV rc = CKR_OK; if (!ptr){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Lock failed.\n"); return CKR_FUNCTION_FAILED; } map = bt_get_node_value(&object_map_btree, handle); if (!map) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); rc = CKR_OBJECT_HANDLE_INVALID; goto done; } if (map->is_session_obj) obj = bt_get_node_value(&sess_obj_btree, map->obj_handle); else if (map->is_private) obj = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); else obj = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); if (!obj) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); rc = CKR_OBJECT_HANDLE_INVALID; goto done; } /* SAB XXX Fix me.. need to make it more efficient than just looking * for the object to be changed. set a global flag that contains the * ref count to all objects.. if the shm ref count changes, then we * update the object. if not */ /* Note: Each C_Initialize call loads up the public token objects * and build corresponding tree(s). The same for private token objects * upon successful C_Login. Since token objects can be shared, it is * possible another process or session has deleted a token object. * Accounting is done in shm, so check shm to see if object still exists. */ if (!object_is_session_object(obj)) { XProcLock(); rc = object_mgr_check_shm( obj ); XProcUnLock(); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_check_shm failed.\n"); goto done; } } *ptr = obj; done: pthread_rwlock_unlock(&obj_list_rw_mutex); return rc; } void find_obj_cb(void *node, unsigned long map_handle, void *p3) { OBJECT_MAP *map = (OBJECT_MAP *)node; OBJECT *obj; struct find_args *fa = (struct find_args *)p3; if (fa->done) return; if (map->is_session_obj) obj = bt_get_node_value(&sess_obj_btree, map->obj_handle); else if (map->is_private) obj = bt_get_node_value(&priv_token_obj_btree, map->obj_handle); else obj = bt_get_node_value(&publ_token_obj_btree, map->obj_handle); if (!obj) return; /* if this object is the one we're looking for (matches p3->obj), return * its map_handle in p3->map_handle */ if (obj == fa->obj) { fa->map_handle = map_handle; fa->done = TRUE; } } // object_mgr_find_in_map2() // CK_RV object_mgr_find_in_map2( OBJECT * obj, CK_OBJECT_HANDLE * handle ) { struct find_args fa; if (!obj || !handle){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } // // no mutex here. the calling function should have locked the mutex // if (pthread_rwlock_rdlock(&obj_list_rw_mutex)) { TRACE_ERROR("Mutex Lock failed.\n"); return CKR_FUNCTION_FAILED; } fa.done = FALSE; fa.obj = obj; fa.map_handle = 0; // pass the fa structure with the values to operate on in the find_obj_cb function bt_for_each_node(&object_map_btree, find_obj_cb, &fa); pthread_rwlock_unlock(&obj_list_rw_mutex); if (fa.done == FALSE || fa.map_handle == 0) { return CKR_OBJECT_HANDLE_INVALID; } *handle = fa.map_handle; XProcLock(); object_mgr_check_shm( obj ); XProcUnLock(); return CKR_OK; } void find_build_list_cb(void *node, unsigned long obj_handle, void *p3) { OBJECT *obj = (OBJECT *)node; struct find_build_list_args *fa = (struct find_build_list_args *)p3; CK_OBJECT_HANDLE map_handle; CK_ATTRIBUTE *attr; CK_BBOOL match = FALSE; CK_RV rc; if ((object_is_private(obj) == FALSE) || (fa->public_only == FALSE)) { // if the user doesn't specify any template attributes then we return // all objects // if (fa->pTemplate == NULL || fa->ulCount == 0) match = TRUE; else match = template_compare( fa->pTemplate, fa->ulCount, obj->template ); } // if we have a match, find the object in the map (add it if necessary) // then add the object to the list of found objects // if (match) { rc = object_mgr_find_in_map2( obj, &map_handle ); if (rc != CKR_OK) { rc = object_mgr_add_to_map( fa->sess, obj, obj_handle, &map_handle ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_add_to_map failed.\n"); return; } } // If hw_feature is false here, we need to filter out all objects // that have the CKO_HW_FEATURE attribute set. - KEY if ((fa->hw_feature == FALSE) && (template_attribute_find(obj->template, CKA_CLASS, &attr) == TRUE)) { if (attr->pValue == NULL) { TRACE_DEVEL("%s\n", ock_err(ERR_GENERAL_ERROR)); return; } if (*(CK_OBJECT_CLASS *)attr->pValue == CKO_HW_FEATURE) return; } /* Don't find objects that have been created with the CKA_HIDDEN * attribute set */ if ((fa->hidden_object == FALSE) && (template_attribute_find(obj->template, CKA_HIDDEN, &attr) == TRUE)) { if (*(CK_BBOOL *)attr->pValue == TRUE) return; } fa->sess->find_list[ fa->sess->find_count ] = map_handle; fa->sess->find_count++; if (fa->sess->find_count >= fa->sess->find_len) { fa->sess->find_len += 15; fa->sess->find_list = (CK_OBJECT_HANDLE *)realloc(fa->sess->find_list, fa->sess->find_len * sizeof(CK_OBJECT_HANDLE)); if (!fa->sess->find_list) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return; } } } } CK_RV object_mgr_find_init( SESSION * sess, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ) { struct find_build_list_args fa; CK_ULONG i; // it is possible the pTemplate == NULL // if (!sess){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } if (sess->find_active != FALSE){ return CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); } // initialize the found object list. if it doesn't exist, allocate // a list big enough for 10 handles. we'll reallocate if we need more // if (sess->find_list != NULL) { memset( sess->find_list, 0x0, sess->find_len * sizeof(CK_OBJECT_HANDLE) ); } else { sess->find_list = (CK_OBJECT_HANDLE *)malloc(10 * sizeof(CK_OBJECT_HANDLE)); if (!sess->find_list){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } else { memset( sess->find_list, 0x0, 10 * sizeof(CK_OBJECT_HANDLE) ); sess->find_len = 10; } } sess->find_count = 0; sess->find_idx = 0; // --- need to grab the object lock here MY_LockMutex(&obj_list_mutex); XProcLock(); object_mgr_update_from_shm(); XProcUnLock(); fa.hw_feature = FALSE; fa.hidden_object = FALSE; fa.sess = sess; fa.pTemplate = pTemplate; fa.ulCount = ulCount; // which objects can be returned: // // Public Session: public session objects, public token objects // User Session: all session objects, all token objects // SO session: public session objects, public token objects // // PKCS#11 v2.11 (pg. 79): "When searching using C_FindObjectsInit // and C_FindObjects, hardware feature objects are not returned // unless the CKA_CLASS attribute in the template has the value // CKO_HW_FEATURE." So, we check for CKO_HW_FEATURE and if its set, // we'll find these objects below. - KEY for (i = 0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { if (*(CK_ULONG *)pTemplate[i].pValue == CKO_HW_FEATURE) { fa.hw_feature = TRUE; break; } } /* only find CKA_HIDDEN objects if its specified in the template. */ if (pTemplate[i].type == CKA_HIDDEN) { if (*(CK_BBOOL *)pTemplate[i].pValue == TRUE) { fa.hidden_object = TRUE; break; } } } switch (sess->session_info.state) { case CKS_RO_PUBLIC_SESSION: case CKS_RW_PUBLIC_SESSION: case CKS_RW_SO_FUNCTIONS: fa.public_only = TRUE; bt_for_each_node(&publ_token_obj_btree, find_build_list_cb, &fa); bt_for_each_node(&sess_obj_btree, find_build_list_cb, &fa); break; case CKS_RO_USER_FUNCTIONS: case CKS_RW_USER_FUNCTIONS: fa.public_only = FALSE; bt_for_each_node(&priv_token_obj_btree, find_build_list_cb, &fa); bt_for_each_node(&publ_token_obj_btree, find_build_list_cb, &fa); bt_for_each_node(&sess_obj_btree, find_build_list_cb, &fa); break; } MY_UnlockMutex(&obj_list_mutex); sess->find_active = TRUE; return CKR_OK; } // // CK_RV object_mgr_find_final( SESSION *sess ) { if (!sess){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } if (sess->find_active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } free( sess->find_list ); sess->find_list = NULL; sess->find_count = 0; sess->find_idx = 0; sess->find_active = FALSE; return CKR_OK; } // // CK_RV object_mgr_get_attribute_values( SESSION * sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ) { OBJECT * obj; CK_BBOOL priv_obj; CK_BBOOL locked = FALSE; CK_RV rc; if (!pTemplate){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return rc; } locked = TRUE; rc = object_mgr_find_in_map1( handle, &obj ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_find_in_map1 failed.\n"); goto done; } priv_obj = object_is_private( obj ); if (priv_obj == TRUE) { if (sess->session_info.state == CKS_RO_PUBLIC_SESSION || sess->session_info.state == CKS_RW_PUBLIC_SESSION) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } } rc = object_get_attribute_values( obj, pTemplate, ulCount ); if (rc != CKR_OK) TRACE_DEVEL("object_get_attribute_values failed.\n"); done: if (locked) MY_UnlockMutex( &obj_list_mutex ); return rc; } // // CK_RV object_mgr_get_object_size( CK_OBJECT_HANDLE handle, CK_ULONG * size ) { OBJECT * obj; CK_RV rc; rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return rc; } rc = object_mgr_find_in_map1( handle, &obj ); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed.\n"); goto done; } *size = object_get_size( obj ); done: MY_UnlockMutex( &obj_list_mutex ); return rc; } void purge_session_obj_cb(void *node, unsigned long obj_handle, void *p3) { OBJECT *obj = (OBJECT *)node; struct purge_args *pa = (struct purge_args *)p3; CK_BBOOL del = FALSE; if (obj->session == pa->sess) { if (pa->type == PRIVATE) { if (object_is_private(obj)) del = TRUE; } else if (pa->type == PUBLIC) { if (object_is_public(obj)) del = TRUE; } else if (pa->type == ALL) { del = TRUE; } if (del == TRUE) { if (obj->map_handle) bt_node_free(&object_map_btree, obj->map_handle, free); bt_node_free(&sess_obj_btree, obj_handle, object_free); } } } // object_mgr_purge_session_objects() // // Args: SESSION * // SESS_OBJ_TYPE: can be ALL, PRIVATE or PUBLIC // // Remove all session objects owned by the specified session satisfying // the 'type' requirements // CK_BBOOL object_mgr_purge_session_objects( SESSION * sess, SESS_OBJ_TYPE type ) { struct purge_args pa = { sess, type }; CK_RV rc; if (!sess) return FALSE; rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return FALSE; } bt_for_each_node(&sess_obj_btree, purge_session_obj_cb, &pa); MY_UnlockMutex( &obj_list_mutex ); return TRUE; } /* purge_token_obj_cb * * @p3 is the btree we're purging from */ void purge_token_obj_cb(void *node, unsigned long obj_handle, void *p3) { OBJECT *obj = (OBJECT *)node; struct btree *t = (struct btree *)p3; if (obj->map_handle) bt_node_free(&object_map_btree, obj->map_handle, free); bt_node_free(t, obj_handle, object_free); } // this routine cleans up the list of token objects. in general, we don't // need to do this but when tracing memory leaks, it's best that we free everything // that we've allocated // CK_BBOOL object_mgr_purge_token_objects( ) { CK_RV rc; rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return FALSE; } bt_for_each_node(&priv_token_obj_btree, purge_token_obj_cb, &priv_token_obj_btree); bt_for_each_node(&publ_token_obj_btree, purge_token_obj_cb, &publ_token_obj_btree); MY_UnlockMutex( &obj_list_mutex ); return TRUE; } CK_BBOOL object_mgr_purge_private_token_objects( void ) { CK_RV rc; rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex Lock failed.\n"); return FALSE; } bt_for_each_node(&priv_token_obj_btree, purge_token_obj_cb, &priv_token_obj_btree); MY_UnlockMutex( &obj_list_mutex ); return TRUE; } // // CK_RV object_mgr_restore_obj( CK_BYTE *data, OBJECT *oldObj ) { return object_mgr_restore_obj_withSize(data, oldObj, -1); } // //Modified verrsion of object_mgr_restore_obj to bounds check //If data_size==-1, won't check bounds CK_RV object_mgr_restore_obj_withSize( CK_BYTE *data, OBJECT *oldObj, int data_size ) { OBJECT * obj = NULL; CK_BBOOL priv; CK_RV rc; if (!data){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } // The calling stack MUST have the mutex // to many grab it now. if (oldObj != NULL) { obj = oldObj; rc = object_restore_withSize( data, &obj, TRUE, data_size ); } else { rc = object_restore_withSize( data, &obj, FALSE, data_size ); if (rc == CKR_OK) { priv = object_is_private( obj ); if (priv) { if (!bt_node_add(&priv_token_obj_btree, obj)) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } } else { if (!bt_node_add(&publ_token_obj_btree, obj)) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } } XProcLock(); if (priv) { if (global_shm->priv_loaded == FALSE){ if (global_shm->num_priv_tok_obj < MAX_TOK_OBJS) object_mgr_add_to_shm( obj ); else{ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; } } } else { if (global_shm->publ_loaded == FALSE){ if (global_shm->num_publ_tok_obj < MAX_TOK_OBJS) object_mgr_add_to_shm( obj ); else{ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; } } } XProcUnLock(); } else { TRACE_DEVEL("object_restore_withSize failed.\n"); } } return rc; } // // CK_RV object_mgr_set_attribute_values( SESSION * sess, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE * pTemplate, CK_ULONG ulCount ) { OBJECT * obj; CK_BBOOL sess_obj, priv_obj; CK_BBOOL modifiable; CK_RV rc; if (!pTemplate){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } rc = MY_LockMutex( &obj_list_mutex ); if (rc != CKR_OK){ TRACE_ERROR("Mutex lock failed.\n"); return rc; } rc = object_mgr_find_in_map1( handle, &obj ); MY_UnlockMutex( &obj_list_mutex ); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed.\n"); return rc; } // determine whether the session is allowed to modify the object // modifiable = object_is_modifiable( obj ); sess_obj = object_is_session_object( obj ); priv_obj = object_is_private( obj ); // if object is not modifiable, it doesn't matter what kind of session // is issuing the request... // if (!modifiable){ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY)); return CKR_ATTRIBUTE_READ_ONLY; } if (sess->session_info.state == CKS_RO_PUBLIC_SESSION) { if (priv_obj){ TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); return CKR_USER_NOT_LOGGED_IN; } if (!sess_obj){ TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); return CKR_SESSION_READ_ONLY; } } if (sess->session_info.state == CKS_RO_USER_FUNCTIONS) { if (!sess_obj){ TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); return CKR_SESSION_READ_ONLY; } } if (sess->session_info.state == CKS_RW_PUBLIC_SESSION) { if (priv_obj){ TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); return CKR_USER_NOT_LOGGED_IN; } } if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (priv_obj){ TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); return CKR_USER_NOT_LOGGED_IN; } } rc = object_set_attribute_values( obj, pTemplate, ulCount ); if (rc != CKR_OK){ TRACE_DEVEL("object_set_attribute_values failed.\n"); return rc; } // okay. the object has been updated. if it's a session object, // we're finished. if it's a token object, we need to update // non-volatile storage. // if (!sess_obj) { TOK_OBJ_ENTRY *entry = NULL; CK_ULONG index; // I still think there's a race condition here if two processes are // updating the same token object at the same time. I don't know how // to solve this short of assigning each token object it's own mutex... // obj->count_lo++; if (obj->count_lo == 0) obj->count_hi++; save_token_object( obj ); rc = XProcLock(); if (rc != CKR_OK){ TRACE_ERROR("Failed to get Process Lock.\n"); return rc; } if (priv_obj) { rc = object_mgr_search_shm_for_obj( global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj-1, obj, &index ); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_search_shm_for_obj failed.\n"); XProcUnLock(); return rc; } entry = &global_shm->priv_tok_objs[index]; } else { rc = object_mgr_search_shm_for_obj( global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj-1, obj, &index ); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_search_shm_for_obj failed.\n"); XProcUnLock(); return rc; } entry = &global_shm->publ_tok_objs[index]; } entry->count_lo = obj->count_lo; entry->count_hi = obj->count_hi; XProcUnLock(); } return rc; } // // void object_mgr_add_to_shm( OBJECT *obj ) { // TODO: Can't this function fail? TOK_OBJ_ENTRY * entry = NULL; CK_BBOOL priv; // the calling routine is responsible for locking the global_shm mutex // priv = object_is_private( obj ); if (priv) entry = &global_shm->priv_tok_objs[global_shm->num_priv_tok_obj]; else entry = &global_shm->publ_tok_objs[global_shm->num_publ_tok_obj]; entry->deleted = FALSE; entry->count_lo = 0; entry->count_hi = 0; memcpy( entry->name, obj->name, 8 ); if (priv) { global_shm->num_priv_tok_obj++; object_mgr_sort_priv_shm(); } else { global_shm->num_publ_tok_obj++; object_mgr_sort_publ_shm(); } return; } // // CK_RV object_mgr_del_from_shm( OBJECT *obj ) { CK_ULONG index, count; CK_BBOOL priv; CK_RV rc; // the calling routine is responsible for locking the global_shm mutex // priv = object_is_private( obj ); if (priv) { rc = object_mgr_search_shm_for_obj( global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj-1, obj, &index ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_search_shm_for_obj failed.\n"); return rc; } // Since the number of objects starts at 1 and index starts at zero, we // decrement before we get count. This eliminates the need to perform // this operation later as well as decrementing the number of objects. // (i.e. If we have 10 objects, num will be 10 but the last index is 9. // If we want to delete the last object we need to subtract 9 from 9 not // 10 from 9.) // global_shm->num_priv_tok_obj--; if (index > global_shm->num_priv_tok_obj) { count = index - global_shm->num_priv_tok_obj; } else { count = global_shm->num_priv_tok_obj - index; } if (count > 0) { // If we are not deleting the last element in the list // Move up count number of elements effectively deleting the index // NB: memmove is required since the copied regions may overlap memmove((char *)&global_shm->priv_tok_objs[index], (char *)&global_shm->priv_tok_objs[index+1], sizeof(TOK_OBJ_ENTRY) * count ); // We need to zero out the last entry... Since the memcopy // does not zero it out... memset((char *)&global_shm->priv_tok_objs[global_shm->num_priv_tok_obj+1], 0, sizeof(TOK_OBJ_ENTRY)); } else { // We are deleting the last element which is in num_priv_tok_obj memset((char *)&global_shm->priv_tok_objs[global_shm->num_priv_tok_obj], 0, sizeof(TOK_OBJ_ENTRY)); } } else { rc = object_mgr_search_shm_for_obj( global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj-1, obj, &index ); if (rc != CKR_OK){ TRACE_DEVEL("object_mgr_search_shm_for_obj failed.\n"); return rc; } global_shm->num_publ_tok_obj--; if (index > global_shm->num_publ_tok_obj) { count = index - global_shm->num_publ_tok_obj; } else { count = global_shm->num_publ_tok_obj - index; } if (count > 0) { // NB: memmove is required since the copied regions may overlap memmove((char *)&global_shm->publ_tok_objs[index], (char *)&global_shm->publ_tok_objs[index+1], sizeof(TOK_OBJ_ENTRY) * count); // We need to zero out the last entry... Since the memcopy // does not zero it out... memset((char *)&global_shm->publ_tok_objs[global_shm->num_publ_tok_obj+1], 0, sizeof(TOK_OBJ_ENTRY)); } else { memset((char *)&global_shm->publ_tok_objs[global_shm->num_publ_tok_obj], 0, sizeof(TOK_OBJ_ENTRY)); } } // // object list is still sorted...so no need to re-sort // return CKR_OK; } // // CK_RV object_mgr_check_shm( OBJECT *obj ) { TOK_OBJ_ENTRY * entry = NULL; CK_BBOOL priv; CK_ULONG index; CK_RV rc; // the calling routine is responsible for locking the global_shm mutex // /* first check the object count. If it is 0, then just return. */ priv = object_is_private( obj ); if (priv) { if (global_shm->num_priv_tok_obj == 0) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); return CKR_OBJECT_HANDLE_INVALID; } rc = object_mgr_search_shm_for_obj( global_shm->priv_tok_objs, 0, global_shm->num_priv_tok_obj-1, obj, &index ); if (rc != CKR_OK){ TRACE_ERROR("object_mgr_search_shm_for_obj failed.\n"); return rc; } entry = &global_shm->priv_tok_objs[index]; } else { if (global_shm->num_publ_tok_obj == 0) { TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); return CKR_OBJECT_HANDLE_INVALID; } rc = object_mgr_search_shm_for_obj( global_shm->publ_tok_objs, 0, global_shm->num_publ_tok_obj-1, obj, &index ); if (rc != CKR_OK){ TRACE_ERROR("object_mgr_search_shm_for_obj failed.\n"); return rc; } entry = &global_shm->publ_tok_objs[index]; } if ((obj->count_hi == entry->count_hi) && (obj->count_lo == entry->count_lo)) return CKR_OK; rc = reload_token_object( obj ); return rc; } // I'd use the standard bsearch() routine but I want an index, not a pointer. // Converting the pointer to an index might cause problems when switching // to a 64-bit environment... // CK_RV object_mgr_search_shm_for_obj( TOK_OBJ_ENTRY * obj_list, CK_ULONG lo, CK_ULONG hi, OBJECT * obj, CK_ULONG * index ) { // SAB XXX reduce the search time since this is what seems to be burning cycles CK_ULONG idx; if ( obj->index == 0 ) { for (idx=0;idx<=hi;idx++){ if (memcmp(obj->name, obj_list[idx].name,8) == 0) { *index = idx; obj->index = idx; return CKR_OK ; } } } else { // SAB better double check if ( memcmp(obj->name, obj_list[obj->index].name,8) == 0 ){ *index = obj->index; return CKR_OK ; } else { // something is hosed.. go back to the brute force method for (idx=0;idx<=hi;idx++){ if (memcmp(obj->name, obj_list[idx].name,8) == 0) { *index = idx; obj->index = idx; return CKR_OK ; } } } } TRACE_ERROR("%s\n", ock_err(ERR_OBJECT_HANDLE_INVALID)); return CKR_OBJECT_HANDLE_INVALID; } // // CK_RV object_mgr_sort_priv_shm( void ) { // for now, we assume the list is sorted by design. this is not unreasonable // since new object handles are assigned in increasing order. problems // will arise after 36^8 token objects have been created... // return CKR_OK; } // // CK_RV object_mgr_sort_publ_shm( void ) { // for now, we assume the list is sorted by design. this is not unreasonable // since new object handles are assigned in increasing order. problems // will arise after 36^8 token objects have been created... // return CKR_OK; } // this routine scans the local token object lists and updates any objects that // have changed. it also adds any new token objects that have been added by // other processes and deletes any objects that have been deleted by other // processes // CK_RV object_mgr_update_from_shm( void ) { object_mgr_update_publ_tok_obj_from_shm(); object_mgr_update_priv_tok_obj_from_shm(); return CKR_OK; } void delete_objs_from_btree_cb(void *node, unsigned long obj_handle, void *p3) { struct update_tok_obj_args * ua = (struct update_tok_obj_args *)p3; TOK_OBJ_ENTRY * shm_te = NULL; OBJECT * obj = (OBJECT *)node; CK_ULONG index; /* for each TOK_OBJ_ENTRY in the SHM list */ for (index = 0; index < *(ua->num_entries); index++) { shm_te = &(ua->entries[index]); /* found it, return */ if (!memcmp(obj->name, shm_te->name, 8)) { return; } } /* didn't find it in SHM, delete it from its btree */ bt_node_free(ua->t, obj_handle, object_free); } void find_by_name_cb(void *node, unsigned long obj_handle, void *p3) { OBJECT *obj = (OBJECT *)node; struct find_by_name_args *fa = (struct find_by_name_args *)p3; if (fa->done) return; if (!memcmp(obj->name, fa->name, 8)) { fa->done = TRUE; } } CK_RV object_mgr_update_publ_tok_obj_from_shm() { struct update_tok_obj_args ua; struct find_by_name_args fa; TOK_OBJ_ENTRY * shm_te = NULL; CK_ULONG index; OBJECT * new_obj; ua.entries = global_shm->publ_tok_objs; ua.num_entries = &(global_shm->num_publ_tok_obj); ua.t = &publ_token_obj_btree; /* delete any objects not in SHM from the btree */ bt_for_each_node(&publ_token_obj_btree, delete_objs_from_btree_cb, &ua); /* for each item in SHM, add it to the btree if its not there */ for (index = 0; index < global_shm->num_publ_tok_obj; index++) { shm_te = &global_shm->publ_tok_objs[index]; fa.done = FALSE; fa.name = shm_te->name; /* find an object from SHM in the btree */ bt_for_each_node(&publ_token_obj_btree, find_by_name_cb, &fa); /* we didn't find it in the btree, so add it */ if (fa.done == FALSE) { new_obj = (OBJECT *)malloc(sizeof(OBJECT)); memset( new_obj, 0x0, sizeof(OBJECT) ); memcpy( new_obj->name, shm_te->name, 8 ); reload_token_object( new_obj ); bt_node_add(&publ_token_obj_btree, new_obj); } } return CKR_OK; } CK_RV object_mgr_update_priv_tok_obj_from_shm() { struct update_tok_obj_args ua; struct find_by_name_args fa; TOK_OBJ_ENTRY * shm_te = NULL; CK_ULONG index; OBJECT * new_obj; // SAB XXX don't bother doing this call if we are not in the correct // login state if ( !(global_login_state == CKS_RW_USER_FUNCTIONS || global_login_state == CKS_RO_USER_FUNCTIONS) ) { return CKR_OK; } ua.entries = global_shm->priv_tok_objs; ua.num_entries = &(global_shm->num_priv_tok_obj); ua.t = &priv_token_obj_btree; /* delete any objects not in SHM from the btree */ bt_for_each_node(&priv_token_obj_btree, delete_objs_from_btree_cb, &ua); /* for each item in SHM, add it to the btree if its not there */ for (index = 0; index < global_shm->num_priv_tok_obj; index++) { shm_te = &global_shm->priv_tok_objs[index]; fa.done = FALSE; fa.name = shm_te->name; /* find an object from SHM in the btree */ bt_for_each_node(&priv_token_obj_btree, find_by_name_cb, &fa); /* we didn't find it in the btree, so add it */ if (fa.done == FALSE) { new_obj = (OBJECT *)malloc(sizeof(OBJECT)); memset( new_obj, 0x0, sizeof(OBJECT) ); memcpy( new_obj->name, shm_te->name, 8 ); reload_token_object( new_obj ); bt_node_add(&priv_token_obj_btree, new_obj); } } return CKR_OK; } // SAB FIXME FIXME void purge_map_by_type_cb(void *node, unsigned long map_handle, void *p3) { OBJECT_MAP *map = (OBJECT_MAP *)node; SESS_OBJ_TYPE type = *(SESS_OBJ_TYPE *)p3; if (type == PRIVATE) { if (map->is_private) { bt_node_free(&object_map_btree, map_handle, free); } } else if (type == PUBLIC) { if (!map->is_private) { bt_node_free(&object_map_btree, map_handle, free); } } } CK_BBOOL object_mgr_purge_map( SESSION * sess, SESS_OBJ_TYPE type ) { if (pthread_rwlock_wrlock(&obj_list_rw_mutex)) { TRACE_ERROR("mutex lock failed.\n"); return CKR_FUNCTION_FAILED; } bt_for_each_node(&object_map_btree, purge_map_by_type_cb, &type); pthread_rwlock_unlock(&obj_list_rw_mutex); return TRUE; } #ifdef DEBUG void dump_shm(const char *s) { CK_ULONG i; TRACE_DEBUG("%s: dump_shm priv:", s); for (i = 0; i < global_shm->num_priv_tok_obj; i++) { TRACE_DEBUG("[%lu]: %.8s", i, global_shm->priv_tok_objs[i].name); } TRACE_DEBUG("%s: dump_shm publ:", s); for (i = 0; i < global_shm->num_publ_tok_obj; i++) { TRACE_DEBUG("[%lu]: %.8s", i, global_shm->publ_tok_objs[i].name); } } #endif opencryptoki+dfsg/usr/lib/pkcs11/common/loadsave.c0000755000175000017500000014433712630407154021231 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // loadsave.c // // routines associated with loading/saving files // // #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "pkcs32.h" #include "sw_crypt.h" #include "trace.h" /* #include "../api/apiproto.h" */ char *pk_dir; CK_BYTE *get_pk_dir(char *fname) { struct passwd *pw = NULL; if (token_specific.data_store.per_user && (pw = getpwuid(getuid())) != NULL) sprintf(fname,"%s/%s", pk_dir, pw->pw_name); else sprintf(fname, "%s", pk_dir); return fname; } static CK_RV get_encryption_info_for_clear_key(CK_ULONG *p_key_len, CK_ULONG *p_block_size) { CK_ULONG key_len = 0L; CK_ULONG block_size = 0L; switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: key_len = 3 * DES_KEY_SIZE; block_size = DES_BLOCK_SIZE; break; case CKM_AES_CBC: key_len = AES_KEY_SIZE_256; block_size = AES_BLOCK_SIZE; break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return ERR_MECHANISM_INVALID; } if (p_key_len) *p_key_len = key_len; if (p_block_size) *p_block_size = block_size; return CKR_OK; } static CK_RV get_encryption_info(CK_ULONG *p_key_len, CK_ULONG *p_block_size) { CK_RV rc; rc = get_encryption_info_for_clear_key(p_key_len, p_block_size); if (rc != CKR_OK) return rc; /* Tokens that use a secure key have a different size for key because * it's just an indentifier not a real key. token_keysize > 0 indicates * that a token uses a specific key format. */ if (token_specific.token_keysize) { if (p_key_len) *p_key_len = token_specific.token_keysize; } return CKR_OK; } static CK_BYTE *duplicate_initial_vector(const CK_BYTE *iv) { CK_ULONG block_size = 0L; CK_BYTE *initial_vector = NULL; if (iv == NULL) goto done; if (get_encryption_info(NULL, &block_size) != CKR_OK) goto done; initial_vector = malloc(block_size); if (initial_vector == NULL) { goto done; } memcpy(initial_vector, iv, block_size); done: return initial_vector; } static CK_RV encrypt_data(CK_BYTE *key, CK_ULONG keylen, const CK_BYTE *iv, CK_BYTE *clear, CK_ULONG clear_len, CK_BYTE *cipher, CK_ULONG *p_cipher_len) { #ifndef CLEARTEXT CK_RV rc = CKR_OK; CK_BYTE *initial_vector = NULL; OBJECT *keyobj = NULL; CK_KEY_TYPE keyType; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; CK_ATTRIBUTE key_tmpl[] = { {CKA_CLASS, &keyClass, sizeof(keyClass)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_VALUE, key, keylen} }; switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: keyType = CKK_DES3; break; case CKM_AES_CBC: keyType = CKK_AES; break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return ERR_MECHANISM_INVALID; } rc = object_create_skel(key_tmpl, 3, MODE_CREATE, CKO_SECRET_KEY, keyType, &keyobj); if (rc != CKR_OK) { TRACE_DEVEL("object_create_skel failed.\n"); return rc; } initial_vector = duplicate_initial_vector(iv); if (initial_vector == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return ERR_HOST_MEMORY; } switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: rc = ckm_des3_cbc_encrypt(clear, clear_len, cipher, p_cipher_len, initial_vector, keyobj); break; case CKM_AES_CBC: rc = ckm_aes_cbc_encrypt(clear, clear_len, cipher, p_cipher_len, initial_vector, keyobj); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = ERR_MECHANISM_INVALID; } if (initial_vector) free(initial_vector); return rc; #else memcpy(cipher, clear, clear_len); return CKR_OK; #endif } static CK_RV encrypt_data_with_clear_key(CK_BYTE *key, CK_ULONG keylen, const CK_BYTE *iv, CK_BYTE *clear, CK_ULONG clear_len, CK_BYTE *cipher, CK_ULONG *p_cipher_len) { #ifndef CLEARTEXT CK_RV rc = CKR_OK; CK_BYTE *initial_vector = NULL; /* If token doesn't have a specific key size that means that it uses a * clear key. */ if (token_specific.token_keysize == 0) { return encrypt_data(key, keylen, iv, clear, clear_len, cipher, p_cipher_len); } /* Fall back to a software alternative if key is secure. */ initial_vector = duplicate_initial_vector(iv); if (initial_vector == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return ERR_HOST_MEMORY; } switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: rc = sw_des3_cbc_encrypt(clear, clear_len, cipher, p_cipher_len, initial_vector, key); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = ERR_MECHANISM_INVALID; } if (initial_vector) free(initial_vector); return rc; #else memcpy(cipher, clear, clear_len); return CKR_OK; #endif } static CK_RV decrypt_data(CK_BYTE *key, CK_ULONG keylen, const CK_BYTE *iv, CK_BYTE *cipher, CK_ULONG cipher_len, CK_BYTE *clear, CK_ULONG *p_clear_len) { #ifndef CLEARTEXT CK_RV rc = CKR_OK; CK_BYTE *initial_vector = NULL; OBJECT *keyobj = NULL; CK_KEY_TYPE keyType; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; CK_ATTRIBUTE key_tmpl[] = { {CKA_CLASS, &keyClass, sizeof(keyClass)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_VALUE, key, keylen} }; switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: keyType = CKK_DES3; break; case CKM_AES_CBC: keyType = CKK_AES; break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return ERR_MECHANISM_INVALID; } rc = object_create_skel(key_tmpl, 3, MODE_CREATE, CKO_SECRET_KEY, keyType, &keyobj); if (rc != CKR_OK) { TRACE_DEVEL("object_create_skel failed.\n"); return rc; } initial_vector = duplicate_initial_vector(iv); if (initial_vector == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return ERR_HOST_MEMORY; } switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: rc = ckm_des3_cbc_decrypt(cipher, cipher_len, clear, p_clear_len, initial_vector, keyobj); break; case CKM_AES_CBC: rc = ckm_aes_cbc_decrypt(cipher, cipher_len, clear, p_clear_len, initial_vector, keyobj); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = ERR_MECHANISM_INVALID; } if (initial_vector) free(initial_vector); return rc; #else memcpy(clear, cipher, cipher_len); return CKR_OK; #endif } static CK_RV decrypt_data_with_clear_key(CK_BYTE *key, CK_ULONG keylen, const CK_BYTE *iv, CK_BYTE *cipher, CK_ULONG cipher_len, CK_BYTE *clear, CK_ULONG *p_clear_len) { #ifndef CLEARTEXT CK_RV rc = CKR_OK; CK_BYTE *initial_vector = NULL; /* If token doesn't have a specific key size that means that it uses a * clear key. */ if (token_specific.token_keysize == 0) { return decrypt_data(key, keylen, iv, cipher, cipher_len, clear, p_clear_len); } /* Fall back to a software alternative if key is secure. */ initial_vector = duplicate_initial_vector(iv); if (initial_vector == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return ERR_HOST_MEMORY; } switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: rc = sw_des3_cbc_decrypt(cipher, cipher_len, clear, p_clear_len, initial_vector, key); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = ERR_MECHANISM_INVALID; } if (initial_vector) free(initial_vector); return rc; #else memcpy(clear, cipher, cipher_len); return CKR_OK; #endif } void set_perm(int file) { struct group *grp; if (token_specific.data_store.per_user) { /* In the TPM token, with per user data stores, we don't share * the token object amongst a group. In fact, we want to * restrict access to a single user */ fchmod(file,S_IRUSR|S_IWUSR); } else { // Set absolute permissions or rw-rw-r-- fchmod(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); grp = getgrnam("pkcs11"); // Obtain the group id if (grp) { // set ownership to root, and pkcs11 group if (fchown(file, getuid(), grp->gr_gid) != 0) { goto error; } } else { goto error; } } return; error: TRACE_DEVEL("Unable to set permissions on file.\n"); } // // CK_RV load_token_data(CK_SLOT_ID slot_id) { FILE *fp = NULL; CK_BYTE fname[PATH_MAX]; TOKEN_DATA td; CK_RV rc; char pk_dir_buf[PATH_MAX]; rc = XProcLock(); if (rc != CKR_OK) { TRACE_ERROR("Failed to get Process Lock.\n"); goto out_nolock; } sprintf(fname, "%s/%s", get_pk_dir(pk_dir_buf), PK_LITE_NV); fp = fopen((char *)fname, "r"); if (!fp) { /* Better error checking added */ if (errno == ENOENT) { /* init_token_data may call save_token_data, which * grabs the lock, so we must release it around this * call */ XProcUnLock(); init_token_data(slot_id); rc = XProcLock(); if (rc != CKR_OK) { TRACE_ERROR("Failed to get Process Lock.\n"); goto out_nolock; } fp = fopen((char *)fname, "r"); if (!fp) { // were really hosed here since the created // did not occur TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto out_unlock; } } else { /* Could not open file for some unknown reason */ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto out_unlock; } } set_perm(fileno(fp)); /* Load generic token data */ if (!fread(&td, sizeof(TOKEN_DATA), 1, fp)) { rc = CKR_FUNCTION_FAILED; goto out_unlock; } memcpy(nv_token_data, &td, sizeof(TOKEN_DATA)); /* Load token-specific data */ if (token_specific.t_load_token_data) { rc = token_specific.t_load_token_data(slot_id, fp); if (rc) goto out_unlock; } rc = CKR_OK; out_unlock: XProcUnLock(); out_nolock: if (fp) fclose(fp); return rc; } // // CK_RV save_token_data(CK_SLOT_ID slot_id) { FILE *fp = NULL; TOKEN_DATA td; CK_RV rc; CK_BYTE fname[PATH_MAX]; char pk_dir_buf[PATH_MAX]; rc = XProcLock(); if (rc != CKR_OK) { TRACE_ERROR("Failed to get Process Lock.\n"); goto out_nolock; } sprintf(fname, "%s/%s", get_pk_dir(pk_dir_buf), PK_LITE_NV); fp = fopen((char *)fname, "r+"); if (!fp) { fp = fopen((char *)fname, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } } set_perm(fileno(fp)); /* Write generic token data */ memcpy(&td, nv_token_data, sizeof(TOKEN_DATA)); if (!fwrite(&td, sizeof(TOKEN_DATA), 1, fp)) { rc = CKR_FUNCTION_FAILED; goto done; } /* Write token-specific data */ if (token_specific.t_save_token_data) { rc = token_specific.t_save_token_data(slot_id, fp); if (rc) goto done; } rc = CKR_OK; done: XProcUnLock(); out_nolock: if (fp) fclose(fp); return rc; } // // CK_RV save_token_object(OBJECT * obj) { FILE *fp = NULL; CK_BYTE line[100]; CK_RV rc; CK_BYTE fname[PATH_MAX]; char pk_dir_buf[PATH_MAX]; if (object_is_private(obj) == TRUE) rc = save_private_token_object(obj); else rc = save_public_token_object(obj); if (rc != CKR_OK) return rc; // update the index file if it exists sprintf(fname, "%s/%s/%s", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); fp = fopen((char *)fname, "r"); if (fp) { set_perm(fileno(fp)); while (!feof(fp)) { (void)fgets((char *)line, 50, fp); if (!feof(fp)) { line[strlen(line) - 1] = 0; if (strcmp(line, obj->name) == 0) { fclose(fp); // object is already in the list return CKR_OK; } } } fclose(fp); } // we didn't find it...either the index file doesn't exist or this // is a new object... // fp = fopen((char *)fname, "a"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); return CKR_FUNCTION_FAILED; } set_perm(fileno(fp)); set_perm(fileno(fp)); fprintf(fp, "%s\n", obj->name); fclose(fp); return CKR_OK; } // this is the same as the old version. public token objects are stored in the // clear // CK_RV save_public_token_object(OBJECT * obj) { FILE *fp = NULL; CK_BYTE *clear = NULL; CK_BYTE fname[PATH_MAX]; CK_ULONG clear_len; CK_BBOOL flag = FALSE; CK_RV rc; CK_ULONG_32 total_len; char pk_dir_buf[PATH_MAX]; rc = object_flatten(obj, &clear, &clear_len); if (rc != CKR_OK) { goto error; } sprintf(fname, "%s/%s/", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR); strncat((char *)fname, (char *)obj->name, 8); fp = fopen((char *)fname, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto error; } set_perm(fileno(fp)); total_len = clear_len + sizeof(CK_ULONG_32) + sizeof(CK_BBOOL); (void)fwrite(&total_len, sizeof(CK_ULONG_32), 1, fp); (void)fwrite(&flag, sizeof(CK_BBOOL), 1, fp); (void)fwrite(clear, clear_len, 1, fp); fclose(fp); free(clear); return CKR_OK; error: if (fp) fclose(fp); if (clear) free(clear); return rc; } // // CK_RV save_private_token_object(OBJECT * obj) { FILE *fp = NULL; CK_BYTE *obj_data = NULL; CK_BYTE *clear = NULL; CK_BYTE *cipher = NULL; CK_BYTE *ptr = NULL; CK_BYTE fname[100]; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_BYTE *key = NULL; CK_ULONG key_len = 0L; CK_ULONG block_size = 0L; CK_ULONG obj_data_len, clear_len, cipher_len; CK_ULONG padded_len; CK_BBOOL flag; CK_RV rc; CK_ULONG_32 obj_data_len_32; CK_ULONG_32 total_len; char pk_dir_buf[PATH_MAX]; rc = object_flatten(obj, &obj_data, &obj_data_len); obj_data_len_32 = obj_data_len; if (rc != CKR_OK) { goto error; } // // format for the object file: // private flag // ---- begin encrypted part <--+ // length of object data | // object data +---- sensitive part // SHA of (object data) | // ---- end encrypted part <--+ // compute_sha1(obj_data, obj_data_len, hash_sha); // encrypt the sensitive object data. need to be careful. // if I use the normal high-level encryption routines I'll need to // create a tepmorary key object containing the master key, perform the // encryption, then destroy the key object. There is a race condition // here if the application is multithreaded (if a thread-switch occurs, // the other application thread could do a FindObject and be able to // access the master key object. // // So I have to use the low-level encryption routines. // if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK) goto error; // Duplicate key key = malloc(key_len); if (!key) goto oom_error; memcpy(key, master_key, key_len); clear_len = sizeof(CK_ULONG_32) + obj_data_len_32 + SHA1_HASH_SIZE; cipher_len = padded_len = block_size * (clear_len / block_size + 1); clear = malloc(padded_len); cipher = malloc(padded_len); if (!clear || !cipher) goto oom_error; // Build data that will be encrypted ptr = clear; memcpy(ptr, &obj_data_len_32, sizeof(CK_ULONG_32)); ptr += sizeof(CK_ULONG_32); memcpy(ptr, obj_data, obj_data_len_32); ptr += obj_data_len_32; memcpy(ptr, hash_sha, SHA1_HASH_SIZE); add_pkcs_padding(clear + clear_len, block_size, clear_len, padded_len); rc = encrypt_data_with_clear_key(key, key_len, token_specific.data_store.obj_initial_vector, clear, padded_len, cipher, &cipher_len); if (rc != CKR_OK) { goto error; } sprintf(fname, "%s/%s/", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR); strncat((char *)fname, (char *)obj->name, 8); fp = fopen((char *)fname, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto error; } set_perm(fileno(fp)); total_len = sizeof(CK_ULONG_32) + sizeof(CK_BBOOL) + cipher_len; flag = TRUE; (void)fwrite(&total_len, sizeof(CK_ULONG_32), 1, fp); (void)fwrite(&flag, sizeof(CK_BBOOL), 1, fp); (void)fwrite(cipher, cipher_len, 1, fp); fclose(fp); free(obj_data); free(clear); free(cipher); free(key); return CKR_OK; oom_error: rc = CKR_HOST_MEMORY; error: if (fp) fclose(fp); if (obj_data) free(obj_data); if (clear) free(clear); if (cipher) free(cipher); if (key) free(key); return rc; } // // CK_RV load_public_token_objects(void) { FILE *fp1 = NULL, *fp2 = NULL; CK_BYTE *buf = NULL; CK_BYTE tmp[PATH_MAX], fname[PATH_MAX], iname[PATH_MAX]; CK_BBOOL priv; CK_ULONG_32 size; size_t read_size; char pk_dir_buf[PATH_MAX]; sprintf(iname, "%s/%s/%s", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); fp1 = fopen((char *)iname, "r"); if (!fp1) return CKR_OK; // no token objects while (!feof(fp1)) { (void)fgets((char *)tmp, 50, fp1); if (!feof(fp1)) { tmp[strlen((char *)tmp) - 1] = 0; sprintf((char *)fname, "%s/%s/", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR); strcat((char *)fname, (char *)tmp); fp2 = fopen((char *)fname, "r"); if (!fp2) continue; fread(&size, sizeof(CK_ULONG_32), 1, fp2); fread(&priv, sizeof(CK_BBOOL), 1, fp2); if (priv == TRUE) { fclose(fp2); continue; } // size--; size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL); buf = (CK_BYTE *) malloc(size); if (!buf) { fclose(fp2); OCK_SYSLOG(LOG_ERR, "Cannot malloc %u bytes to read in " "token object %s (ignoring it)", size, fname); continue; } read_size = fread(buf, 1, size, fp2); if (read_size != size) { fclose(fp2); free(buf); OCK_SYSLOG(LOG_ERR, "Cannot read token object %s " "(ignoring it)", fname); continue; } // ... grab object mutex here. MY_LockMutex(&obj_list_mutex); if (object_mgr_restore_obj_withSize(buf, NULL, size) != CKR_OK) { OCK_SYSLOG(LOG_ERR, "Cannot restore token object %s " "(ignoring it)", fname); } MY_UnlockMutex(&obj_list_mutex); free(buf); fclose(fp2); } } fclose(fp1); return CKR_OK; } // // CK_RV load_private_token_objects(void) { FILE *fp1 = NULL, *fp2 = NULL; CK_BYTE *buf = NULL; CK_BYTE tmp[PATH_MAX], fname[PATH_MAX], iname[PATH_MAX]; CK_BBOOL priv; CK_ULONG_32 size; CK_RV rc; size_t read_size; char pk_dir_buf[PATH_MAX]; sprintf(iname, "%s/%s/%s", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); fp1 = fopen((char *)iname, "r"); if (!fp1) return CKR_OK; // no token objects while (!feof(fp1)) { (void)fgets((char *)tmp, 50, fp1); if (!feof(fp1)) { tmp[strlen((char *)tmp) - 1] = 0; sprintf((char *)fname, "%s/%s/", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR); strcat((char *)fname, (char *)tmp); fp2 = fopen((char *)fname, "r"); if (!fp2) continue; fread(&size, sizeof(CK_ULONG_32), 1, fp2); fread(&priv, sizeof(CK_BBOOL), 1, fp2); if (priv == FALSE) { fclose(fp2); continue; } //size--; size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL); buf = (CK_BYTE *) malloc(size); if (!buf) { fclose(fp2); OCK_SYSLOG(LOG_ERR, "Cannot malloc %u bytes to read in " "token object %s (ignoring it)", size, fname); continue; } read_size = fread((char *)buf, 1, size, fp2); if (read_size != size) { free(buf); fclose(fp2); OCK_SYSLOG(LOG_ERR, "Cannot read token object %s " "(ignoring it)", fname); continue; } // Grab object list mutex MY_LockMutex(&obj_list_mutex); rc = restore_private_token_object(buf, size, NULL); MY_UnlockMutex(&obj_list_mutex); if (rc != CKR_OK) goto error; free(buf); fclose(fp2); } } fclose(fp1); return CKR_OK; error: if (buf) free(buf); if (fp1) fclose(fp1); if (fp2) fclose(fp2); return rc; } // // CK_RV restore_private_token_object(CK_BYTE * data, CK_ULONG len, OBJECT * pObj) { CK_BYTE *clear = NULL; CK_BYTE *obj_data = NULL; CK_BYTE *ptr = NULL; CK_BYTE *key = NULL; CK_ULONG key_len; CK_ULONG block_size; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_ULONG clear_len, obj_data_len; CK_RV rc; // format for the object data: // (private flag has already been read at this point) // ---- begin encrypted part // length of object data // object data // SHA of object data // ---- end encrypted part // clear_len = len; clear = (CK_BYTE *) malloc(len); if (!clear) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK) goto done; // decrypt the encrypted chunk key = malloc(key_len); if (!key) { rc = ERR_HOST_MEMORY; goto done; } memcpy(key, master_key, key_len); rc = decrypt_data_with_clear_key(key, key_len, token_specific.data_store.obj_initial_vector, data, len, clear, &clear_len); if (rc != CKR_OK) { goto done; } rc = strip_pkcs_padding(clear, len, &clear_len); // if the padding extraction didn't work it means the object was // tampered with or the key was incorrect // if (rc != CKR_OK || (clear_len > len)) { TRACE_DEVEL("strip_pkcs_padding failed.\n"); rc = CKR_FUNCTION_FAILED; goto done; } ptr = clear; obj_data_len = *(CK_ULONG_32 *) ptr; // prevent buffer overflow in sha_update if (obj_data_len > clear_len) { TRACE_ERROR("stripped length is greater than clear length\n"); rc = CKR_FUNCTION_FAILED; goto done; } ptr += sizeof(CK_ULONG_32); obj_data = ptr; // check the hash // rc = compute_sha1(ptr, obj_data_len, hash_sha); if (rc != CKR_OK) { goto done; } ptr += obj_data_len; if (memcmp(ptr, hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("stored hash does not match restored data hash.\n"); rc = CKR_FUNCTION_FAILED; goto done; } // okay. at this point, we're satisfied that nobody has tampered with // the token object... // rc = object_mgr_restore_obj(obj_data, pObj); if (rc != CKR_OK) { goto done; } rc = CKR_OK; done: if (clear) free(clear); if (key) free(key); return rc; } // // CK_RV load_masterkey_so(void) { FILE *fp = NULL; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_BYTE *cipher = NULL; CK_BYTE *clear = NULL; CK_BYTE *key = NULL; CK_ULONG data_len; CK_ULONG cipher_len, clear_len; CK_RV rc; CK_BYTE fname[PATH_MAX]; CK_ULONG key_len = 0L; CK_ULONG master_key_len = 0L; CK_ULONG block_size = 0L; char pk_dir_buf[PATH_MAX]; if ((rc = get_encryption_info_for_clear_key(&key_len, &block_size)) != CKR_OK) goto done; if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) goto done; memset(master_key, 0x0, master_key_len); data_len = master_key_len + SHA1_HASH_SIZE; clear_len = cipher_len = (data_len + block_size - 1) & ~(block_size - 1); key = malloc(key_len); cipher = malloc(cipher_len); clear = malloc(clear_len); if (key == NULL || cipher == NULL || clear == NULL) { rc = ERR_HOST_MEMORY; goto done; } // this file gets created on C_InitToken so we can assume that it always // exists // sprintf(fname, "%s/MK_SO", get_pk_dir(pk_dir_buf)); fp = fopen((char *)fname, "r"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } set_perm(fileno(fp)); rc = fread(cipher, cipher_len, 1, fp); if (rc != 1) { TRACE_ERROR("fread() failed.\n"); rc = CKR_FUNCTION_FAILED; goto done; } // decrypt the master key data using the MD5 of the SO key // (we can't use the SHA of the SO key since the SHA of the key is // stored in the token data file). memcpy(key, so_pin_md5, MD5_HASH_SIZE); memcpy(key + MD5_HASH_SIZE, so_pin_md5, key_len - MD5_HASH_SIZE); rc = decrypt_data_with_clear_key(key, key_len, token_specific.data_store.pin_initial_vector, cipher, cipher_len, clear, &clear_len); if (rc != CKR_OK) { TRACE_DEVEL("decrypt_data_with_clear_key failed.\n"); goto done; } // // technically should strip PKCS padding here but since I already know // what the length should be, I don't bother. // // compare the hashes // rc = compute_sha1(clear, master_key_len, hash_sha); if (rc != CKR_OK) { goto done; } if (memcmp(hash_sha, clear + master_key_len, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("masterkey hashes do not match\n"); rc = CKR_FUNCTION_FAILED; goto done; } memcpy(master_key, clear, master_key_len); rc = CKR_OK; done: if (fp) fclose(fp); if (clear) free(clear); if (cipher) free(cipher); if (key) free(key); return rc; } // // CK_RV load_masterkey_user(void) { FILE *fp = NULL; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_BYTE *cipher = NULL; CK_BYTE *clear = NULL; CK_BYTE *key = NULL; CK_ULONG data_len; CK_ULONG cipher_len, clear_len; CK_RV rc; CK_BYTE fname[PATH_MAX]; CK_ULONG key_len = 0L; CK_ULONG master_key_len = 0L; CK_ULONG block_size = 0L; char pk_dir_buf[PATH_MAX]; if ((rc = get_encryption_info_for_clear_key(&key_len, &block_size)) != CKR_OK) goto done; if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) goto done; memset(master_key, 0x0, master_key_len); data_len = master_key_len + SHA1_HASH_SIZE; clear_len = cipher_len = (data_len + block_size - 1) & ~(block_size - 1); key = malloc(key_len); cipher = malloc(cipher_len); clear = malloc(clear_len); if (key == NULL || cipher == NULL || clear == NULL) { rc = ERR_HOST_MEMORY; goto done; } // this file gets created on C_InitToken so we can assume that it always // exists // sprintf(fname, "%s/MK_USER", get_pk_dir(pk_dir_buf)); fp = fopen((char *)fname, "r"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } set_perm(fileno(fp)); rc = fread(cipher, cipher_len, 1, fp); if (rc != 1) { TRACE_ERROR("fread failed.\n"); rc = CKR_FUNCTION_FAILED; goto done; } // decrypt the master key data using the MD5 of the SO key // (we can't use the SHA of the SO key since the SHA of the key is // stored in the token data file). memcpy(key, user_pin_md5, MD5_HASH_SIZE); memcpy(key + MD5_HASH_SIZE, user_pin_md5, key_len - MD5_HASH_SIZE); rc = decrypt_data_with_clear_key(key, key_len, token_specific.data_store.pin_initial_vector, cipher, cipher_len, clear, &clear_len); if (rc != CKR_OK) { TRACE_DEVEL("decrypt_data_with_clear_key failed.\n"); goto done; } // // technically should strip PKCS padding here but since I already know // what the length should be, I don't bother. // // compare the hashes // rc = compute_sha1(clear, master_key_len, hash_sha); if (rc != CKR_OK) { goto done; } if (memcmp(hash_sha, clear + master_key_len, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("User's masterkey hashes do not match.\n"); rc = CKR_FUNCTION_FAILED; goto done; } memcpy(master_key, clear, master_key_len); rc = CKR_OK; done: if (fp) fclose(fp); if (key) free(key); if (clear) free(clear); if (cipher) free(cipher); return rc; } // // CK_RV save_masterkey_so(void) { FILE *fp = NULL; CK_BYTE *clear = NULL; CK_ULONG clear_len = 0L; CK_BYTE *cipher = NULL; CK_ULONG cipher_len = 0L; CK_BYTE *key = NULL; CK_ULONG key_len = 0L; CK_ULONG master_key_len = 0L; CK_ULONG block_size = 0L; CK_ULONG data_len = 0L; CK_BYTE fname[PATH_MAX]; CK_RV rc; char pk_dir_buf[PATH_MAX]; /* Skip it if master key is not needed. */ if (!token_specific.data_store.use_master_key) return CKR_OK; if ((rc = get_encryption_info_for_clear_key(&key_len, &block_size)) != CKR_OK) goto done; if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) goto done; data_len = master_key_len + SHA1_HASH_SIZE; cipher_len = clear_len = block_size * (data_len / block_size + 1); key = malloc(key_len); clear = malloc(clear_len); cipher = malloc(cipher_len); if (key == NULL || clear == NULL || cipher == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = ERR_HOST_MEMORY; goto done; } // Copy data to buffer (key+hash) memcpy(clear, master_key, master_key_len); if ((rc = compute_sha1(master_key, master_key_len, clear + master_key_len)) != CKR_OK) goto done; add_pkcs_padding(clear + data_len, block_size, data_len, clear_len); // encrypt the key data memcpy(key, so_pin_md5, MD5_HASH_SIZE); memcpy(key + MD5_HASH_SIZE, so_pin_md5, key_len - MD5_HASH_SIZE); rc = encrypt_data_with_clear_key(key, key_len, token_specific.data_store.pin_initial_vector, clear, clear_len, cipher, &cipher_len); if (rc != CKR_OK) { goto done; } // write the file // // probably ought to ensure the permissions are correct // sprintf(fname, "%s/MK_SO", get_pk_dir(pk_dir_buf)); fp = fopen((char *)fname, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } set_perm(fileno(fp)); rc = fwrite(cipher, cipher_len, 1, fp); if (rc != 1) { TRACE_ERROR("fwrite failed.\n"); rc = CKR_FUNCTION_FAILED; goto done; } rc = CKR_OK; done: if (fp) fclose(fp); if (key) free(key); if (clear) free(clear); if (cipher) free(cipher); return rc; } // // CK_RV save_masterkey_user(void) { FILE *fp = NULL; CK_BYTE *clear = NULL; CK_ULONG clear_len = 0L; CK_BYTE *cipher = NULL; CK_ULONG cipher_len = 0L; CK_BYTE *key = NULL; CK_ULONG key_len = 0L; CK_ULONG master_key_len = 0L; CK_ULONG block_size; CK_ULONG data_len; CK_BYTE fname[PATH_MAX]; CK_RV rc; char pk_dir_buf[PATH_MAX]; if ((rc = get_encryption_info_for_clear_key(&key_len, &block_size)) != CKR_OK) goto done; if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) goto done; data_len = master_key_len + SHA1_HASH_SIZE; cipher_len = clear_len = block_size * (data_len/block_size + 1); key = malloc(key_len); clear = malloc(clear_len); cipher = malloc(cipher_len); if (key == NULL || clear == NULL || cipher == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = ERR_HOST_MEMORY; goto done; } // Copy data to buffer (key+hash) memcpy(clear, master_key, master_key_len); if ((rc = compute_sha1(master_key, master_key_len, clear + master_key_len)) != CKR_OK) goto done; add_pkcs_padding(clear + data_len, block_size , data_len, clear_len); // encrypt the key data memcpy(key, user_pin_md5, MD5_HASH_SIZE); memcpy(key + MD5_HASH_SIZE, user_pin_md5, key_len - MD5_HASH_SIZE); rc = encrypt_data_with_clear_key(key, key_len, token_specific.data_store.pin_initial_vector, clear, clear_len, cipher, &cipher_len); if (rc != CKR_OK) { goto done; } // write the file // // probably ought to ensure the permissions are correct // sprintf(fname, "%s/MK_USER", get_pk_dir(pk_dir_buf)); fp = fopen((char *)fname, "w"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } set_perm(fileno(fp)); rc = fwrite(cipher, cipher_len, 1, fp); if (rc != 1) { TRACE_ERROR("fwrite failed.\n"); rc = CKR_FUNCTION_FAILED; goto done; } rc = CKR_OK; done: if (fp) fclose(fp); if (key) free(key); if (clear) free(clear); if (cipher) free(cipher); return rc; } // // CK_RV reload_token_object(OBJECT * obj) { FILE *fp = NULL; CK_BYTE *buf = NULL; CK_BYTE fname[PATH_MAX]; CK_BBOOL priv; CK_ULONG_32 size; CK_ULONG size_64; CK_RV rc; size_t read_size; char pk_dir_buf[PATH_MAX]; memset((char *)fname, 0x0, sizeof(fname)); sprintf((char *)fname, "%s/%s/", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR); strncat((char *)fname, (char *)obj->name, 8); fp = fopen((char *)fname, "r"); if (!fp) { TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); rc = CKR_FUNCTION_FAILED; goto done; } set_perm(fileno(fp)); fread(&size, sizeof(CK_ULONG_32), 1, fp); fread(&priv, sizeof(CK_BBOOL), 1, fp); size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL); // SAB buf = (CK_BYTE *) malloc(size); if (!buf) { rc = CKR_HOST_MEMORY; OCK_SYSLOG(LOG_ERR, "Cannot malloc %u bytes to read in token object %s " "(ignoring it)", size, fname); goto done; } read_size = fread(buf, 1, size, fp); if (read_size != size) { OCK_SYSLOG(LOG_ERR, "Token object %s appears corrupted (ignoring it)", fname); rc = CKR_FUNCTION_FAILED; goto done; } size_64 = size; if (priv) rc = restore_private_token_object(buf, size_64, obj); else rc = object_mgr_restore_obj(buf, obj); done: if (fp) fclose(fp); if (buf) free(buf); return rc; } extern void set_perm(int); // // CK_RV delete_token_object(OBJECT * obj) { FILE *fp1, *fp2; CK_BYTE line[100]; CK_BYTE objidx[PATH_MAX], idxtmp[PATH_MAX], fname[PATH_MAX]; char pk_dir_buf[PATH_MAX]; sprintf((char *)objidx, "%s/%s/%s", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX); sprintf((char *)idxtmp, "%s/%s/%s", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR, "IDX.TMP"); // FIXME: on UNIX, we need to make sure these guys aren't symlinks // before we blindly write to these files... // // remove the object from the index file // fp1 = fopen((char *)objidx, "r"); fp2 = fopen((char *)idxtmp, "w"); if (!fp1 || !fp2) { if (fp1) fclose(fp1); if (fp2) fclose(fp2); TRACE_ERROR("fopen failed\n"); return CKR_FUNCTION_FAILED; } set_perm(fileno(fp2)); while (!feof(fp1)) { (void)fgets((char *)line, 50, fp1); if (!feof(fp1)) { line[strlen((char *)line) - 1] = 0; if (strcmp((char *)line, (char *)obj->name) == 0) continue; else fprintf(fp2, "%s\n", line); } } fclose(fp1); fclose(fp2); fp2 = fopen((char *)objidx, "w"); fp1 = fopen((char *)idxtmp, "r"); if (!fp1 || !fp2) { if (fp1) fclose(fp1); if (fp2) fclose(fp2); TRACE_ERROR("fopen failed\n"); return CKR_FUNCTION_FAILED; } set_perm(fileno(fp2)); while (!feof(fp1)) { (void)fgets((char *)line, 50, fp1); if (!feof(fp1)) fprintf(fp2, "%s", (char *)line); } fclose(fp1); fclose(fp2); sprintf((char *)fname, "%s/%s/%s", get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR, (char *)obj->name); unlink((char *)fname); return CKR_OK; } CK_RV delete_token_data() { CK_RV rc = CKR_OK; char *cmd = NULL; char pk_dir_buf[PATH_MAX]; // Construct a string to delete the token objects. // // META This should be fine since the open session checking // should occur at the API not the STDLL // // TODO: Implement delete_all_files_in_dir() */ if (asprintf(&cmd, "%s %s/%s/* > /dev/null 2>&1", DEL_CMD, get_pk_dir(pk_dir_buf), PK_LITE_OBJ_DIR) < 0) { rc = CKR_HOST_MEMORY; goto done; } system(cmd); done: free(cmd); return rc; } CK_RV generate_master_key(CK_BYTE *key) { CK_RV rc = CKR_OK; CK_ULONG key_len = 0L; CK_ULONG master_key_len = 0L; /* Skip it if master key is not needed. */ if (!token_specific.data_store.use_master_key) return CKR_OK; if ((rc = get_encryption_info_for_clear_key(&key_len, NULL)) != CKR_OK || (rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK) return ERR_FUNCTION_FAILED; /* For secure key tokens, object encrypt/decrypt uses * software(openssl), not token. So generate masterkey via RNG. */ if (token_specific.token_keysize) return rng_generate(key, key_len); /* For clear key tokens, let token generate masterkey * since token will also encrypt/decrypt the objects. */ switch (token_specific.data_store.encryption_algorithm) { case CKM_DES3_CBC: return token_specific.t_des_key_gen(key, master_key_len, key_len); case CKM_AES_CBC: return token_specific.t_aes_key_gen(key, master_key_len, key_len); } return ERR_MECHANISM_INVALID; } void init_data_store(char *directory) { char *pkdir; if ((pkdir = getenv("PKCS_APP_STORE")) != NULL) { pk_dir = (char *)malloc(strlen(pkdir) + 1024); memset(pk_dir, 0, strlen(pkdir) + 1024); sprintf(pk_dir, "%s/%s", pkdir, SUB_DIR); } else { pk_dir = (char *)malloc(strlen(directory) + 25); memset(pk_dir, 0, strlen(directory) + 25); sprintf(pk_dir, "%s", directory); } } opencryptoki+dfsg/usr/lib/pkcs11/common/decr_mgr.c0000755000175000017500000015225412630407154021212 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: decr_mgr.c // // Decryption manager routines // #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" CK_AES_CTR_PARAMS aesctr; // // CK_RV decr_mgr_init( SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_ULONG operation, CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle ) { OBJECT * key_obj = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_KEY_TYPE keytype; CK_BBOOL flag; CK_RV rc; if (!sess){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active != FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } // key usage restrictions // if (operation == OP_DECRYPT_INIT) { rc = object_mgr_find_in_map1( key_handle, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle.\n"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } // is key allowed to do general decryption? // rc = template_attribute_find( key_obj->template, CKA_DECRYPT, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_ENCRYPT for the key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } else { flag = *(CK_BBOOL *)attr->pValue; if (flag != TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_FUNCTION_NOT_PERMITTED)); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } } else if (operation == OP_UNWRAP) { rc = object_mgr_find_in_map1( key_handle, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to acquire key from specified handle.\n"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_WRAPPING_KEY_HANDLE_INVALID; else return rc; } // is key allowed to unwrap other keys? // rc = template_attribute_find( key_obj->template, CKA_UNWRAP, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_UNWRAP for the key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } else { flag = *(CK_BBOOL *)attr->pValue; if (flag == FALSE){ TRACE_ERROR("CKA_UNWRAP is set to FALSE.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } } } else{ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // is the mechanism supported? is the key type correct? is a // parameter present if required? is the key size allowed? // does the key support decryption? // // Will the FCV allow the operation? // switch (mech->mechanism) { case CKM_DES_ECB: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_56_BIT_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_CDMF_ECB: { if (mech->ulParameterLen != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_CDMF){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_CDMF_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_DES_CBC: case CKM_DES_CBC_PAD: { if (mech->ulParameterLen != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_56_BIT_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_CDMF_CBC: case CKM_CDMF_CBC_PAD: { if (mech->ulParameterLen != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_CDMF){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_DES_CFB8: case CKM_DES_CFB64: case CKM_DES_OFB64: { if (mech->ulParameterLen != DES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if ((keytype != CKK_DES3)) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_DES3_ECB: { if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DES3 && keytype != CKK_DES2){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_TRIPLE_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_DES3_CBC: case CKM_DES3_CBC_PAD: { if (mech->ulParameterLen != DES_BLOCK_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_DES3 && keytype != CKK_DES2){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // Check FCV // // if ((nv_FCV.FunctionCntlBytes[DES_FUNCTION_BYTE] & FCV_TRIPLE_DES) == 0) // return CKR_MECHANISM_INVALID; ctx->context_len = sizeof(DES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(DES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(DES_CONTEXT) ); } break; case CKM_RSA_PKCS_OAEP: if (mech->ulParameterLen == 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find(key_obj->template,CKA_KEY_TYPE,&attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } // RSA cannot be used for multi-part operations // ctx->context_len = 0; ctx->context = NULL; break; case CKM_RSA_X_509: case CKM_RSA_PKCS: { if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_RSA){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } // RSA cannot be used for multi-part operations // ctx->context_len = 0; ctx->context = NULL; } break; case CKM_AES_ECB: { // XXX Copied from DES3, should be verified - KEY if (mech->ulParameterLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_AES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_CONTEXT) ); } break; case CKM_AES_CBC: case CKM_AES_CBC_PAD: { // XXX Copied from DES3, should be verified - KEY if (mech->ulParameterLen != AES_INIT_VECTOR_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? // rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_AES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_CONTEXT) ); } break; case CKM_AES_CTR: { if (mech->ulParameterLen != sizeof(CK_AES_CTR_PARAMS)){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } // is the key type correct? rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_AES){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_CONTEXT) ); } break; case CKM_AES_GCM: { if (mech->ulParameterLen != sizeof(CK_GCM_PARAMS)) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find(key_obj->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if (keytype != CKK_AES) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_GCM_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_GCM_CONTEXT)); if (!ctx->context) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(ctx->context, 0x0, sizeof(AES_GCM_CONTEXT)); rc = aes_gcm_init(sess, ctx, mech, key_handle, 0); if (rc) { TRACE_ERROR("Could not initialize AES_GCM parms.\n"); return CKR_FUNCTION_FAILED; } } break; case CKM_AES_OFB: case CKM_AES_CFB8: case CKM_AES_CFB64: case CKM_AES_CFB128: { if (mech->ulParameterLen != AES_INIT_VECTOR_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } rc = template_attribute_find( key_obj->template, CKA_KEY_TYPE, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } else { keytype = *(CK_KEY_TYPE *)attr->pValue; if ( keytype != CKK_AES ){ TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } } ctx->context_len = sizeof(AES_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(AES_CONTEXT)); if (!ctx->context){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset( ctx->context, 0x0, sizeof(AES_CONTEXT) ); } break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_INVALID; } if ((mech->ulParameterLen > 0) || (mech->mechanism == CKM_AES_CTR) || (mech->mechanism == CKM_AES_GCM)) { ptr = (CK_BYTE *) malloc(mech->ulParameterLen); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, mech->pParameter, mech->ulParameterLen ); } else if (mech->ulParameterLen > 0) { ptr = (CK_BYTE *)malloc(mech->ulParameterLen); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( ptr, mech->pParameter, mech->ulParameterLen ); } ctx->key = key_handle; ctx->mech.ulParameterLen = mech->ulParameterLen; ctx->mech.mechanism = mech->mechanism; ctx->mech.pParameter = ptr; ctx->multi = FALSE; ctx->active = TRUE; return CKR_OK; } // // CK_RV decr_mgr_cleanup( ENCR_DECR_CONTEXT *ctx ) { if (!ctx){ TRACE_ERROR("Invalid function argument.\n"); return CKR_FUNCTION_FAILED; } ctx->key = 0; ctx->mech.ulParameterLen = 0; ctx->mech.mechanism = 0; ctx->multi = FALSE; ctx->active = FALSE; ctx->context_len = 0; if (ctx->mech.pParameter) { free( ctx->mech.pParameter ); ctx->mech.pParameter = NULL; } if (ctx->context) { free( ctx->context ); ctx->context = NULL; } return CKR_OK; } // // CK_RV decr_mgr_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { CK_KEY_TYPE keytype; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } // if the caller just wants the decrypted length, there is no reason to // specify the input data. I just need the data length // if ((length_only == FALSE) && (!in_data || !out_data)){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->multi == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); return CKR_OPERATION_ACTIVE; } switch (ctx->mech.mechanism) { case CKM_CDMF_ECB: case CKM_DES_ECB: return des_ecb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_CDMF_CBC: case CKM_DES_CBC: return des_cbc_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES_CBC_PAD: case CKM_CDMF_CBC_PAD: return des_cbc_pad_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES_OFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_ofb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB8: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x01); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x08); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES3_ECB: return des3_ecb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_CBC: return des3_cbc_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_CBC_PAD: return des3_cbc_pad_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_RSA_PKCS: return rsa_pkcs_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_RSA_PKCS_OAEP: return rsa_oaep_crypt(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, DECRYPT); case CKM_RSA_X_509: return rsa_x509_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); #ifndef NOAES case CKM_AES_CBC: return aes_cbc_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_ECB: return aes_ecb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CBC_PAD: return aes_cbc_pad_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CTR: return aes_ctr_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_GCM: return aes_gcm_decrypt(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); case CKM_AES_OFB: return aes_ofb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); case CKM_AES_CFB8: return aes_cfb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x01); case CKM_AES_CFB64: return aes_cfb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x08); case CKM_AES_CFB128: return aes_cfb_decrypt( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x10); #endif default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV decr_mgr_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { CK_KEY_TYPE keytype; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (!out_data && !length_only){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } ctx->multi = TRUE; switch (ctx->mech.mechanism) { case CKM_CDMF_ECB: case CKM_DES_ECB: return des_ecb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_CDMF_CBC: case CKM_DES_CBC: return des_cbc_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES_CBC_PAD: case CKM_CDMF_CBC_PAD: return des_cbc_pad_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES_OFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_ofb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB8: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x01); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x08); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES3_ECB: return des3_ecb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_CBC: return des3_cbc_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_DES3_CBC_PAD: return des3_cbc_pad_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); #ifndef NOAES case CKM_AES_ECB: return aes_ecb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CBC: return aes_cbc_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CBC_PAD: return aes_cbc_pad_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CTR: return aes_ctr_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); case CKM_AES_GCM: return aes_gcm_decrypt_update(sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len); case CKM_AES_OFB: return aes_ofb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); case CKM_AES_CFB8: return aes_cfb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x01); case CKM_AES_CFB64: return aes_cfb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x08); case CKM_AES_CFB128: return aes_cfb_decrypt_update( sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len, 0x10); #endif default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // // CK_RV decr_mgr_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { CK_KEY_TYPE keytype; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } switch (ctx->mech.mechanism) { case CKM_CDMF_ECB: case CKM_DES_ECB: return des_ecb_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_CDMF_CBC: case CKM_DES_CBC: return des_cbc_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_DES_CBC_PAD: case CKM_CDMF_CBC_PAD: return des_cbc_pad_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_DES_OFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_ofb_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB8: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_decrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x01); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES_CFB64: get_keytype(ctx->key, &keytype); if (keytype == CKK_DES3) { return des3_cfb_decrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x08); } else { TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT)); return CKR_KEY_TYPE_INCONSISTENT; } case CKM_DES3_ECB: return des3_ecb_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_DES3_CBC: return des3_cbc_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_DES3_CBC_PAD: return des3_cbc_pad_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); #ifndef NOAES case CKM_AES_ECB: return aes_ecb_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_CBC: return aes_cbc_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_CBC_PAD: return aes_cbc_pad_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_OFB: return aes_ofb_decrypt_final( sess, length_only, ctx, out_data, out_data_len ); case CKM_AES_CFB8: return aes_cfb_decrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x01); case CKM_AES_CFB64: return aes_cfb_decrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x08); case CKM_AES_CFB128: return aes_cfb_decrypt_final( sess, length_only, ctx, out_data, out_data_len, 0x10); case CKM_AES_CTR: return aes_ctr_decrypt_final( sess, length_only, ctx, out_data, out_data_len); case CKM_AES_GCM: return aes_gcm_decrypt_final(sess, length_only, ctx, out_data, out_data_len); #endif default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } opencryptoki+dfsg/usr/lib/pkcs11/common/mech_dsa.c0000755000175000017500000005336512630407154021176 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: mech_dsa.c // // Mechanisms for DSA // // Routines contained within: #include #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV dsa_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_BYTE sig[DSA_SIGNATURE_SIZE]; CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc } // must be a PRIVATE key operation // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find in the template\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; // if it's not a private DSA key then we have an internal failure...means // that somehow a public key got assigned a CKA_SIGN attribute // if (class != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } // check input data length restrictions. Generic DSA works on the SHA-1 // hash of the data so the input to the DSA operation must be 20 bytes // if (in_data_len != 20){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } if (length_only == TRUE) { *out_data_len = DSA_SIGNATURE_SIZE; return CKR_OK; } rc = ckm_dsa_sign( in_data, sig, key_obj ); if (rc == CKR_OK) { memcpy( out_data, sig, DSA_SIGNATURE_SIZE ); *out_data_len = DSA_SIGNATURE_SIZE; } return rc; } // // CK_RV dsa_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * signature, CK_ULONG sig_len ) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_OBJECT_CLASS class; CK_BBOOL flag; CK_RV rc; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc } // must be a PUBLIC key operation // flag = template_attribute_find( key_obj->template, CKA_CLASS, &attr ); if (flag == FALSE){ TRACE_ERROR("Could not find CKA_CLASS in the template\n"); return CKR_FUNCTION_FAILED; } else class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PUBLIC_KEY){ TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } // check input data length restrictions // if (sig_len != DSA_SIGNATURE_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } if (in_data_len != 20){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } rc = ckm_dsa_verify( signature, in_data, key_obj ); return rc; } // // mechanisms // // // CK_RV ckm_dsa_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_ATTRIBUTE * prime = NULL; CK_ATTRIBUTE * subprime = NULL; CK_ATTRIBUTE * base = NULL; CK_ATTRIBUTE * priv_exp = NULL; CK_ATTRIBUTE * publ_exp = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_BYTE repl_buf[5500]; CK_BBOOL flag; CK_RV rc; if (token_specific.t_dsa_generate_keypair == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_dsa_generate_keypair(publ_tmpl,priv_tmpl); if (rc != CKR_OK) TRACE_DEVEL("Tpken specific dsa keypair generation failed.\n"); return rc; } // // CK_RV ckm_dsa_sign( CK_BYTE * in_data, CK_BYTE * signature, OBJECT * priv_key ) { CK_ATTRIBUTE * prime = NULL; CK_ATTRIBUTE * subprime = NULL; CK_ATTRIBUTE * base = NULL; CK_ATTRIBUTE * exponent = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = template_attribute_find( priv_key->template, CKA_CLASS, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_CLASS in the template\n"); return CKR_FUNCTION_FAILED; } else keyclass = *(CK_OBJECT_CLASS *)attr->pValue; // this had better be a private key // if (keyclass != CKO_PRIVATE_KEY){ TRACE_ERROR("This operation requires a private key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if (token_specific.t_dsa_sign == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_dsa_sign(in_data, signature, priv_key); if (rc != CKR_OK) TRACE_DEVEL("Token specific dsa sign failed.\n"); return rc; } // // CK_RV ckm_dsa_verify( CK_BYTE * signature, CK_BYTE * data, OBJECT * publ_key ) { CK_ATTRIBUTE * prime = NULL; CK_ATTRIBUTE * subprime = NULL; CK_ATTRIBUTE * base = NULL; CK_ATTRIBUTE * exponent = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_OBJECT_CLASS keyclass; CK_RV rc; rc = template_attribute_find( publ_key->template, CKA_CLASS, &attr ); if (rc == FALSE){ TRACE_ERROR("Could not find CKA_CLASS in the template\n"); return CKR_FUNCTION_FAILED; } else keyclass = *(CK_OBJECT_CLASS *)attr->pValue; // this had better be a private key // if (keyclass != CKO_PUBLIC_KEY){ TRACE_ERROR("This operation requires a public key.\n"); return CKR_KEY_FUNCTION_NOT_PERMITTED; } if (token_specific.t_dsa_verify == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_dsa_verify(signature, data, publ_key); if (rc != CKR_OK) TRACE_DEVEL("Token specific dsa verify failed.\n"); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/common/mech_sha.c0000755000175000017500000016116212630407154021175 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: mech_sha.c // // Mechanisms for SHA-1 related routines // // The following applies to the software SHA implementation: // Written 2 September 1992, Peter C. Gutmann. // This implementation placed in the public domain. // // Modified 1 June 1993, Colin Plumb. // Modified for the new SHS based on Peter Gutmann's work, // 18 July 1994, Colin Plumb. // Gutmann's work. // Renamed to SHA and comments updated a bit 1 November 1995, Colin Plumb. // These modifications placed in the public domain. // // Comments to pgut1@cs.aukuni.ac.nz // #include #include // for memcmp() et al #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" #define SHA_HARDWARE_THRESHHOLD 128000 // The SHA f()-functions. The f1 and f3 functions can be optimized to // save one boolean operation each - thanks to Rich Schroeppel, // rcs@cs.arizona.edu for discovering this // #define f1(x,y,z) (z ^ (x & (y ^ z))) // Rounds 0-19 #define f2(x,y,z) (x ^ y ^ z) // Rounds 20-39 #define f3(x,y,z) ((x & y) | (z & (x | y))) // Rounds 40-59 #define f4(x,y,z) (x ^ y ^ z) // Rounds 60-79 // The SHA Mysterious Constants. // K1 = floor(sqrt(2) * 2^30) // K2 = floor(sqrt(3) * 2^30) // K3 = floor(sqrt(5) * 2^30) // K4 = floor(sqrt(10) * 2^30) // #define K1 0x5A827999L // Rounds 0-19 #define K2 0x6ED9EBA1L // Rounds 20-39 #define K3 0x8F1BBCDCL // Rounds 40-59 #define K4 0xCA62C1D6L // Rounds 60-79 // SHA initial values // #define h0init 0x67452301 #define h1init 0xEFCDAB89 #define h2init 0x98BADCFE #define h3init 0x10325476 #define h4init 0xC3D2E1F0 // // Note that it may be necessary to add parentheses to these macros // if they are to be called with expressions as arguments. // // 32-bit rotate left - kludged with shifts // #define ROTL(n,X) ((X << n) | (X >> (32-n))) // The initial expanding function // // The hash function is defined over an 80-word expanded input array W, // where the first 16 are copies of the input data, and the remaining 64 // are defined by W[i] = W[i-16] ^ W[i-14] ^ W[i-8] ^ W[i-3]. This // implementation generates these values on the fly in a circular buffer. // #define expand(W,i) \ (W[i&15] ^= W[(i-14)&15] ^ W[(i-8)&15] ^ W[(i-3)&15], W[i&15] = ROTL(1, W[i&15])) // The prototype SHA sub-round // // The fundamental sub-round is // a' = e + ROTL(5,a) + f(b, c, d) + k + data; // b' = a; // c' = ROTL(30,b); // d' = c; // e' = d; // ... but this is implemented by unrolling the loop 5 times and renaming // the variables (e,a,b,c,d) = (a',b',c',d',e') each iteration. // #define subRound(a, b, c, d, e, f, k, data) \ (e += ROTL(5,a) + f(b, c, d) + k + data, b = ROTL(30, b)) /* * Perform the SHA transformation. Note that this code, like MD5, seems to * break some optimizing compilers due to the complexity of the expressions * and the size of the basic block. It may be necessary to split it into * sections, e.g. based on the four subrounds * * Note that this corrupts the sha->data area */ void shaTransform(SHA1_CONTEXT *ctx) { register unsigned int A, B, C, D, E; // Set up first buffer // A = ctx->hash_value[0]; B = ctx->hash_value[1]; C = ctx->hash_value[2]; D = ctx->hash_value[3]; E = ctx->hash_value[4]; // Heavy mangling, in 4 sub-rounds of 20 interations each. // subRound(A, B, C, D, E, f1, K1, ctx->buf[ 0]); subRound(E, A, B, C, D, f1, K1, ctx->buf[ 1]); subRound(D, E, A, B, C, f1, K1, ctx->buf[ 2]); subRound(C, D, E, A, B, f1, K1, ctx->buf[ 3]); subRound(B, C, D, E, A, f1, K1, ctx->buf[ 4]); subRound(A, B, C, D, E, f1, K1, ctx->buf[ 5]); subRound(E, A, B, C, D, f1, K1, ctx->buf[ 6]); subRound(D, E, A, B, C, f1, K1, ctx->buf[ 7]); subRound(C, D, E, A, B, f1, K1, ctx->buf[ 8]); subRound(B, C, D, E, A, f1, K1, ctx->buf[ 9]); subRound(A, B, C, D, E, f1, K1, ctx->buf[10]); subRound(E, A, B, C, D, f1, K1, ctx->buf[11]); subRound(D, E, A, B, C, f1, K1, ctx->buf[12]); subRound(C, D, E, A, B, f1, K1, ctx->buf[13]); subRound(B, C, D, E, A, f1, K1, ctx->buf[14]); subRound(A, B, C, D, E, f1, K1, ctx->buf[15]); subRound(E, A, B, C, D, f1, K1, expand(ctx->buf, 16)); subRound(D, E, A, B, C, f1, K1, expand(ctx->buf, 17)); subRound(C, D, E, A, B, f1, K1, expand(ctx->buf, 18)); subRound(B, C, D, E, A, f1, K1, expand(ctx->buf, 19)); subRound(A, B, C, D, E, f2, K2, expand(ctx->buf, 20)); subRound(E, A, B, C, D, f2, K2, expand(ctx->buf, 21)); subRound(D, E, A, B, C, f2, K2, expand(ctx->buf, 22)); subRound(C, D, E, A, B, f2, K2, expand(ctx->buf, 23)); subRound(B, C, D, E, A, f2, K2, expand(ctx->buf, 24)); subRound(A, B, C, D, E, f2, K2, expand(ctx->buf, 25)); subRound(E, A, B, C, D, f2, K2, expand(ctx->buf, 26)); subRound(D, E, A, B, C, f2, K2, expand(ctx->buf, 27)); subRound(C, D, E, A, B, f2, K2, expand(ctx->buf, 28)); subRound(B, C, D, E, A, f2, K2, expand(ctx->buf, 29)); subRound(A, B, C, D, E, f2, K2, expand(ctx->buf, 30)); subRound(E, A, B, C, D, f2, K2, expand(ctx->buf, 31)); subRound(D, E, A, B, C, f2, K2, expand(ctx->buf, 32)); subRound(C, D, E, A, B, f2, K2, expand(ctx->buf, 33)); subRound(B, C, D, E, A, f2, K2, expand(ctx->buf, 34)); subRound(A, B, C, D, E, f2, K2, expand(ctx->buf, 35)); subRound(E, A, B, C, D, f2, K2, expand(ctx->buf, 36)); subRound(D, E, A, B, C, f2, K2, expand(ctx->buf, 37)); subRound(C, D, E, A, B, f2, K2, expand(ctx->buf, 38)); subRound(B, C, D, E, A, f2, K2, expand(ctx->buf, 39)); subRound(A, B, C, D, E, f3, K3, expand(ctx->buf, 40)); subRound(E, A, B, C, D, f3, K3, expand(ctx->buf, 41)); subRound(D, E, A, B, C, f3, K3, expand(ctx->buf, 42)); subRound(C, D, E, A, B, f3, K3, expand(ctx->buf, 43)); subRound(B, C, D, E, A, f3, K3, expand(ctx->buf, 44)); subRound(A, B, C, D, E, f3, K3, expand(ctx->buf, 45)); subRound(E, A, B, C, D, f3, K3, expand(ctx->buf, 46)); subRound(D, E, A, B, C, f3, K3, expand(ctx->buf, 47)); subRound(C, D, E, A, B, f3, K3, expand(ctx->buf, 48)); subRound(B, C, D, E, A, f3, K3, expand(ctx->buf, 49)); subRound(A, B, C, D, E, f3, K3, expand(ctx->buf, 50)); subRound(E, A, B, C, D, f3, K3, expand(ctx->buf, 51)); subRound(D, E, A, B, C, f3, K3, expand(ctx->buf, 52)); subRound(C, D, E, A, B, f3, K3, expand(ctx->buf, 53)); subRound(B, C, D, E, A, f3, K3, expand(ctx->buf, 54)); subRound(A, B, C, D, E, f3, K3, expand(ctx->buf, 55)); subRound(E, A, B, C, D, f3, K3, expand(ctx->buf, 56)); subRound(D, E, A, B, C, f3, K3, expand(ctx->buf, 57)); subRound(C, D, E, A, B, f3, K3, expand(ctx->buf, 58)); subRound(B, C, D, E, A, f3, K3, expand(ctx->buf, 59)); subRound(A, B, C, D, E, f4, K4, expand(ctx->buf, 60)); subRound(E, A, B, C, D, f4, K4, expand(ctx->buf, 61)); subRound(D, E, A, B, C, f4, K4, expand(ctx->buf, 62) ); subRound(C, D, E, A, B, f4, K4, expand(ctx->buf, 63) ); subRound(B, C, D, E, A, f4, K4, expand(ctx->buf, 64) ); subRound(A, B, C, D, E, f4, K4, expand(ctx->buf, 65) ); subRound(E, A, B, C, D, f4, K4, expand(ctx->buf, 66) ); subRound(D, E, A, B, C, f4, K4, expand(ctx->buf, 67) ); subRound(C, D, E, A, B, f4, K4, expand(ctx->buf, 68) ); subRound(B, C, D, E, A, f4, K4, expand(ctx->buf, 69) ); subRound(A, B, C, D, E, f4, K4, expand(ctx->buf, 70) ); subRound(E, A, B, C, D, f4, K4, expand(ctx->buf, 71) ); subRound(D, E, A, B, C, f4, K4, expand(ctx->buf, 72) ); subRound(C, D, E, A, B, f4, K4, expand(ctx->buf, 73) ); subRound(B, C, D, E, A, f4, K4, expand(ctx->buf, 74) ); subRound(A, B, C, D, E, f4, K4, expand(ctx->buf, 75) ); subRound(E, A, B, C, D, f4, K4, expand(ctx->buf, 76) ); subRound(D, E, A, B, C, f4, K4, expand(ctx->buf, 77) ); subRound(C, D, E, A, B, f4, K4, expand(ctx->buf, 78) ); subRound(B, C, D, E, A, f4, K4, expand(ctx->buf, 79) ); // Build message digest // ctx->hash_value[0] += A; ctx->hash_value[1] += B; ctx->hash_value[2] += C; ctx->hash_value[3] += D; ctx->hash_value[4] += E; } /* * SHA is defined in big-endian form, so this converts the buffer from * bytes to words, independent of the machine's native endianness. * * Assuming a consistent byte ordering for the machine, this also * has the magic property of being self-inverse. It is used as * such. */ static void byteReverse(unsigned int *buffer, unsigned int byteCount) { #ifndef __BYTE_ORDER #error "Endianess MUST be defined" #endif #if __BYTE_ORDER == __LITTLE_ENDIAN CK_ULONG value, val; byteCount /= sizeof(CK_ULONG_32); while (byteCount--) { val = *buffer; value = ((0x000000FF & val) << 24) | ((0x0000FF00 & val) << 8 ) | ((0x00FF0000 & val) >> 8 ) | ((0xFF000000 & val) >> 24); *buffer++ = value; } #endif /* * JRM - this code gives funky results on Linux/Intel. * I assume this is a GCC issue since regression tests passed on NT * * byteCount /= sizeof(CK_ULONG); * while ( byteCount-- ) { * value = (CK_ULONG)((unsigned)((CK_BYTE *)buffer)[0] << 8 | * ((CK_BYTE *)buffer)[1]) << 16 | * ((unsigned)((CK_BYTE *)buffer)[2] << 8 | * ((CK_BYTE *)buffer)[3]); * *buffer++ = value; * } */ } void shaUpdate(SHA1_CONTEXT *ctx, CK_BYTE const *buffer, CK_ULONG count) { CK_ULONG t; // Update bitcount // t = ctx->bits_lo; if ((ctx->bits_lo = t + count) < t) ctx->bits_hi++; // Carry from low to high t &= 0x3f; // Bytes already in ctx->buf // Handle any leading odd-sized chunks // if (t) { CK_BYTE *p = (CK_BYTE *)ctx->buf + t; t = 64-t; if (count < t) { memcpy(p, buffer, count); return; } memcpy(p, buffer, t); byteReverse(ctx->buf, SHA1_BLOCK_SIZE); shaTransform(ctx); buffer += t; count -= t; } // Process data in SHA1_BLOCK_SIZE chunks // while (count >= SHA1_BLOCK_SIZE) { memcpy(ctx->buf, buffer, SHA1_BLOCK_SIZE); byteReverse(ctx->buf, SHA1_BLOCK_SIZE); shaTransform(ctx); buffer += SHA1_BLOCK_SIZE; count -= SHA1_BLOCK_SIZE; } // Handle any remaining bytes of data. // memcpy(ctx->buf, buffer, count); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void shaFinal(SHA1_CONTEXT *ctx, CK_BYTE *hash) { int count; CK_BYTE *p; // Compute number of bytes mod 64 // count = (int)ctx->bits_lo & 0x3F; // Set the first char of padding to 0x80. // This is safe since there is always at least one byte free // p = (CK_BYTE *)ctx->buf + count; *p++ = 0x80; // Bytes of padding needed to make 64 bytes // count = SHA1_BLOCK_SIZE - 1 - count; // Pad out to 56 mod 64 // if (count < 8) { // Two lots of padding: Pad the first block to 64 bytes // memset(p, 0, count); byteReverse(ctx->buf, SHA1_BLOCK_SIZE); shaTransform(ctx); // Now fill the next block with 56 bytes // memset(ctx->buf, 0, SHA1_BLOCK_SIZE-8); } else { // Pad block to 56 bytes // memset(p, 0, count-8); } byteReverse(ctx->buf, SHA1_BLOCK_SIZE-8); // Append length in *bits* and transform // ctx->buf[14] = ctx->bits_hi << 3 | ctx->bits_lo >> 29; ctx->buf[15] = ctx->bits_lo << 3; shaTransform(ctx); // Store output hash in buffer // byteReverse(ctx->hash_value, SHA1_HASH_SIZE); memcpy(hash, ctx->hash_value, SHA1_HASH_SIZE); } // // Software SHA-1 implementation // void sw_sha1_init(DIGEST_CONTEXT *ctx) { // Set the h-vars to their initial values SHA1_CONTEXT *sha1_ctx; /* Allocate the context */ ctx->context_len = sizeof(SHA1_CONTEXT); ctx->context = (CK_BYTE *)malloc(sizeof(SHA1_CONTEXT)); if (ctx->context == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); // TODO: propagate error up? return; } sha1_ctx = (SHA1_CONTEXT *)ctx->context; sha1_ctx->hash_value[0] = h0init; sha1_ctx->hash_value[1] = h1init; sha1_ctx->hash_value[2] = h2init; sha1_ctx->hash_value[3] = h3init; sha1_ctx->hash_value[4] = h4init; // Initialise bit count sha1_ctx->bits_lo = sha1_ctx->bits_hi = 0; } CK_RV sw_sha1_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { if (!ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < SHA1_HASH_SIZE) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (ctx->context == NULL) return CKR_HOST_MEMORY; shaUpdate((SHA1_CONTEXT *)ctx->context, in_data, in_data_len); shaFinal((SHA1_CONTEXT *)ctx->context, out_data); *out_data_len = SHA1_HASH_SIZE; return CKR_OK; } CK_RV sha_hash(SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { CK_ULONG hsize; if (!ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } switch(ctx->mech.mechanism) { case CKM_SHA_1: hsize = SHA1_HASH_SIZE; break; case CKM_SHA256: hsize = SHA2_HASH_SIZE; break; case CKM_SHA384: hsize = SHA3_HASH_SIZE; break; case CKM_SHA512: hsize = SHA5_HASH_SIZE; break; default: return CKR_MECHANISM_INVALID; } if (length_only == TRUE) { *out_data_len = hsize; return CKR_OK; } if (*out_data_len < hsize) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (ctx->context == NULL) return CKR_HOST_MEMORY; if (token_specific.t_sha != NULL) return token_specific.t_sha(ctx, in_data, in_data_len, out_data, out_data_len); else { if (ctx->mech.mechanism == CKM_SHA_1) return sw_sha1_hash(ctx, in_data, in_data_len, out_data, out_data_len); else return CKR_MECHANISM_INVALID; } } // // CK_RV sha_hash_update(SESSION *sess, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { /* if no data to hash, just return */ if (!in_data_len) return CKR_OK; if (token_specific.t_sha_update != NULL) return token_specific.t_sha_update(ctx, in_data, in_data_len); else { if (ctx->mech.mechanism == CKM_SHA_1) { shaUpdate((SHA1_CONTEXT *)ctx->context, in_data, in_data_len); return CKR_OK; } else return CKR_MECHANISM_INVALID; } } CK_RV sha_hash_final(SESSION *sess, CK_BYTE length_only, DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len) { CK_ULONG hsize; if (!out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } switch(ctx->mech.mechanism) { case CKM_SHA_1: hsize = SHA1_HASH_SIZE; break; case CKM_SHA256: hsize = SHA2_HASH_SIZE; break; case CKM_SHA384: hsize = SHA3_HASH_SIZE; break; case CKM_SHA512: hsize = SHA5_HASH_SIZE; break; default: return CKR_MECHANISM_INVALID; } if (length_only == TRUE) { *out_data_len = hsize; return CKR_OK; } if (*out_data_len < hsize) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_sha_final != NULL) return token_specific.t_sha_final(ctx, out_data, out_data_len); else { if (ctx->mech.mechanism == CKM_SHA_1) { shaFinal((SHA1_CONTEXT *)ctx->context, out_data); *out_data_len = hsize; return CKR_OK; } else return CKR_MECHANISM_INVALID; } } // this routine gets called for two mechanisms actually: // CKM_SHA_1_HMAC // CKM_SHA_1_HMAC_GENERAL // CK_RV sha1_hmac_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_BYTE hash[SHA1_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[SHA1_BLOCK_SIZE]; CK_BYTE k_opad[SHA1_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return CKR_OK; } } else hmac_len = SHA1_HASH_SIZE; if (length_only == TRUE) { *out_data_len = hmac_len; return CKR_OK; } if (token_specific.t_hmac_sign != NULL) return token_specific.t_hmac_sign(sess, in_data, in_data_len, out_data, out_data_len); /* Do manual hmac if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else key_bytes = attr->ulValueLen; // build (K XOR ipad), (K XOR opad) // if (key_bytes > SHA1_BLOCK_SIZE) { digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest(sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); for (i=0; i < hash_len; i++) { k_ipad[i] = hash[i] ^ 0x36; k_opad[i] = hash[i] ^ 0x5C; } memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - i); memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - i); } else { CK_BYTE *key = attr->pValue; for (i=0; i < key_bytes; i++) { k_ipad[i] = key[i] ^ 0x36; k_opad[i] = key[i] ^ 0x5C; } memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - key_bytes); memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - key_bytes); } digest_mech.mechanism = CKM_SHA_1; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, k_ipad, SHA1_BLOCK_SIZE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, in_data, in_data_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final(sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); // outer hash // rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, k_opad, SHA1_BLOCK_SIZE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, hash, hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final(sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memcpy(out_data, hash, hmac_len); *out_data_len = hmac_len; return CKR_OK; } /** This routine gets called for two mechanisms actually: * CKM_SHA256_HMAC * CKM_SHA256_HMAC_GENERAL */ CK_RV sha2_hmac_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_BYTE hash[SHA2_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[SHA2_BLOCK_SIZE]; CK_BYTE k_opad[SHA2_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_SHA256_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return CKR_OK; } } else hmac_len = SHA2_HASH_SIZE; if (length_only == TRUE) { *out_data_len = hmac_len; return CKR_OK; } if (token_specific.t_hmac_sign != NULL) return token_specific.t_hmac_sign(sess, in_data, in_data_len, out_data, out_data_len); /* Do manual hmac if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else key_bytes = attr->ulValueLen; // build (K XOR ipad), (K XOR opad) // if (key_bytes > SHA2_BLOCK_SIZE) { digest_mech.mechanism = CKM_SHA256; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest(sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); for (i=0; i < hash_len; i++) { k_ipad[i] = hash[i] ^ 0x36; k_opad[i] = hash[i] ^ 0x5C; } memset(&k_ipad[i], 0x36, SHA2_BLOCK_SIZE - i); memset(&k_opad[i], 0x5C, SHA2_BLOCK_SIZE - i); } else { CK_BYTE *key = attr->pValue; for (i=0; i < key_bytes; i++) { k_ipad[i] = key[i] ^ 0x36; k_opad[i] = key[i] ^ 0x5C; } memset(&k_ipad[i], 0x36, SHA2_BLOCK_SIZE - key_bytes); memset(&k_opad[i], 0x5C, SHA2_BLOCK_SIZE - key_bytes); } digest_mech.mechanism = CKM_SHA256; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, k_ipad, SHA2_BLOCK_SIZE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, in_data, in_data_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final(sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); // outer hash // rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, k_opad, SHA2_BLOCK_SIZE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, hash, hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final(sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memcpy(out_data, hash, hmac_len); *out_data_len = hmac_len; return CKR_OK; } /** This routine gets called for two mechanisms actually: * CKM_SHA384_HMAC * CKM_SHA384_HMAC_GENERAL */ CK_RV sha3_hmac_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_BYTE hash[SHA3_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[SHA3_BLOCK_SIZE]; CK_BYTE k_opad[SHA3_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_SHA384_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return CKR_OK; } } else hmac_len = SHA3_HASH_SIZE; if (length_only == TRUE) { *out_data_len = hmac_len; return CKR_OK; } if (token_specific.t_hmac_sign != NULL) return token_specific.t_hmac_sign(sess, in_data, in_data_len, out_data, out_data_len); /* Do manual hmac if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else key_bytes = attr->ulValueLen; // build (K XOR ipad), (K XOR opad) // if (key_bytes > SHA3_BLOCK_SIZE) { digest_mech.mechanism = CKM_SHA384; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest(sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); for (i=0; i < hash_len; i++) { k_ipad[i] = hash[i] ^ 0x36; k_opad[i] = hash[i] ^ 0x5C; } memset(&k_ipad[i], 0x36, SHA3_BLOCK_SIZE - i); memset(&k_opad[i], 0x5C, SHA3_BLOCK_SIZE - i); } else { CK_BYTE *key = attr->pValue; for (i=0; i < key_bytes; i++) { k_ipad[i] = key[i] ^ 0x36; k_opad[i] = key[i] ^ 0x5C; } memset(&k_ipad[i], 0x36, SHA3_BLOCK_SIZE - key_bytes); memset(&k_opad[i], 0x5C, SHA3_BLOCK_SIZE - key_bytes); } digest_mech.mechanism = CKM_SHA384; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, k_ipad, SHA3_BLOCK_SIZE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, in_data, in_data_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final(sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); // outer hash // rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, k_opad, SHA3_BLOCK_SIZE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, hash, hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final(sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memcpy(out_data, hash, hmac_len); *out_data_len = hmac_len; return CKR_OK; } /** This routine gets called for two mechanisms actually: * CKM_SHA512_HMAC * CKM_SHA512_HMAC_GENERAL */ CK_RV sha5_hmac_sign(SESSION *sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_BYTE hash[SHA5_HASH_SIZE]; DIGEST_CONTEXT digest_ctx; CK_MECHANISM digest_mech; CK_BYTE k_ipad[SHA5_BLOCK_SIZE]; CK_BYTE k_opad[SHA5_BLOCK_SIZE]; CK_ULONG key_bytes, hash_len, hmac_len; CK_ULONG i; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.mechanism == CKM_SHA512_HMAC_GENERAL) { hmac_len = *(CK_ULONG *)ctx->mech.pParameter; if (hmac_len == 0) { *out_data_len = 0; return CKR_OK; } } else hmac_len = SHA5_HASH_SIZE; if (length_only == TRUE) { *out_data_len = hmac_len; return CKR_OK; } if (token_specific.t_hmac_sign != NULL) return token_specific.t_hmac_sign(sess, in_data, in_data_len, out_data, out_data_len); /* Do manual hmac if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("Failed to acquire key from specified handle"); if (rc == CKR_OBJECT_HANDLE_INVALID) return CKR_KEY_HANDLE_INVALID; else return rc; } rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE in the template\n"); return CKR_FUNCTION_FAILED; } else key_bytes = attr->ulValueLen; // build (K XOR ipad), (K XOR opad) // if (key_bytes > SHA5_BLOCK_SIZE) { digest_mech.mechanism = CKM_SHA512; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest(sess, FALSE, &digest_ctx, attr->pValue, attr->ulValueLen, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Digest failed.\n"); return rc; } memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT)); for (i=0; i < hash_len; i++) { k_ipad[i] = hash[i] ^ 0x36; k_opad[i] = hash[i] ^ 0x5C; } memset(&k_ipad[i], 0x36, SHA5_BLOCK_SIZE - i); memset(&k_opad[i], 0x5C, SHA5_BLOCK_SIZE - i); } else { CK_BYTE *key = attr->pValue; for (i=0; i < key_bytes; i++) { k_ipad[i] = key[i] ^ 0x36; k_opad[i] = key[i] ^ 0x5C; } memset(&k_ipad[i], 0x36, SHA5_BLOCK_SIZE - key_bytes); memset(&k_opad[i], 0x5C, SHA5_BLOCK_SIZE - key_bytes); } digest_mech.mechanism = CKM_SHA512; digest_mech.ulParameterLen = 0; digest_mech.pParameter = NULL; // inner hash // rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, k_ipad, SHA5_BLOCK_SIZE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, in_data, in_data_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final(sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } if (token_specific.t_hmac_sign != NULL) return token_specific.t_hmac_sign(sess, in_data, in_data_len, out_data, out_data_len); /* Do manual hmac if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ memset( &digest_ctx, 0x0, sizeof(DIGEST_CONTEXT) ); // outer hash // rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Init failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, k_opad, SHA5_BLOCK_SIZE); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } rc = digest_mgr_digest_update(sess, &digest_ctx, hash, hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Update failed.\n"); return rc; } hash_len = sizeof(hash); rc = digest_mgr_digest_final(sess, FALSE, &digest_ctx, hash, &hash_len); if (rc != CKR_OK) { TRACE_DEVEL("Digest Mgr Final failed.\n"); return rc; } memcpy(out_data, hash, hmac_len); *out_data_len = hmac_len; return CKR_OK; } CK_RV sha1_hmac_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_BYTE hmac[SHA1_HASH_SIZE]; SIGN_VERIFY_CONTEXT hmac_ctx; CK_ULONG hmac_len, len; CK_RV rc; if (!sess || !ctx || !in_data || !signature) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (token_specific.t_hmac_verify != NULL) return token_specific.t_hmac_verify(sess, in_data, in_data_len, signature, sig_len); /* Do manual hmac verify if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) hmac_len = *(CK_ULONG *)ctx->mech.pParameter; else hmac_len = SHA1_HASH_SIZE; memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); rc = sign_mgr_init(sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } len = sizeof(hmac); rc = sign_mgr_sign(sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Sign failed.\n"); goto done; } if ((len != hmac_len) || (len != sig_len)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); rc = CKR_SIGNATURE_LEN_RANGE; goto done; } if (memcmp(hmac, signature, hmac_len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rc = CKR_SIGNATURE_INVALID; } done: sign_mgr_cleanup(&hmac_ctx); return rc; } CK_RV sha2_hmac_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_BYTE hmac[SHA2_HASH_SIZE]; SIGN_VERIFY_CONTEXT hmac_ctx; CK_ULONG hmac_len, len; CK_RV rc; if (!sess || !ctx || !in_data || !signature) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (token_specific.t_hmac_verify != NULL) return token_specific.t_hmac_verify(sess, in_data, in_data_len, signature, sig_len); /* Do manual hmac verify if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ if (ctx->mech.mechanism == CKM_SHA256_HMAC_GENERAL) hmac_len = *(CK_ULONG *)ctx->mech.pParameter; else hmac_len = SHA2_HASH_SIZE; memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); rc = sign_mgr_init(sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } len = sizeof(hmac); rc = sign_mgr_sign(sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Sign failed.\n"); goto done; } if ((len != hmac_len) || (len != sig_len)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); rc = CKR_SIGNATURE_LEN_RANGE; goto done; } if (memcmp(hmac, signature, hmac_len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rc = CKR_SIGNATURE_INVALID; } done: sign_mgr_cleanup(&hmac_ctx); return rc; } CK_RV sha3_hmac_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_BYTE hmac[SHA3_HASH_SIZE]; SIGN_VERIFY_CONTEXT hmac_ctx; CK_ULONG hmac_len, len; CK_RV rc; if (!sess || !ctx || !in_data || !signature) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (token_specific.t_hmac_verify != NULL) return token_specific.t_hmac_verify(sess, in_data, in_data_len, signature, sig_len); /* Do manual hmac verify if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ if (ctx->mech.mechanism == CKM_SHA384_HMAC_GENERAL) hmac_len = *(CK_ULONG *)ctx->mech.pParameter; else hmac_len = SHA3_HASH_SIZE; memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); rc = sign_mgr_init(sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } len = sizeof(hmac); rc = sign_mgr_sign(sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Sign failed.\n"); goto done; } if ((len != hmac_len) || (len != sig_len)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); rc = CKR_SIGNATURE_LEN_RANGE; goto done; } if (memcmp(hmac, signature, hmac_len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rc = CKR_SIGNATURE_INVALID; } done: sign_mgr_cleanup(&hmac_ctx); return rc; } CK_RV sha5_hmac_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_BYTE hmac[SHA5_HASH_SIZE]; SIGN_VERIFY_CONTEXT hmac_ctx; CK_ULONG hmac_len, len; CK_RV rc; if (!sess || !ctx || !in_data || !signature) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (token_specific.t_hmac_verify != NULL) return token_specific.t_hmac_verify(sess, in_data, in_data_len, signature, sig_len); /* Do manual hmac verify if token doesn't have an hmac crypto call. * Secure tokens should not do manual hmac. */ if (ctx->mech.mechanism == CKM_SHA512_HMAC_GENERAL) hmac_len = *(CK_ULONG *)ctx->mech.pParameter; else hmac_len = SHA5_HASH_SIZE; memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT)); rc = sign_mgr_init(sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Init failed.\n"); goto done; } len = sizeof(hmac); rc = sign_mgr_sign(sess, FALSE, &hmac_ctx, in_data, in_data_len, hmac, &len); if (rc != CKR_OK) { TRACE_DEVEL("Sign Mgr Sign failed.\n"); goto done; } if ((len != hmac_len) || (len != sig_len)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); rc = CKR_SIGNATURE_LEN_RANGE; goto done; } if (memcmp(hmac, signature, hmac_len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rc = CKR_SIGNATURE_INVALID; } done: sign_mgr_cleanup(&hmac_ctx); return rc; } CK_RV sha_init(SESSION *sess, DIGEST_CONTEXT *ctx, CK_MECHANISM *mech) { if (token_specific.t_sha_init != NULL) return token_specific.t_sha_init(ctx, mech); else { /* For current tokens, continue legacy of using software * implemented SHA-1 if the token does not have its own * SHA-1 implementation. * Future tokens' crypto should be its own so that * opencryptoki is not responsible for crypto. If token * does not have SHA-1, then should be mechanism not * supported. JML */ if (mech->mechanism == CKM_SHA_1) { sw_sha1_init(ctx); return CKR_OK; } else return CKR_MECHANISM_INVALID; } } CK_RV hmac_sign_init(SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE hkey) { if (token_specific.t_hmac_sign_init != NULL) return token_specific.t_hmac_sign_init(sess, mech, hkey); else /* Return ok with the intention that the local hmac * implementation will get used instead. * For those tokens not supporting HMAC at all, * will need to return CKR_MECHANISM_INVALID. */ return CKR_OK; } CK_RV hmac_sign_update(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len) { SIGN_VERIFY_CONTEXT *ctx = &sess->sign_ctx; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (token_specific.t_hmac_sign_update != NULL) return token_specific.t_hmac_sign_update(sess, in_data, in_data_len); else { TRACE_ERROR("hmac-update is not supported\n"); return CKR_MECHANISM_INVALID; } } CK_RV hmac_sign_final(SESSION *sess, CK_BYTE *signature, CK_ULONG *sig_len) { SIGN_VERIFY_CONTEXT *ctx = &sess->sign_ctx; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (token_specific.t_hmac_sign_final != NULL) return token_specific.t_hmac_sign_final(sess, signature, sig_len); else { TRACE_ERROR("hmac-final is not supported\n"); return CKR_MECHANISM_INVALID; } } CK_RV hmac_verify_init(SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE hkey) { if (token_specific.t_hmac_verify_init != NULL) return token_specific.t_hmac_verify_init(sess, mech, hkey); else /* Return ok with the intention that the local hmac * implementation will get used instead. * For those tokens not supporting HMAC at all, * will need to return CKR_MECHANISM_INVALID. */ return CKR_OK; } CK_RV hmac_verify_update(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len) { SIGN_VERIFY_CONTEXT *ctx = &sess->sign_ctx; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (token_specific.t_hmac_verify_update != NULL) return token_specific.t_hmac_verify_update(sess, in_data, in_data_len); else { TRACE_ERROR("hmac-update is not supported\n"); return CKR_MECHANISM_INVALID; } } CK_RV hmac_verify_final(SESSION *sess, CK_BYTE *signature, CK_ULONG sig_len) { SIGN_VERIFY_CONTEXT *ctx = &sess->sign_ctx; if (!sess || ! ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (token_specific.t_hmac_verify_final != NULL) return token_specific.t_hmac_verify_final(sess, signature, sig_len); else { TRACE_ERROR("hmac-final is not supported\n"); return CKR_MECHANISM_INVALID; } } CK_RV ckm_generic_secret_key_gen(TEMPLATE *tmpl) { if (token_specific.t_generic_secret_key_gen == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } else return token_specific.t_generic_secret_key_gen(tmpl); } opencryptoki+dfsg/usr/lib/pkcs11/common/trace.c0000644000175000017500000005412112630407154020515 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2015 */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" pthread_mutex_t tlmtx = PTHREAD_MUTEX_INITIALIZER; struct trace_handle_t trace; static const char *ock_err_msg[] = { "Malloc Failed", /*ERR_HOST_MEMORY*/ "Slot Invalid", /*ERR_SLOT_ID_INVALID*/ "General Error", /*ERR_GENERAL_ERROR*/ "Function Failed", /*ERR_FUNCTION_FAILED*/ "Bad Arguments", /*ERR_ARGUMENTS_BAD*/ "No Event", /*ERR_NO_EVENT */ "Attribute Read Only", /*ERR_ATTRIBUTE_READ_ONLY*/ "Attribute Sensitive", /*ERR_ATTRIBUTE_SENSITIVE*/ "Attribute Type Invalid", /*ERR_ATTRIBUTE_TYPE_INVALID*/ "Attribute Value Invalid", /*ERR_ATTRIBUTE_VALUE_INVALID*/ "Data Invalid", /*ERR_DATA_INVALID */ "Data Length out of Range", /*ERR_DATA_LEN_RANGE*/ "Device Error", /*ERR_DEVICE_ERROR*/ "Device does not have Sufficient Memory", /*ERR_DEVICE_MEMORY*/ "Device Removed", /*ERR_DEVICE_REMOVED*/ "Encrypted Data Invalid", /*ERR_ENCRYPTED_DATA_INVALID */ "Encrypted Data Length out of Range", /*ERR_ENCRYPTED_DATA_LEN_RANGE*/ "Function Cancelled", /*ERR_FUNCTION_CANCELED*/ "Function Not Parallel", /*ERR_FUNCTION_NOT_PARALLEL*/ "Function Not Supported", /*ERR_FUNCTION_NOT_SUPPORTED*/ "Key Changed", /*ERR_KEY_CHANGED */ "Key Function Not Permitted", /*ERR_KEY_FUNCTION_NOT_PERMITTED*/ "Key Handle Invalid", /*ERR_KEY_HANDLE_INVALID*/ "Key Indigestible", /*ERR_KEY_INDIGESTIBLE*/ "Key Needed", /*ERR_KEY_NEEDED*/ "Key Not Needed", /*ERR_KEY_NOT_NEEDED */ "Key Not Wrappable", /*ERR_KEY_NOT_WRAPPABLE*/ "Key Size out of Range", /*ERR_KEY_SIZE_RANGE*/ "Key Type Inconsistent", /*ERR_KEY_TYPE_INCONSISTENT*/ "Key Unextractable", /*ERR_KEY_UNEXTRACTABLE*/ "Mechanism Invalid", /*ERR_MECHANISM_INVALID */ "Mechanism Param Invalid", /*ERR_MECHANISM_PARAM_INVALID*/ "Object Handle Invalid", /*ERR_OBJECT_HANDLE_INVALID*/ "Operation Active", /*ERR_OPERATION_ACTIVE*/ "Operation Not Initialized", /*ERR_OPERATION_NOT_INITIALIZED*/ "Pin Incorrect", /*ERR_PIN_INCORRECT */ "Pin Invalid", /*ERR_PIN_INVALID*/ "Pin Length out of Range", /*ERR_PIN_LEN_RANGE*/ "Pin Expired", /*ERR_PIN_EXPIRED*/ "Pin Locked", /*ERR_PIN_LOCKED*/ "Session Closed", /*ERR_SESSION_CLOSED */ "Session Count", /*ERR_SESSION_COUNT*/ "Session Handle Invalid", /*ERR_SESSION_HANDLE_INVALID*/ "Parallel Session Not Supported", /*ERR_SESSION_PARALLEL_NOT_SUPPORTED*/ "Session Read Only", /*ERR_SESSION_READ_ONLY*/ "Session Exists", /*ERR_SESSION_EXISTS */ "Session Read only Exists", /*ERR_SESSION_READ_ONLY_EXISTS*/ "Session Read Write Exists", /*ERR_SESSION_READ_WRITE_SO_EXISTS*/ "Signature Invalid", /*ERR_SIGNATURE_INVALID*/ "Signature Length out of Range", /*ERR_SIGNATURE_LEN_RANGE*/ "Template Incomplete", /*ERR_TEMPLATE_INCOMPLETE */ "Template Inconsistent", /*ERR_TEMPLATE_INCONSISTENT*/ "Token Not Present", /*ERR_TOKEN_NOT_PRESENT*/ "Token Not Recognized", /*ERR_TOKEN_NOT_RECOGNIZED*/ "Token Write Protected", /*ERR_TOKEN_WRITE_PROTECTED*/ "Unwrapping Key Handle Invalid", /*ERR_UNWRAPPING_KEY_HANDLE_INVALID*/ "Unwrapping Key Size Range Invalid", /*ERR_UNWRAPPING_KEY_SIZE_RANGE*/ "Unwrapping Key Type Inconsistent", /*ERR_UNWRAPPING_KEY_TYPE_INCONSISTENT*/ "User Already Logged In", /*ERR_USER_ALREADY_LOGGED_IN*/ "User Not Logged In", /*ERR_USER_NOT_LOGGED_IN*/ "User PIN Not Initialized", /*ERR_USER_PIN_NOT_INITIALIZED */ "User Type Invalid", /*ERR_USER_TYPE_INVALID*/ "Another User Already Logged In", /*ERR_USER_ANOTHER_ALREADY_LOGGED_IN*/ "Too Many User Types", /*ERR_USER_TOO_MANY_TYPES*/ "Wrapped Key Invalid", /*ERR_WRAPPED_KEY_INVALID*/ "Wrapped Key Length Invalid", /*ERR_WRAPPED_KEY_LEN_RANGE*/ "Wrapping Key Handle Invalid", /*ERR_WRAPPING_KEY_HANDLE_INVALID*/ "Wrapping Key Size out of Range", /*ERR_WRAPPING_KEY_SIZE_RANGE*/ "Wrapping Key Type Inconsistent", /*ERR_WRAPPING_KEY_TYPE_INCONSISTENT*/ "Random Seed Not Supported", /*ERR_RANDOM_SEED_NOT_SUPPORTED*/ "Domain Parameter Invalid", /*ERR_DOMAIN_PARAMS_INVALID*/ "Buffer Too Small", /*ERR_BUFFER_TOO_SMALL */ "Saved State Invalid", /*ERR_SAVED_STATE_INVALID*/ "Information Sensitive", /*ERR_INFORMATION_SENSITIVE*/ "State Unsaveable", /*ERR_STATE_UNSAVEABLE*/ "API not initialized", /*ERR_CRYPTOKI_NOT_INITIALIZED*/ "API already Initialized", /*ERR_CRYPTOKI_ALREADY_INITIALIZED*/ "Mutex Invalid", /*ERR_MUTEX_BAD*/ "Mutex was not locked", /*ERR_MUTEX_NOT_LOCKED*/ }; void set_trace(struct trace_handle_t t_handle) { trace.fd = t_handle.fd; trace.level = t_handle.level; } void trace_finalize(void) { if (trace.fd) close(trace.fd); trace.fd = -1; trace.level = 0; } CK_RV trace_initialize(void) { char *opt = NULL; char *end; long int num; struct group *grp; char tracefile[PATH_MAX]; /* initialize the trace values */ trace.level = 0; trace.fd = -1; opt = getenv("OPENCRYPTOKI_TRACE_LEVEL"); if (!opt) return(CKR_FUNCTION_FAILED); num = strtol(opt, &end, 10); if (*end) { OCK_SYSLOG(LOG_WARNING, "OPENCRYPTOKI_TRACE_LEVEL '%s' is " "invalid. Tracing disabled.", opt); return(CKR_FUNCTION_FAILED); } switch(num) { case TRACE_LEVEL_NONE: return CKR_OK; case TRACE_LEVEL_ERROR: case TRACE_LEVEL_WARNING: case TRACE_LEVEL_INFO: case TRACE_LEVEL_DEVEL: #ifdef DEBUG case TRACE_LEVEL_DEBUG: #endif trace.level = num; break; default : OCK_SYSLOG(LOG_WARNING, "Trace level %ld is out of range. " "Tracing disabled.", num); return(CKR_FUNCTION_FAILED); } grp = getgrnam("pkcs11"); if (grp == NULL) { OCK_SYSLOG(LOG_ERR, "getgrnam(pkcs11) failed: %s." "Tracing is disabled.\n", strerror(errno)); goto error; } /* open trace file */ snprintf(tracefile, sizeof(tracefile), "/%s/%s.%d", OCK_LOGDIR, "trace", getpid()); trace.fd = open(tracefile, O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP); if (trace.fd < 0) { OCK_SYSLOG(LOG_WARNING, "open(%s) failed: %s. Tracing disabled.\n", tracefile, strerror(errno)); goto error; } /* set pkcs11 group permission on tracefile */ if (fchown(trace.fd, -1, grp->gr_gid) == -1) { OCK_SYSLOG(LOG_ERR, "fchown(%s,-1,pkcs11) failed: %s." "Tracing is disabled.\n", tracefile, strerror(errno)); goto error; } return(CKR_OK); error: trace.level = 0; trace.fd = -1; return(CKR_FUNCTION_FAILED); } void ock_traceit(trace_level_t level, const char *fmt, ...) { va_list ap; time_t t; struct tm *tm; char buf[1024]; char *pbuf; int buflen, len; if (trace.fd < 0) return; if (level <= trace.level) { pbuf = buf; buflen = sizeof(buf); /* add the current time */ t = time(0); tm = localtime(&t); len = strftime(pbuf, buflen, "%m/%d/%Y %H:%M:%S ", tm); pbuf +=len; buflen -= len; /* add the current time */ /* add the format */ va_start(ap, fmt); vsnprintf(pbuf, buflen, fmt, ap); va_end(ap); /* serialize appends to the file */ pthread_mutex_lock(&tlmtx); write(trace.fd, buf, strlen(buf)); pthread_mutex_unlock(&tlmtx); } } const char *ock_err(int num) { if ( num < 0 || num > ERR_MAX) num = ERR_MAX; return ock_err_msg[num]; } opencryptoki+dfsg/usr/lib/pkcs11/common/mech_aes.c0000644000175000017500000031776212630407154021200 0ustar xnoxxnox// /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ // File: mech_aes.c // // Mechanisms for AES // #include // for memcmp() et al #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "trace.h" // // CK_RV aes_ecb_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (in_data_len % AES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_aes_ecb_encrypt(in_data, in_data_len, out_data, out_data_len, key); } // // CK_RV aes_ecb_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES3_ECB requires the input data to be an integral // multiple of the block size // if (in_data_len % AES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_aes_ecb_decrypt(in_data, in_data_len, out_data, out_data_len, key); } // // CK_RV aes_cbc_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES3_CBC requires the input data to be an integral // multiple of the block size // if (in_data_len % AES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_aes_cbc_encrypt(in_data, in_data_len, out_data, out_data_len, ctx->mech.pParameter, key); } // // CK_RV aes_cbc_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // CKM_DES3_CBC requires the input data to be an integral // multiple of the block size // if (in_data_len % AES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } return ckm_aes_cbc_decrypt(in_data, in_data_len, out_data, out_data_len, ctx->mech.pParameter, key); } // // CK_RV aes_cbc_pad_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_BYTE *clear = NULL; CK_ULONG padded_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // DES3-CBC-PAD has no input length requirements // rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // compute the output length, accounting for padding // padded_len = AES_BLOCK_SIZE * (in_data_len / AES_BLOCK_SIZE + 1); if (length_only == TRUE) { *out_data_len = padded_len; return CKR_OK; } if (*out_data_len < padded_len) { *out_data_len = padded_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } clear = (CK_BYTE *)malloc( padded_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy( clear, in_data, in_data_len ); add_pkcs_padding( clear + in_data_len, AES_BLOCK_SIZE, in_data_len, padded_len ); rc = ckm_aes_cbc_encrypt(clear, padded_len, out_data, out_data_len, ctx->mech.pParameter, key); free( clear ); return rc; } // // CK_RV aes_cbc_pad_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { OBJECT *key = NULL; CK_BYTE *clear = NULL; CK_ULONG padded_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // // no need to validate the input length since we'll pad as necessary // rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // we're decrypting so even with CBC-PAD, we should have an integral // number of block to decrypt // if (in_data_len % AES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } // the amount of cleartext after stripping the padding will actually be less // than the input bytes... // padded_len = in_data_len; if (length_only == TRUE) { *out_data_len = padded_len; return CKR_OK; } clear = (CK_BYTE *)malloc( padded_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = ckm_aes_cbc_decrypt(in_data, in_data_len, clear, &padded_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { strip_pkcs_padding( clear, padded_len, out_data_len ); memcpy( out_data, clear, *out_data_len ); } free( clear ); return rc; } // // CK_RV aes_ctr_encrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key = NULL; CK_RV rc; CK_AES_CTR_PARAMS *aesctr = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (in_data_len % AES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } aesctr = (CK_AES_CTR_PARAMS *)ctx->mech.pParameter; return ckm_aes_ctr_encrypt(in_data, in_data_len, out_data, out_data_len, (CK_BYTE *)aesctr->cb, (CK_ULONG)aesctr->ulCounterBits, key); } // // CK_RV aes_ctr_decrypt( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key = NULL; CK_RV rc; CK_AES_CTR_PARAMS *aesctr = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (in_data_len % AES_BLOCK_SIZE != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len) { *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } aesctr = (CK_AES_CTR_PARAMS *)ctx->mech.pParameter; return ckm_aes_ctr_decrypt(in_data, in_data_len, out_data, out_data_len, (CK_BYTE *)aesctr->cb, (CK_ULONG)aesctr->ulCounterBits, key); } // // CK_RV aes_ecb_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad arguments\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % AES_BLOCK_SIZE); out_len = (total - remain); // should always be at least 1 block if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); rc = ckm_aes_ecb_encrypt(clear, out_len, out_data, out_data_len, key); if (rc == CKR_OK) { *out_data_len = out_len; // update the context buffer. we already used the buffer's current // contents so we completely overwrite it // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV aes_ecb_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % AES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_aes_ecb_decrypt(cipher, out_len, out_data, out_data_len, key); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV aes_cbc_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = (total % AES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); rc = ckm_aes_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { *out_data_len = out_len; // the new init_v is the last encrypted data block // memcpy( ctx->mech.pParameter, out_data + (*out_data_len - AES_BLOCK_SIZE), AES_BLOCK_SIZE ); // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV aes_cbc_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = context->len + in_data_len; if (total < AES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block // remain = total % AES_BLOCK_SIZE; out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_aes_cbc_decrypt(cipher, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { *out_data_len = out_len; // the new init_v is the last input data block // memcpy( ctx->mech.pParameter, cipher + (out_len - AES_BLOCK_SIZE), AES_BLOCK_SIZE ); // copy the remaining 'new' input data to the context buffer // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV aes_cbc_pad_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); // note, this is subtly different from the other encrypt update routines // if (total <= AES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { remain = (total % AES_BLOCK_SIZE); out_len = total - remain; // out_len is a multiple of DES_BLOCK_SIZE if (remain == 0) { remain = AES_BLOCK_SIZE; out_len -= AES_BLOCK_SIZE; } if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } // at this point, we should have: // 1) remain != 0 // 2) out_len != 0 // rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // clear = (CK_BYTE *)malloc( out_len ); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first // memcpy( clear, context->data, context->len ); memcpy( clear + context->len, in_data, out_len - context->len ); // // we don't do padding during the update // rc = ckm_aes_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { // the new init_v is the last encrypted data block // memcpy( ctx->mech.pParameter, out_data + (*out_data_len - AES_BLOCK_SIZE), AES_BLOCK_SIZE ); // copy the remaining 'new' input data to the temporary space // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV aes_cbc_pad_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); // note, this is subtly different from the other decrypt update routines // if (total <= AES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block + 1 byte // remain = total % AES_BLOCK_SIZE; out_len = total - remain; if (remain == 0) { remain = AES_BLOCK_SIZE; out_len -= AES_BLOCK_SIZE; } if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } // at this point, we should have: // 1) remain != 0 // 2) out_len != 0 // rc = object_mgr_find_in_map_nocache( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } // these buffers need to be longword aligned // cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first // memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = ckm_aes_cbc_decrypt(cipher, out_len, out_data, out_data_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { // the new init_v is the last input data block // memcpy( ctx->mech.pParameter, cipher + (out_len - AES_BLOCK_SIZE), AES_BLOCK_SIZE ); // copy the remaining 'new' input data to the temporary space // if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( cipher ); return rc; } } // // CK_RV aes_ctr_encrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; CK_AES_CTR_PARAMS *aesctr = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx -> context; total = (context->len + in_data_len); if( total < AES_BLOCK_SIZE){ if(length_only == FALSE){ memcpy( context->data + context->len, in_data, in_data_len); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we atleast have 1 block remain = (total % AES_BLOCK_SIZE); out_len = total -remain; if (length_only == TRUE){ *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache(ctx->key, &key); if(rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } //these buffers need to be longword aligned clear = (CK_BYTE*) malloc (out_len); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } //copy all the leftover data from the previous encryption operation first memcpy ( clear, context->data, context->len); memcpy ( clear+context->len, in_data, out_len - context->len); aesctr = (CK_AES_CTR_PARAMS *)ctx->mech.pParameter; rc = ckm_aes_ctr_encrypt(clear, out_len, out_data, out_data_len, (CK_BYTE *)aesctr->cb, (CK_ULONG)aesctr->ulCounterBits, key); if (rc == CKR_OK){ *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV aes_ctr_decrypt_update( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT * context = NULL; OBJECT * key = NULL; CK_BYTE * clear = NULL; CK_ULONG total, remain, out_len; CK_RV rc; CK_AES_CTR_PARAMS *aesctr = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx -> context; total = (context->len + in_data_len); if( total < AES_BLOCK_SIZE){ if(length_only == FALSE){ memcpy( context->data + context->len, in_data, in_data_len); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else{ // we atleast have 1 block remain = (total % AES_BLOCK_SIZE); out_len = total -remain; if (length_only == TRUE){ *out_data_len = out_len; return CKR_OK; } rc = object_mgr_find_in_map_nocache(ctx->key, &key); if(rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } //these buffers need to be longword aligned clear = (CK_BYTE*) malloc (out_len); if (!clear){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } //copy all the leftover data from the previous encryption operation first memcpy ( clear, context->data, context->len); memcpy ( clear+context->len, in_data, out_len - context->len); aesctr = (CK_AES_CTR_PARAMS *)ctx->mech.pParameter; rc = ckm_aes_ctr_decrypt(clear, out_len, out_data, out_data_len, (CK_BYTE *)aesctr->cb, (CK_ULONG)aesctr->ulCounterBits, key); if (rc == CKR_OK){ *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } free( clear ); return rc; } } // // CK_RV aes_ecb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (AES_CONTEXT *)ctx->context; // DES3-ECB does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV aes_ecb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (AES_CONTEXT *)ctx->context; // DES3-ECB does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV aes_cbc_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (AES_CONTEXT *)ctx->context; // DES3-CBC does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV aes_cbc_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT *context = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (AES_CONTEXT *)ctx->context; if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV aes_cbc_pad_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT *context = NULL; OBJECT *key = NULL; CK_BYTE clear[2*AES_BLOCK_SIZE]; CK_ULONG out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } context = (AES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate one block of output // if a full block is stored, we generate two blocks of output (one pad block) // if (context->len == AES_BLOCK_SIZE) out_len = 2 * AES_BLOCK_SIZE; else out_len = AES_BLOCK_SIZE; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } else { memcpy( clear, context->data, context->len ); add_pkcs_padding( clear + context->len, AES_BLOCK_SIZE, context->len, out_len ); rc = ckm_aes_cbc_encrypt(clear, out_len, out_data, out_data_len, ctx->mech.pParameter, key); return rc; } } // // CK_RV aes_cbc_pad_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT *context = NULL; OBJECT *key = NULL; CK_BYTE clear[AES_BLOCK_SIZE]; CK_ULONG out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } rc = object_mgr_find_in_map1( ctx->key, &key ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } context = (AES_CONTEXT *)ctx->context; // there had better be a full block in the context buffer // if (context->len != AES_BLOCK_SIZE){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } // we don't know a priori how much data we'll be returning. we won't // know until after we decrypt it and strip the padding. it's possible // that we'll return nothing (the final block might be a padding block). // out_len = AES_BLOCK_SIZE; // upper bound on what we'll return if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } else { rc = ckm_aes_cbc_decrypt(context->data, AES_BLOCK_SIZE, clear, &out_len, ctx->mech.pParameter, key); if (rc == CKR_OK) { strip_pkcs_padding( clear, out_len, &out_len ); if (out_len != 0) memcpy( out_data, clear, out_len ); *out_data_len = out_len; } return rc; } } // // CK_RV aes_ctr_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT *context = NULL; CK_AES_CTR_PARAMS *aesctr = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (AES_CONTEXT *)ctx->context; // DES3-CBC does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } aesctr = (CK_AES_CTR_PARAMS *)ctx->mech.pParameter; //to check that the counter buffer doesnot overflow if ( ((CK_ULONG)aesctr->ulCounterBits) > ((CK_ULONG)aesctr->ulCounterBits+1) ) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } // // CK_RV aes_ctr_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { AES_CONTEXT *context = NULL; CK_AES_CTR_PARAMS *aesctr = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler // if (length_only) context = NULL; context = (AES_CONTEXT *)ctx->context; // DES3-CBC does no padding so there had better not be // any data in the context buffer. if there is it means // that the overall data length was not a multiple of the blocksize // if (context->len != 0){ TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); return CKR_ENCRYPTED_DATA_LEN_RANGE; } aesctr = (CK_AES_CTR_PARAMS *)ctx->mech.pParameter; //to check that the counter buffer doesnot overflow if ( ((CK_ULONG)aesctr->ulCounterBits) > ((CK_ULONG)aesctr->ulCounterBits+1) ) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } *out_data_len = 0; return CKR_OK; } CK_RV aes_ofb_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { CK_ULONG rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_ofb(in_data, in_data_len, out_data, key_obj, ctx->mech.pParameter, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes ofb encrypt failed.\n"); return rc; } CK_RV aes_ofb_encrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { AES_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block remain = (total % AES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } if (*out_data_len < out_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_aes_ofb(cipher, out_len, out_data, key_obj, ctx->mech.pParameter, 1); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific aes ofb encrypt failed.\n"); free( cipher ); return rc; } } CK_RV aes_ofb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT *key_obj = NULL; AES_CONTEXT *context = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate same length of output data // if no data stored, no data can be returned (length zero) if (length_only == TRUE) { *out_data_len = context->len; return CKR_OK; } else { if (context->len == 0) { *out_data_len = 0; return CKR_OK; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_ofb(context->data, context->len, out_data, key_obj, ctx->mech.pParameter, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes ofb encrypt failed.\n"); *out_data_len = context->len; return rc; } } CK_RV aes_ofb_decrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len ) { CK_ULONG rc; OBJECT *key_obj = NULL; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_ofb(in_data, in_data_len, out_data, key_obj, ctx->mech.pParameter, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes ofb decrypt failed.\n"); return rc; } CK_RV aes_ofb_decrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { AES_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block remain = (total % AES_BLOCK_SIZE); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } if (*out_data_len < out_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_aes_ofb(cipher, out_len, out_data, key_obj, ctx->mech.pParameter, 0); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific aes ofb decrypt failed.\n"); free( cipher ); return rc; } } CK_RV aes_ofb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len ) { OBJECT * key_obj = NULL; AES_CONTEXT * context = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } // satisfy the compiler //if (length_only) // context = NULL; context = (AES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate same length of output data // if no data stored, no data can be returned (length zero) if (length_only == TRUE) { *out_data_len = context->len; return CKR_OK; } else { if (context->len == 0) { *out_data_len = 0; return CKR_OK; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_ofb(context->data, context->len, out_data, key_obj, ctx->mech.pParameter, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes ofb decrypt failed.\n"); *out_data_len = context->len; return rc; } } CK_RV aes_cfb_encrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len ) { CK_ULONG rc; OBJECT *key_obj = NULL; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_cfb(in_data, in_data_len, out_data, key_obj, ctx->mech.pParameter, cfb_len, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes cfb encrypt failed.\n"); return rc; } CK_RV aes_cfb_encrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len) { AES_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < cfb_len) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block remain = (total % cfb_len); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } if (*out_data_len < out_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous encryption operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_aes_cfb(cipher, out_len, out_data, key_obj, ctx->mech.pParameter, cfb_len, 1); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific aes cfb encrypt failed.\n"); free( cipher ); return rc; } } CK_RV aes_cfb_encrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG cfb_len) { OBJECT *key_obj = NULL; AES_CONTEXT *context = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate same length of output data // if no data stored, no data can be returned (length zero) if (context->len == 0) { *out_data_len = 0; return CKR_OK; } if (length_only == TRUE) { *out_data_len = context->len; return CKR_OK; } else { rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_cfb(context->data, context->len, out_data, key_obj, ctx->mech.pParameter, cfb_len, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes cfb encrypt failed.\n"); *out_data_len = context->len; return rc; } } CK_RV aes_cfb_decrypt( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len ) { CK_ULONG rc; OBJECT *key_obj = NULL; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len; return CKR_OK; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_cfb(in_data, in_data_len, out_data, key_obj, ctx->mech.pParameter, cfb_len, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes cfb decrypt failed.\n"); return rc; } CK_RV aes_cfb_decrypt_update( SESSION * sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_ULONG cfb_len) { AES_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; CK_RV rc; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < cfb_len) { if (length_only == FALSE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; } *out_data_len = 0; return CKR_OK; } else { // we have at least 1 block remain = (total % cfb_len); out_len = total - remain; if (length_only == TRUE) { *out_data_len = out_len; return CKR_OK; } if (*out_data_len < out_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous decryption operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_aes_cfb(cipher, out_len, out_data, key_obj, ctx->mech.pParameter, cfb_len, 0); if (rc == CKR_OK) { *out_data_len = out_len; // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific aes cfb decrypt failed.\n"); free( cipher ); return rc; } } CK_RV aes_cfb_decrypt_final( SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_ULONG cfb_len) { OBJECT *key_obj = NULL; AES_CONTEXT *context = NULL; CK_RV rc; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_CONTEXT *)ctx->context; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate same length of output data // if no data stored, no data can be returned (length zero) if (context->len == 0) { *out_data_len = 0; return CKR_OK; } if (length_only == TRUE) { *out_data_len = context->len; return CKR_OK; } else { rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_cfb(context->data, context->len, out_data, key_obj, ctx->mech.pParameter, cfb_len, 0); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes cfb decrypt failed.\n"); *out_data_len = context->len; return rc; } } CK_RV aes_mac_sign( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len) { CK_ULONG rc; OBJECT * key_obj = NULL; CK_ULONG mac_len; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (ctx->mech.pParameter) mac_len = *(CK_MAC_GENERAL_PARAMS *)ctx->mech.pParameter; else mac_len = AES_BLOCK_SIZE / 2; if (length_only == TRUE) { *out_data_len = mac_len; return CKR_OK; } if ( (in_data_len % AES_BLOCK_SIZE) != 0) { rc = aes_mac_sign_update(sess, ctx, in_data, in_data_len); if (rc != CKR_OK) return rc; rc = aes_mac_sign_final(sess, length_only, ctx, out_data, out_data_len); return rc; } else { if (*out_data_len < mac_len) { *out_data_len = mac_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_mac(in_data, in_data_len, key_obj, ((AES_DATA_CONTEXT *)ctx->context)->iv); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes mac failed.\n"); memcpy(out_data, ((AES_DATA_CONTEXT *)ctx->context)->iv, mac_len); *out_data_len = mac_len; return rc; } } CK_RV aes_mac_sign_update ( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len ) { CK_ULONG rc; OBJECT * key_obj = NULL; AES_DATA_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_DATA_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; return CKR_OK; } else { // we have at least 1 block remain = (total % AES_BLOCK_SIZE); out_len = total - remain; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous signUpdate operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_aes_mac(cipher, out_len, key_obj, context->iv); if (rc == CKR_OK) { // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific aes mac failed.\n"); free( cipher ); return rc; } } CK_RV aes_mac_sign_final( SESSION * sess, CK_BBOOL length_only, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * out_data, CK_ULONG * out_data_len) { CK_ULONG rc = CKR_OK; CK_ULONG mac_len; AES_DATA_CONTEXT * context = NULL; OBJECT * key_obj = NULL; if (!sess || !ctx || !out_data_len){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_DATA_CONTEXT *)ctx->context; if (ctx->mech.pParameter) mac_len = *(CK_MAC_GENERAL_PARAMS *)ctx->mech.pParameter; else mac_len = AES_BLOCK_SIZE / 2; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate one block of output (with padding) // if no data stored, we are done (take the cipher from previous round) if (length_only == TRUE) { *out_data_len = mac_len; return CKR_OK; } if (context->len > 0) { if (*out_data_len < mac_len) { *out_data_len = mac_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* padding with '00' in case case we didn't reach block size */ memset(context->data + context->len, 0x0, AES_BLOCK_SIZE - context->len); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_mac(context->data, AES_BLOCK_SIZE, key_obj, context->iv); if (rc != CKR_OK) { TRACE_DEVEL("Token Specific aes mac failed.\n"); return rc; } } memcpy(out_data, context->iv, mac_len); *out_data_len = mac_len; return rc; } CK_RV aes_mac_verify( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG out_data_len) { CK_ULONG rc; OBJECT * key_obj = NULL; CK_ULONG mac_len; if (!sess || !ctx || !in_data || !out_data){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if ( (in_data_len % AES_BLOCK_SIZE) != 0) { rc = aes_mac_verify_update(sess, ctx, in_data, in_data_len); if (rc != CKR_OK) return rc; rc = aes_mac_verify_final(sess, ctx, out_data, out_data_len); return rc; } else { if (ctx->mech.pParameter) mac_len = *(CK_MAC_GENERAL_PARAMS *)ctx->mech.pParameter; else mac_len = AES_BLOCK_SIZE / 2; if (out_data_len != mac_len) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_mac(in_data, in_data_len, key_obj, ((AES_DATA_CONTEXT *)ctx->context)->iv); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes mac failed.\n"); if (memcmp( out_data, ((AES_DATA_CONTEXT *)ctx->context)->iv, out_data_len) == 0) { return CKR_OK; } else return CKR_SIGNATURE_INVALID; } } CK_RV aes_mac_verify_update( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * in_data, CK_ULONG in_data_len) { CK_ULONG rc; OBJECT * key_obj = NULL; AES_DATA_CONTEXT * context = NULL; CK_BYTE * cipher = NULL; CK_ULONG total, remain, out_len; if (!sess || !ctx) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_DATA_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (total < AES_BLOCK_SIZE) { memcpy( context->data + context->len, in_data, in_data_len ); context->len += in_data_len; return CKR_OK; } else { // we have at least 1 block remain = (total % AES_BLOCK_SIZE); out_len = total - remain; rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } cipher = (CK_BYTE *)malloc( out_len ); if (!cipher){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // copy any data left over from the previous signUpdate operation first memcpy( cipher, context->data, context->len ); memcpy( cipher + context->len, in_data, out_len - context->len ); rc = token_specific.t_aes_mac(cipher, out_len, key_obj, context->iv); if (rc == CKR_OK) { // copy the remaining 'new' input data to the context buffer if (remain != 0) memcpy( context->data, in_data + (in_data_len - remain), remain ); context->len = remain; } else TRACE_DEVEL("Token specific aes mac failed.\n"); free( cipher ); return rc; } } CK_RV aes_mac_verify_final( SESSION * sess, SIGN_VERIFY_CONTEXT * ctx, CK_BYTE * signature, CK_ULONG signature_len) { CK_ULONG rc; OBJECT * key_obj = NULL; CK_ULONG mac_len; AES_DATA_CONTEXT * context = NULL; if (!sess || !ctx || !signature){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_DATA_CONTEXT *)ctx->context; if (ctx->mech.pParameter) mac_len = *(CK_MAC_GENERAL_PARAMS *)ctx->mech.pParameter; else mac_len = AES_BLOCK_SIZE / 2; // there will never be more than one block in the context buffer // so the amount of output is as follows: // if less than 1 block stored, we generate one block of output (with padding) // if no data stored, we are done (take the cipher from previous round) if (context->len > 0) { if (signature_len != mac_len) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE)); return CKR_SIGNATURE_LEN_RANGE; } /* padding with '00' in case case we didn't reach block size */ memset(context->data + context->len, 0x0, AES_BLOCK_SIZE - context->len); rc = object_mgr_find_in_map1( ctx->key, &key_obj ); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } rc = token_specific.t_aes_mac(context->data, AES_BLOCK_SIZE, key_obj, context->iv); if (rc != CKR_OK) { TRACE_DEVEL("Token specific aes mac failed.\n"); return rc; } } if (memcmp(signature, context->iv, signature_len) == 0) { return CKR_OK; } else return CKR_SIGNATURE_INVALID; } CK_RV aes_gcm_init(SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_MECHANISM *mech, CK_OBJECT_HANDLE key, CK_BYTE direction) { if (token_specific.t_aes_gcm_init == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } return token_specific.t_aes_gcm_init(sess, ctx, mech, key, direction); } CK_RV aes_gcm_encrypt(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { CK_RV rc; CK_GCM_PARAMS *aesgcm = NULL; CK_ULONG tag_data_len; if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } aesgcm = (CK_GCM_PARAMS *)ctx->mech.pParameter; tag_data_len = (aesgcm->ulTagBits + 7) / 8; /* round to full byte */ if (length_only == TRUE) { *out_data_len = in_data_len + tag_data_len; return CKR_OK; } if (*out_data_len < in_data_len + tag_data_len) { *out_data_len = in_data_len + tag_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_aes_gcm == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_gcm(sess, ctx , in_data, in_data_len, out_data, out_data_len, 1); if (rc != CKR_OK) TRACE_ERROR("Token specific aes gcm encrypt failed: %02lx\n", rc); return rc; } CK_RV aes_gcm_encrypt_update(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { AES_GCM_CONTEXT *context = NULL; CK_ULONG total, remain, out_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_GCM_CONTEXT *)ctx->context; total = (context->len + in_data_len); if (length_only) { if (total < AES_BLOCK_SIZE) { *out_data_len = 0; return CKR_OK; } else { remain = (total % AES_BLOCK_SIZE); out_len = total - remain; *out_data_len = out_len; TRACE_DEVEL("Length Only requested (%02ld bytes).\n", *out_data_len); return CKR_OK; } } if (token_specific.t_aes_gcm_update == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_gcm_update(sess, ctx, in_data, in_data_len, out_data, out_data_len, 1); if (rc != CKR_OK) TRACE_ERROR("Token specific AES GCM EncryptUpdate failed: " "%02lx\n", rc); return rc; } CK_RV aes_gcm_encrypt_final(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len) { CK_GCM_PARAMS *aesgcm = NULL; AES_GCM_CONTEXT *context = NULL; CK_ULONG tag_data_len; CK_RV rc = CKR_OK; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_GCM_CONTEXT *)ctx->context; aesgcm = (CK_GCM_PARAMS *)ctx->mech.pParameter; tag_data_len = (aesgcm->ulTagBits + 7) / 8; /* round to full byte */ if (length_only) { if (context->len == 0) { *out_data_len = tag_data_len; } else { *out_data_len = context->len + tag_data_len; } return CKR_OK; } if (*out_data_len < context->len + tag_data_len) { TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_aes_gcm_final == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_gcm_final(sess, ctx, out_data, out_data_len, 1); if (rc != CKR_OK) TRACE_ERROR("Token specific AES GCM EncryptFinal failed: " "%02lx\n", rc); return rc; } CK_RV aes_gcm_decrypt(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { CK_GCM_PARAMS *aesgcm = NULL; CK_ULONG tag_data_len; CK_RV rc; aesgcm = (CK_GCM_PARAMS *)ctx->mech.pParameter; tag_data_len = (aesgcm->ulTagBits + 7) / 8; /* round to full byte */ if (!sess || !ctx || !in_data || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (length_only == TRUE) { *out_data_len = in_data_len - tag_data_len; return CKR_OK; } if (*out_data_len < in_data_len - tag_data_len) { *out_data_len = in_data_len - tag_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_aes_gcm == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_gcm(sess, ctx, in_data, in_data_len, out_data, out_data_len, 0); if (rc != CKR_OK) TRACE_ERROR("Token specific aes gcm decrypt failed.\n"); return rc; } CK_RV aes_gcm_decrypt_update(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { AES_GCM_CONTEXT *context = NULL; CK_GCM_PARAMS *aesgcm = NULL; CK_ULONG total, remain, out_len; CK_ULONG tag_data_len; CK_RV rc; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } /* Be aware that this part of incoming data could be the last chunk, * that means it's tag data, not encrypted plaintext. * Hence we'll keep at least tag data size in the context buffer */ context = (AES_GCM_CONTEXT *)ctx->context; total = (context->len + in_data_len); aesgcm = (CK_GCM_PARAMS *)ctx->mech.pParameter; tag_data_len = (aesgcm->ulTagBits + 7) / 8; /* round to full byte */ if (length_only) { if (total < AES_BLOCK_SIZE + tag_data_len) { *out_data_len = 0; return CKR_OK; } else { remain = ((total - tag_data_len) % AES_BLOCK_SIZE) + tag_data_len; out_len = total - remain; *out_data_len = out_len; TRACE_DEVEL("Length Only requested (%02ld bytes).\n", *out_data_len); return CKR_OK; } } if (token_specific.t_aes_gcm_update == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_gcm_update(sess, ctx, in_data, in_data_len, out_data, out_data_len, 0 ); if (rc != CKR_OK) TRACE_ERROR("Token specific AES GCM DecryptUpdate " "failed: %02lx\n", rc); return rc; } CK_RV aes_gcm_decrypt_final(SESSION *sess, CK_BBOOL length_only, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len) { AES_GCM_CONTEXT *context = NULL; CK_RV rc = CKR_OK; if (!sess || !ctx || !out_data_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } context = (AES_GCM_CONTEXT *)ctx->context; if (length_only) { if (context->len == 0) { *out_data_len = 0; } else { *out_data_len = context->len; } return CKR_OK; } if (token_specific.t_aes_gcm_final == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_gcm_final(sess, ctx, out_data, out_data_len, 0); if (rc != CKR_OK) TRACE_ERROR("Token specific AES GCM DecryptFinal failed: " "%02lx\n", rc); return rc; } // // mechanisms // // // CK_RV ckm_aes_key_gen( TEMPLATE *tmpl ) { CK_ATTRIBUTE * opaque_attr = NULL; CK_ATTRIBUTE * value_attr = NULL; CK_ATTRIBUTE * key_type_attr = NULL; CK_ATTRIBUTE * class_attr = NULL; CK_ATTRIBUTE * local_attr = NULL; CK_ATTRIBUTE * val_len_attr = NULL; CK_BYTE * aes_key = NULL; CK_BYTE dummy_key[AES_KEY_SIZE_256] = { 0, }; CK_ULONG rc; CK_ULONG key_size; CK_ULONG token_keysize; CK_BBOOL found = FALSE; found = template_attribute_find( tmpl, CKA_VALUE_LEN, &val_len_attr ); if (found == FALSE) return CKR_TEMPLATE_INCONSISTENT; key_size = *(CK_ULONG *)val_len_attr->pValue; if (key_size != AES_KEY_SIZE_128 && key_size != AES_KEY_SIZE_192 && key_size != AES_KEY_SIZE_256) { return CKR_ATTRIBUTE_VALUE_INVALID; } if (token_specific.t_aes_key_gen == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (token_specific.token_keysize) token_keysize = token_specific.token_keysize; else token_keysize = key_size; if ((aes_key = (CK_BYTE *)calloc(1,token_keysize)) == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = token_specific.t_aes_key_gen(aes_key, token_keysize, key_size); if (rc != CKR_OK) goto err; /* For secure-key keys put in CKA_IBM_OPAQUE * and put dummy_key in CKA_VALUE. */ if (token_specific.token_keysize) { opaque_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + token_keysize); if (!opaque_attr) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto err; } opaque_attr->type = CKA_IBM_OPAQUE; opaque_attr->ulValueLen = token_keysize; opaque_attr->pValue = (CK_BYTE *)opaque_attr + sizeof(CK_ATTRIBUTE); memcpy(opaque_attr->pValue, aes_key, token_keysize); template_update_attribute(tmpl, opaque_attr); } value_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + key_size ); key_type_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) ); class_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) ); local_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) ); if (!value_attr || !key_type_attr || !class_attr || !local_attr) { if (value_attr) free( value_attr ); if (key_type_attr) free( key_type_attr ); if (class_attr) free( class_attr ); if (local_attr) free( local_attr ); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto err; } value_attr->type = CKA_VALUE; value_attr->ulValueLen = key_size; value_attr->pValue = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE); if (token_specific.token_keysize) memcpy( value_attr->pValue, dummy_key, key_size ); else memcpy( value_attr->pValue, aes_key, key_size ); free(aes_key); key_type_attr->type = CKA_KEY_TYPE; key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE); key_type_attr->pValue = (CK_BYTE *)key_type_attr + sizeof(CK_ATTRIBUTE); *(CK_KEY_TYPE *)key_type_attr->pValue = CKK_AES; class_attr->type = CKA_CLASS; class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS); class_attr->pValue = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE); *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY; local_attr->type = CKA_LOCAL; local_attr->ulValueLen = sizeof(CK_BBOOL); local_attr->pValue = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE); *(CK_BBOOL *)local_attr->pValue = TRUE; template_update_attribute( tmpl, value_attr ); template_update_attribute( tmpl, key_type_attr ); template_update_attribute( tmpl, class_attr ); template_update_attribute( tmpl, local_attr ); return CKR_OK; err: if (aes_key) free(aes_key); return rc; } // // CK_RV ckm_aes_ecb_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_aes_ecb == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_ecb(in_data,in_data_len, out_data,out_data_len, key, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes ecb encrypt failed.\n"); return rc; } // // CK_RV ckm_aes_ecb_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_aes_ecb == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_ecb(in_data,in_data_len, out_data,out_data_len, key, 0); if (rc != CKR_OK) TRACE_DEVEL("token specific aes ecb decrypt failed.\n"); return rc; } // // CK_RV ckm_aes_cbc_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_BYTE * init_v, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !init_v || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_aes_cbc == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_cbc(in_data, in_data_len, out_data,out_data_len, key, init_v, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes cbc encrypt failed.\n"); return rc; } // // CK_RV ckm_aes_cbc_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, CK_ULONG * out_data_len, CK_BYTE * init_v, OBJECT * key ) { CK_ULONG rc; if (!in_data || !out_data || !init_v || !key ){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (token_specific.t_aes_cbc == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_cbc(in_data, in_data_len, out_data, out_data_len, key, init_v,0); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes cbc decrypt failed.\n"); return rc; } // // CK_RV ckm_aes_ctr_encrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *counterblock, CK_ULONG counter_width, OBJECT *key ) { CK_ULONG rc; if (!in_data || !out_data || !counterblock || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (counter_width % 8 != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if (token_specific.t_aes_ctr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_ctr(in_data, in_data_len, out_data, out_data_len, key, counterblock, counter_width, 1); if (rc != CKR_OK) TRACE_DEVEL("Token specific aes ctr encrypt failed.\n"); return rc; } // // CK_RV ckm_aes_ctr_decrypt( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *counterblock, CK_ULONG counter_width, OBJECT *key ) { CK_ULONG rc; if (!in_data || !out_data || !counterblock || !key){ TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (*out_data_len < in_data_len){ *out_data_len = in_data_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } if (counter_width % 8 != 0){ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); return CKR_MECHANISM_PARAM_INVALID; } if (token_specific.t_aes_ctr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } rc = token_specific.t_aes_ctr(in_data, in_data_len, out_data,out_data_len, key, counterblock, counter_width, 0); if (rc != CKR_OK) TRACE_ERROR("Token specific aes ctr decrypt failed.\n"); return rc; } // // CK_RV ckm_aes_wrap_format( CK_BBOOL length_only, CK_BYTE ** data, CK_ULONG * data_len ) { CK_BYTE * ptr = NULL; CK_ULONG len1, len2; len1 = *data_len; // if the input key data isn't a multiple of the blocksize, // we pad with NULLs to the next blocksize multiple. // if (len1 % AES_BLOCK_SIZE != 0) { len2 = AES_BLOCK_SIZE * ((len1 / AES_BLOCK_SIZE) + 1); if (length_only == FALSE) { ptr = (CK_BYTE *)realloc(*data, len2); if (!ptr){ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } else memset( ptr + len1, 0x0, (len2 - len1) ); *data = ptr; *data_len = len2; } } return CKR_OK; } opencryptoki+dfsg/usr/lib/pkcs11/common/new_host.c0000755000175000017500000031203412630407154021250 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "stdll.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "pkcs32.h" #include "trace.h" #include "../api/apiproto.h" /* Declared in obj_mgr.c */ extern pthread_rwlock_t obj_list_rw_mutex; void SC_SetFunctionList(void); CK_ULONG usage_count = 0; /* track DLL usage */ void Fork_Initializer(void) { /* Initialize spinlock. */ XProcLock_Init(); /* Force logout. This cleans out the private session and list * and cleans out the private object map */ session_mgr_logout_all(); /* Clean out the public object map * First parm is no longer used.. */ object_mgr_purge_map((SESSION *)0xFFFF, PUBLIC); object_mgr_purge_map((SESSION *)0xFFFF, PRIVATE); /* This should clear the entire session list out */ session_mgr_close_all_sessions(); /* Clean out the global login state variable * When implemented... Although logout_all should clear this up. */ bt_destroy(&priv_token_obj_btree, object_free); bt_destroy(&publ_token_obj_btree, object_free); /* Need to do something to prevent the shared memory from * having the objects loaded again.... The most likely place * is in the obj_mgr file where the object is added to shared * memory (object_mgr_add_to_shm) a query should be done to * the appropriate object list.... */ } /* verify that the mech specified is in the * mech list for this token... */ CK_RV valid_mech(CK_MECHANISM_PTR m, CK_FLAGS f) { CK_RV rc; CK_MECHANISM_INFO info; if (m && token_specific.t_get_mechanism_info) { memset(&info, 0, sizeof(info)); rc = token_specific.t_get_mechanism_info(m->mechanism, &info); if (rc != CKR_OK || !(info.flags & (f))) return CKR_MECHANISM_INVALID; } return CKR_OK; } /* In an STDLL this is called once for each card in the system * therefore the initialized only flags certain one time things. */ CK_RV ST_Initialize(void **FunctionList, CK_SLOT_ID SlotNumber, char *conf_name, struct trace_handle_t t) { CK_RV rc = CKR_OK; if ((rc = check_user_and_group()) != CKR_OK) return rc; /* assume that the upper API prevents multiple calls of initialize * since that only happens on C_Initialize and that is the * resonsibility of the upper layer.. */ initialized = FALSE; /* So the rest of the code works correctly */ /* If we're not already initialized, grab the mutex and do the * initialization. Check to see if another thread did so while we * were waiting... * * One of the things we do during initialization is create the mutex * for PKCS#11 operations; until we do so, we have to use the native * mutex... */ if (pthread_mutex_lock(&native_mutex)) { rc = CKR_FUNCTION_FAILED; TRACE_ERROR("Failed to lock mutex.\n"); } /* SAB need to call Fork_Initializer here * instead of at the end of the loop... * it may also need to call destroy of the following 3 mutexes.. * it may not matter... */ Fork_Initializer(); /* set trace info */ set_trace(t); MY_CreateMutex(&pkcs_mutex); MY_CreateMutex(&obj_list_mutex); if (pthread_rwlock_init(&obj_list_rw_mutex, NULL)) { TRACE_ERROR("Mutex lock failed.\n"); } MY_CreateMutex(&sess_list_mutex); MY_CreateMutex(&login_mutex); /* Create lockfile */ if (CreateXProcLock() != CKR_OK) { TRACE_ERROR("Process lock failed.\n"); goto done; } init_data_store((char *)PK_DIR); /* Handle global initialization issues first if we have not * been initialized. */ if (initialized == FALSE) { rc = attach_shm(SlotNumber, &global_shm); if (rc != CKR_OK) { TRACE_ERROR("Could not attach to shared memory.\n"); goto done; } nv_token_data = &global_shm->nv_token_data; initialized = TRUE; SC_SetFunctionList(); /* Always call the token_specific_init function.... */ rc = token_specific.t_init(SlotNumber, conf_name); if (rc != 0) { *FunctionList = NULL; TRACE_DEVEL("Token Specific Init failed.\n"); goto done; } } rc = load_token_data(SlotNumber); if (rc != CKR_OK) { *FunctionList = NULL; TRACE_DEVEL("Failed to load token data.\n"); goto done; } /* no need to return error here, we load the token data we can * and syslog the rest */ load_public_token_objects(); XProcLock(); global_shm->publ_loaded = TRUE; XProcUnLock(); init_slotInfo(); usage_count++; (*FunctionList) = &function_list; done: if (pthread_mutex_unlock(&native_mutex)) { TRACE_ERROR("Failed to unlock mutex.\n"); rc = CKR_FUNCTION_FAILED; } return rc; } /* What does this really have to do in this new token... probably * need to close the adapters that are opened, and clear the other * stuff */ CK_RV SC_Finalize(CK_SLOT_ID sid) { CK_RV rc, rc_mutex; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } rc = MY_LockMutex(&pkcs_mutex); if (rc != CKR_OK) { TRACE_ERROR("Mutex lock failed.\n"); return rc; } /* If somebody else has taken care of things, leave... */ if (initialized == FALSE) { MY_UnlockMutex(&pkcs_mutex); TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } usage_count--; if (usage_count == 0) { initialized = FALSE; } session_mgr_close_all_sessions(); object_mgr_purge_token_objects(); detach_shm(); /* close spin lock file */ CloseXProcLock(); if (token_specific.t_final != NULL) { rc = token_specific.t_final(); if (rc != CKR_OK) { TRACE_ERROR("Token specific final call failed.\n"); goto done; } } done: rc_mutex = MY_UnlockMutex(&pkcs_mutex); if (rc_mutex != CKR_OK) { TRACE_ERROR("Mutex unlock failed.\n"); return rc_mutex; } return rc; } CK_RV SC_GetTokenInfo(CK_SLOT_ID sid, CK_TOKEN_INFO_PTR pInfo) { CK_RV rc = CKR_OK; time_t now; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto done; } copy_token_contents_sensibly(pInfo, nv_token_data); /* Set the time */ now = time ((time_t *)NULL); strftime((char *)pInfo->utcTime, 16, "%X", localtime(&now)); done: TRACE_INFO("C_GetTokenInfo: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } /* * Get the mechanism type list for the current token. */ CK_RV SC_GetMechanismList(CK_SLOT_ID sid, CK_MECHANISM_TYPE_PTR pMechList, CK_ULONG_PTR count) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto out; } if (count == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto out; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto out; } if (!token_specific.t_get_mechanism_list) { TRACE_ERROR("token specific GetMechanismList doesn't exist.\n"); rc = CKR_GENERAL_ERROR; goto out; } rc = token_specific.t_get_mechanism_list(pMechList, count); if (rc == CKR_OK) { /* To accomodate certain special cases, we may need to * make adjustments to the token's mechanism list. */ mechanism_list_transformations(pMechList, count); } out: TRACE_INFO("C_GetMechanismList: rc = 0x%08lx, # mechanisms: %lu\n", rc, *count); return rc; } /* * Get the mechanism info for the current type and token. */ CK_RV SC_GetMechanismInfo(CK_SLOT_ID sid, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto out; } if (pInfo == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto out; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto out; } if (!token_specific.t_get_mechanism_info) { TRACE_ERROR("token specific GetMechanismInfo doesn't exist.\n"); rc = CKR_GENERAL_ERROR; goto out; } rc = token_specific.t_get_mechanism_info(type, pInfo); out: TRACE_INFO("C_GetMechanismInfo: rc = 0x%08lx, mech type = 0x%08lx\n", rc, type); return rc; } /* * This routine should only be called if no other processes are * attached to the token. we need to somehow check that this is the * only process Meta API should prevent this since it knows session * states in the shared memory. */ CK_RV SC_InitToken(CK_SLOT_ID sid, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) { CK_RV rc = CKR_OK; CK_BYTE hash_sha[SHA1_HASH_SIZE]; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPin || !pLabel) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (nv_token_data->token_info.flags & CKF_SO_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } /* Check if token has a specific handler for this, otherwise fall back * to default behaviour. */ if (token_specific.t_init_token) { rc = token_specific.t_init_token(sid, pPin, ulPinLen, pLabel); if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; } goto done; } rc = compute_sha1(pPin, ulPinLen, hash_sha); if (memcmp(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* Before we reconstruct all the data, we should delete the * token objects from the filesystem. */ object_mgr_destroy_token_objects(); delete_token_data(); init_token_data(sid); init_slotInfo(); memcpy(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE); nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED; memcpy(nv_token_data->token_info.label, pLabel, 32); rc = save_token_data(sid); if (rc != CKR_OK) { TRACE_DEVEL("Failed to save token data.\n"); goto done; } done: TRACE_INFO("C_InitToken: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_InitPIN(ST_SESSION_HANDLE *sSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { SESSION *sess = NULL; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_BYTE hash_md5[MD5_HASH_SIZE]; CK_RV rc = CKR_OK; CK_FLAGS_32 *flags = NULL; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPin) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_locked(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } if (sess->session_info.state != CKS_RW_SO_FUNCTIONS) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } /* Check if token has a specific handler for this, otherwise fall back * to default behaviour. */ if (token_specific.t_init_pin) { rc = token_specific.t_init_pin(sess, pPin, ulPinLen); if (rc == CKR_OK) { flags = &nv_token_data->token_info.flags; *flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW); rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) TRACE_DEVEL("Failed to save token data.\n"); } goto done; } if ((ulPinLen < MIN_PIN_LEN) || (ulPinLen > MAX_PIN_LEN)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LEN_RANGE)); rc = CKR_PIN_LEN_RANGE; goto done; } /* compute the SHA and MD5 hashes of the user pin */ rc = compute_sha1(pPin, ulPinLen, hash_sha); rc |= compute_md5( pPin, ulPinLen, hash_md5 ); if (rc != CKR_OK) { TRACE_ERROR("Failed to compute sha or md5 for user pin.\n"); goto done; } rc = XProcLock(); if (rc != CKR_OK) { TRACE_ERROR("Failed to get process lock.\n"); goto done; } memcpy(nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE); nv_token_data->token_info.flags |= CKF_USER_PIN_INITIALIZED; nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); nv_token_data->token_info.flags &= ~(CKF_USER_PIN_LOCKED); XProcUnLock(); memcpy(user_pin_md5, hash_md5, MD5_HASH_SIZE); rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) { TRACE_DEVEL("Failed to save token data.\n"); goto done; } rc = save_masterkey_user(); if (rc != CKR_OK) TRACE_DEVEL("Failed to save user's masterkey.\n"); done: TRACE_INFO("C_InitPin: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_SetPIN(ST_SESSION_HANDLE *sSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { SESSION *sess = NULL; CK_BYTE old_hash_sha[SHA1_HASH_SIZE]; CK_BYTE new_hash_sha[SHA1_HASH_SIZE]; CK_BYTE hash_md5[MD5_HASH_SIZE]; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_locked(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } /* Check if token has a specific handler for this, otherwise fall back * to default behaviour. */ if (token_specific.t_set_pin) { rc = token_specific.t_set_pin(sess, pOldPin, ulOldLen, pNewPin, ulNewLen); goto done; } if ((ulNewLen < MIN_PIN_LEN) || (ulNewLen > MAX_PIN_LEN)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LEN_RANGE)); rc = CKR_PIN_LEN_RANGE; goto done; } rc = compute_sha1(pOldPin, ulOldLen, old_hash_sha); if (rc != CKR_OK) { TRACE_ERROR("Failed to compute sha for old pin.\n"); goto done; } /* From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of * the user that is currently logged in, or the CKU_USER PIN * if the session is not logged in." A non R/W session fails * with CKR_SESSION_READ_ONLY. */ if ((sess->session_info.state == CKS_RW_USER_FUNCTIONS) || (sess->session_info.state == CKS_RW_PUBLIC_SESSION)) { if (memcmp(nv_token_data->user_pin_sha, old_hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } rc = compute_sha1(pNewPin, ulNewLen, new_hash_sha); rc |= compute_md5(pNewPin, ulNewLen, hash_md5); if (rc != CKR_OK) { TRACE_ERROR("Failed to compute hash for new pin.\n"); goto done; } /* The old PIN matches, now make sure its different * than the new and is not the default. */ if ((memcmp(old_hash_sha, new_hash_sha, SHA1_HASH_SIZE) == 0) || (memcmp(new_hash_sha, default_user_pin_sha, SHA1_HASH_SIZE) == 0)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID)); rc = CKR_PIN_INVALID; goto done; } rc = XProcLock(); if (rc != CKR_OK) { TRACE_DEVEL("Failed to get process lock.\n"); goto done; } memcpy(nv_token_data->user_pin_sha, new_hash_sha, SHA1_HASH_SIZE); memcpy(user_pin_md5, hash_md5, MD5_HASH_SIZE); nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); XProcUnLock(); rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) { TRACE_DEVEL("Failed to save token data.\n"); goto done; } rc = save_masterkey_user(); } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (memcmp(nv_token_data->so_pin_sha, old_hash_sha, SHA1_HASH_SIZE) != 0) { rc = CKR_PIN_INCORRECT; TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); goto done; } rc = compute_sha1(pNewPin, ulNewLen, new_hash_sha); rc |= compute_md5(pNewPin, ulNewLen, hash_md5); if (rc != CKR_OK) { TRACE_ERROR("Failed to compute hash for new pin.\n"); goto done; } /* The old PIN matches, now make sure its different * than the new and is not the default. */ if ((memcmp(old_hash_sha, new_hash_sha, SHA1_HASH_SIZE) == 0) || (memcmp(new_hash_sha, default_so_pin_sha, SHA1_HASH_SIZE) == 0)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID)); rc = CKR_PIN_INVALID; goto done; } rc = XProcLock(); if (rc != CKR_OK) { TRACE_DEVEL("Failed to get process lock.\n"); goto done; } memcpy(nv_token_data->so_pin_sha, new_hash_sha, SHA1_HASH_SIZE); memcpy(so_pin_md5, hash_md5, MD5_HASH_SIZE); nv_token_data->token_info.flags &= ~(CKF_SO_PIN_TO_BE_CHANGED); XProcUnLock(); rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) { TRACE_DEVEL("Failed to save token data.\n"); goto done; } rc = save_masterkey_so(); if (rc != CKR_OK) TRACE_DEVEL("Failed to save SO's masterkey.\n"); } else { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; } done: TRACE_INFO("C_SetPin: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_OpenSession(CK_SLOT_ID sid, CK_FLAGS flags, CK_SESSION_HANDLE_PTR phSession) { CK_BBOOL locked = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (phSession == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto done; } flags |= CKF_SERIAL_SESSION; if ((flags & CKF_RW_SESSION) == 0) { if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_WRITE_SO_EXISTS)); rc = CKR_SESSION_READ_WRITE_SO_EXISTS; goto done; } } // Get the mutex because we may modify the pid_list rc = MY_LockMutex(&pkcs_mutex); if (rc != CKR_OK) { TRACE_ERROR("Failed to get mutex lock.\n"); goto done; } locked = TRUE; MY_UnlockMutex(&pkcs_mutex); locked = FALSE; rc = session_mgr_new(flags, sid, phSession); if (rc != CKR_OK) { TRACE_DEVEL("session_mgr_new() failed\n"); goto done; } done: if (locked) MY_UnlockMutex(&pkcs_mutex); TRACE_INFO("C_OpenSession: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_CloseSession(ST_SESSION_HANDLE *sSession) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } rc = session_mgr_close_session(sSession->sessionh); done: TRACE_INFO("C_CloseSession: rc = 0x%08lx sess = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_CloseAllSessions(CK_SLOT_ID sid) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } rc = session_mgr_close_all_sessions(); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_close_all_sessions() failed.\n"); done: TRACE_INFO("C_CloseAllSessions: rc = 0x%08lx slot = %lu\n", rc, sid); return rc; } CK_RV SC_GetSessionInfo(ST_SESSION_HANDLE *sSession, CK_SESSION_INFO_PTR pInfo) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } memcpy(pInfo, &sess->session_info, sizeof(CK_SESSION_INFO)); done: TRACE_INFO("C_GetSessionInfo: session = %lu\n", sSession->sessionh); return rc; } CK_RV SC_GetOperationState(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulOperationStateLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (!pOperationState) length_only = TRUE; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = session_mgr_get_op_state(sess, length_only, pOperationState, pulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_get_op_state() failed.\n"); done: TRACE_INFO("C_GetOperationState: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_SetOperationState(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pOperationState || (ulOperationStateLen == 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey, pOperationState, ulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_set_op_state() failed.\n"); done: TRACE_INFO("C_SetOperationState: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_Login(ST_SESSION_HANDLE *sSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { SESSION *sess = NULL; CK_FLAGS_32 *flags = NULL; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_RV rc = CKR_OK; /* In v2.11, logins should be exclusive, since token * specific flags may need to be set for a bad login. - KEY */ rc = MY_LockMutex(&login_mutex); if (rc != CKR_OK) { TRACE_ERROR("Failed to get mutex lock.\n"); return CKR_FUNCTION_FAILED; } if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } flags = &nv_token_data->token_info.flags; if (!pPin || ulPinLen > MAX_PIN_LEN) { set_login_flags(userType, flags); TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* PKCS #11 v2.01 requires that all sessions have the same login status: * --> all sessions are public, all are SO or all are USER */ if (userType == CKU_USER) { if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_ANOTHER_ALREADY_LOGGED_IN)); rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } if (session_mgr_user_session_exists()) { TRACE_ERROR("%s\n",ock_err(ERR_USER_ALREADY_LOGGED_IN)); rc = CKR_USER_ALREADY_LOGGED_IN; } } else if (userType == CKU_SO) { if (session_mgr_user_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_ANOTHER_ALREADY_LOGGED_IN)); rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n",ock_err(ERR_USER_ALREADY_LOGGED_IN)); rc = CKR_USER_ALREADY_LOGGED_IN; } if (session_mgr_readonly_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY_EXISTS)); rc = CKR_SESSION_READ_ONLY_EXISTS; } } else { rc = CKR_USER_TYPE_INVALID; TRACE_ERROR("%s\n", ock_err(ERR_USER_TYPE_INVALID)); } if (rc != CKR_OK) goto done; if (userType == CKU_USER) { if (*flags & CKF_USER_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } /* Check if token has a specific handler for this, otherwise * fall back to default behaviour. */ if (token_specific.t_login) { // call the pluggable login function here - KEY rc = token_specific.t_login(sess, userType, pPin, ulPinLen); if (rc == CKR_OK) { *flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW); } else if (rc == CKR_PIN_INCORRECT) { set_login_flags(userType, flags); } goto done; } if (memcmp(nv_token_data->user_pin_sha, "00000000000000000000", SHA1_HASH_SIZE) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED)); rc = CKR_USER_PIN_NOT_INITIALIZED; goto done; } rc = compute_sha1(pPin, ulPinLen, hash_sha); if (memcmp(nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { set_login_flags(userType, flags); TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* Successful login, clear flags */ *flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW); compute_md5( pPin, ulPinLen, user_pin_md5 ); memset( so_pin_md5, 0x0, MD5_HASH_SIZE ); rc = load_masterkey_user(); if (rc != CKR_OK){ TRACE_DEVEL("Failed to load user's masterkey.\n"); goto done; } /* no need to return error here, we load the token data * we can and syslog the rest */ load_private_token_objects(); XProcLock(); global_shm->priv_loaded = TRUE; XProcUnLock(); } else { if (*flags & CKF_SO_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } /* Check if token has a specific handler for this, otherwise * fall back to default behaviour. */ if (token_specific.t_login) { /* call the pluggable login function here - KEY */ rc = token_specific.t_login(sess, userType, pPin, ulPinLen); if (rc == CKR_OK) { *flags &= ~(CKF_SO_PIN_LOCKED | CKF_SO_PIN_FINAL_TRY | CKF_SO_PIN_COUNT_LOW); } else if (rc == CKR_PIN_INCORRECT) { set_login_flags(userType, flags); } goto done; } rc = compute_sha1(pPin, ulPinLen, hash_sha); if (memcmp(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { set_login_flags(userType, flags); TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* Successful login, clear flags */ *flags &= ~(CKF_SO_PIN_LOCKED | CKF_SO_PIN_FINAL_TRY | CKF_SO_PIN_COUNT_LOW); compute_md5(pPin, ulPinLen, so_pin_md5); memset(user_pin_md5, 0x0, MD5_HASH_SIZE); rc = load_masterkey_so(); if (rc != CKR_OK) TRACE_DEVEL("Failed to load SO's masterkey.\n"); } done: if (rc == CKR_OK) { rc = session_mgr_login_all(userType); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_login_all failed.\n"); } TRACE_INFO("C_Login: rc = 0x%08lx\n", rc); save_token_data(sess->session_info.slotID); MY_UnlockMutex(&login_mutex); return rc; } CK_RV SC_Logout(ST_SESSION_HANDLE *sSession) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* all sessions have the same state so we just have to check one */ if (session_mgr_public_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } rc = session_mgr_logout_all(); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_logout_all failed.\n"); /* Check if token has a specific handler for this, otherwise fall back * to default behaviour. */ if (token_specific.t_logout) { rc = token_specific.t_logout(); goto done; } memset(user_pin_md5, 0x0, MD5_HASH_SIZE); memset(so_pin_md5, 0x0, MD5_HASH_SIZE); object_mgr_purge_private_token_objects(); done: TRACE_INFO("C_Logout: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_CreateObject(ST_SESSION_HANDLE *sSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_add(sess, pTemplate, ulCount, phObject); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_add() failed.\n"); done: TRACE_INFO("C_CreateObject: rc = 0x%08lx\n", rc); #ifdef DEBUG int i; for (i = 0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { TRACE_DEBUG("Object Type: 0x%02lx\n", *((CK_ULONG *) pTemplate[i].pValue)); } } if (rc == CKR_OK) TRACE_DEBUG("Handle: %lu\n", *phObject); #endif return rc; } CK_RV SC_CopyObject(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_copy(sess, pTemplate, ulCount, hObject, phNewObject); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_copy() failed\n"); done: TRACE_INFO("C_CopyObject:rc = 0x%08lx,old handle = %lu,new handle = %lu\n", rc, hObject, *phNewObject); return rc; } CK_RV SC_DestroyObject(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_destroy_object(sess, hObject); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_destroy_object() failed\n"); done: TRACE_INFO("C_DestroyObject: rc = 0x%08lx, handle = %lu\n", rc, hObject); return rc; } CK_RV SC_GetObjectSize(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_get_object_size(hObject, pulSize); if (rc != CKR_OK) TRACE_ERROR("object_mgr_get_object_size() failed.\n"); done: TRACE_INFO("C_GetObjectSize: rc = 0x%08lx, handle = %lu\n", rc, hObject); return rc; } CK_RV SC_GetAttributeValue(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_get_attribute_values(sess, hObject, pTemplate, ulCount); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_get_attribute_value() failed.\n"); done: TRACE_INFO("C_GetAttributeValue: rc = 0x%08lx, handle = %lu\n", rc, hObject); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; CK_BYTE *ptr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_SetAttributeValue(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_set_attribute_values(sess, hObject, pTemplate, ulCount); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_set_attribute_values() failed.\n"); done: TRACE_INFO("C_SetAttributeValue: rc = 0x%08lx, handle = %lu\n", rc, hObject); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_FindObjectsInit(ST_SESSION_HANDLE *sSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->find_active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = object_mgr_find_init(sess, pTemplate, ulCount); done: TRACE_INFO("C_FindObjectsInit: rc = 0x%08lx\n", rc); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_FindObjects(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { SESSION *sess = NULL; CK_ULONG count = 0; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!phObject || !pulObjectCount) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->find_active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!sess->find_list) { TRACE_DEVEL("sess->find_list is NULL.\n"); rc = CKR_FUNCTION_FAILED; goto done; } count = MIN(ulMaxObjectCount, (sess->find_count - sess->find_idx)); memcpy(phObject, sess->find_list + sess->find_idx, count * sizeof(CK_OBJECT_HANDLE)); *pulObjectCount = count; sess->find_idx += count; rc = CKR_OK; done: TRACE_INFO("C_FindObjects: rc = 0x%08lx, returned %lu objects\n", rc, count); return rc; } CK_RV SC_FindObjectsFinal(ST_SESSION_HANDLE *sSession) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->find_active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (sess->find_list) free(sess->find_list); sess->find_list = NULL; sess->find_len = 0; sess->find_idx = 0; sess->find_active = FALSE; rc = CKR_OK; done: TRACE_INFO("C_FindObjectsFinal: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_EncryptInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_ENCRYPT); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->encr_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = encr_mgr_init(sess, &sess->encr_ctx, OP_ENCRYPT_INIT, pMechanism, hKey); done: TRACE_INFO("C_EncryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Encrypt(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pulEncryptedDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pEncryptedData) length_only = TRUE; rc = encr_mgr_encrypt(sess, length_only, &sess->encr_ctx, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); if (rc != CKR_OK) TRACE_DEVEL("encr_mgr_encrypt() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_EncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if ((!pPart && ulPartLen != 0) || !pulEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pEncryptedPart) length_only = TRUE; rc = encr_mgr_encrypt_update(sess, length_only, &sess->encr_ctx, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); if (rc != CKR_OK) TRACE_DEVEL("encr_mgr_encrypt_update() failed.\n"); done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); return rc; } /* I think RSA goofed when designing the specification for C_EncryptFinal. * This function is supposed to follow the Cryptoki standard that if * pLastEncryptedPart == NULL then the user is requesting only the length * of the output. * * But it's quite possible that no output will be returned (say the user * specifies a total of 64 bytes of input data throughout the multi-part * encryption). The same thing can happen during an EncryptUpdate. * * ie: * * 1) user calls C_EncryptFinal to get the needed length * --> we return "0 bytes required" * 2) user passes in a NULL pointer for pLastEncryptedPart * --> we think the user is requesting the length again <-- * * So the user needs to pass in a non-NULL pointer even though we're not * going to return anything in it. It would have been cleaner if RSA would * have simply included a "give-me-the-length-only flag" as an argument. */ CK_RV SC_EncryptFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulLastEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pLastEncryptedPart) length_only = TRUE; rc = encr_mgr_encrypt_final(sess,length_only, &sess->encr_ctx, pLastEncryptedPart, pulLastEncryptedPartLen); if (rc != CKR_OK) TRACE_ERROR("encr_mgr_encrypt_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); return rc; } CK_RV SC_DecryptInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DECRYPT); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->decr_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = decr_mgr_init(sess, &sess->decr_ctx, OP_DECRYPT_INIT, pMechanism, hKey); if (rc != CKR_OK) TRACE_DEVEL("decr_mgr_init() failed.\n"); done: TRACE_INFO("C_DecryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Decrypt(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pEncryptedData || !pulDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pData) length_only = TRUE; rc = decr_mgr_decrypt(sess, length_only, &sess->decr_ctx, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen); if (rc != CKR_OK) TRACE_DEVEL("decr_mgr_decrypt() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulEncryptedDataLen); return rc; } CK_RV SC_DecryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if ((!pEncryptedPart && ulEncryptedPartLen != 0) || !pulPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pPart) length_only = TRUE; rc = decr_mgr_decrypt_update(sess, length_only, &sess->decr_ctx, pEncryptedPart,ulEncryptedPartLen, pPart, pulPartLen); if (rc != CKR_OK) TRACE_DEVEL("decr_mgr_decrypt_update() failed.\n"); done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulEncryptedPartLen); return rc; } CK_RV SC_DecryptFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulLastPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pLastPart) length_only = TRUE; rc = decr_mgr_decrypt_final(sess, length_only, &sess->decr_ctx, pLastPart, pulLastPartLen); if (rc != CKR_OK) TRACE_DEVEL("decr_mgr_decrypt_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, *pulLastPartLen); return rc; } CK_RV SC_DigestInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DIGEST); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->digest_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = digest_mgr_init(sess, &sess->digest_ctx, pMechanism); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_init() failed.\n"); done: TRACE_INFO("C_DigestInit: rc = 0x%08lx, sess = %ld, mech = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Digest(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } /* Netscape has been known to pass a null pData to DigestUpdate * but never for Digest. It doesn't really make sense to allow it here */ if (!pData || !pulDigestLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pDigest) length_only = TRUE; rc = digest_mgr_digest(sess, length_only, &sess->digest_ctx, pData, ulDataLen, pDigest, pulDigestLen); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest() failed.\n"); done: TRACE_INFO("C_Digest: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_DigestUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } /* If there is data to hash, do so. */ if (ulPartLen) { rc = digest_mgr_digest_update(sess, &sess->digest_ctx, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest_update() failed.\n"); } done: TRACE_INFO("C_DigestUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_DigestKey(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = digest_mgr_digest_key(sess, &sess->digest_ctx, hKey); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest_key() failed.\n"); done: TRACE_INFO("C_DigestKey: rc = %08lx, sess = %ld, key = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, hKey); return rc; } CK_RV SC_DigestFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulDigestLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pDigest) length_only = TRUE; rc = digest_mgr_digest_final(sess, length_only, &sess->digest_ctx, pDigest, pulDigestLen); if (rc != CKR_OK) TRACE_ERROR("digest_mgr_digest_final() failed.\n"); done: TRACE_INFO("C_DigestFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_SignInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism ) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = valid_mech(pMechanism, CKF_SIGN); if (rc != CKR_OK) goto done; if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->sign_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); goto done; } rc = sign_mgr_init(sess, &sess->sign_ctx, pMechanism, FALSE, hKey); if (rc != CKR_OK) TRACE_DEVEL("sign_mgr_init() failed.\n"); done: TRACE_INFO("C_SignInit: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Sign(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pSignature) length_only = TRUE; rc = sign_mgr_sign(sess, length_only, &sess->sign_ctx, pData, ulDataLen, pSignature, pulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("sign_mgr_sign() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_Sign: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_SignUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = sign_mgr_sign_update(sess, &sess->sign_ctx, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("sign_mgr_sign_update() failed.\n"); done: if (rc != CKR_OK) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_SignFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pSignature) length_only = TRUE; rc = sign_mgr_sign_final(sess, length_only, &sess->sign_ctx, pSignature, pulSignatureLen); if (rc != CKR_OK) TRACE_ERROR("sign_mgr_sign_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_SignRecoverInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism ){ TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_SIGN_RECOVER); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->sign_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); goto done; } rc = sign_mgr_init(sess, &sess->sign_ctx, pMechanism, TRUE, hKey); if (rc != CKR_OK) TRACE_DEVEL("sign_mgr_init() failed.\n"); done: TRACE_INFO("C_SignRecoverInit: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_SignRecover(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if ((sess->sign_ctx.active == FALSE) || (sess->sign_ctx.recover == FALSE)) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } if (!pSignature) length_only = TRUE; rc = sign_mgr_sign_recover(sess, length_only, &sess->sign_ctx, pData, ulDataLen, pSignature, pulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("sign_mgr_sign_recover() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignRecover: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_VerifyInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism ) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_VERIFY); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->verify_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); goto done; } rc = verify_mgr_init(sess, &sess->verify_ctx, pMechanism, FALSE, hKey); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_init() failed.\n"); done: TRACE_INFO("C_VerifyInit: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Verify(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pSignature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = verify_mgr_verify(sess, &sess->verify_ctx, pData, ulDataLen, pSignature, ulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_verify() failed.\n"); done: verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_Verify: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_VerifyUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = verify_mgr_verify_update(sess, &sess->verify_ctx, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_verify_update() failed.\n"); done: if (rc != CKR_OK) verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_VerifyFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pSignature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = verify_mgr_verify_final(sess, &sess->verify_ctx, pSignature, ulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_verify_final() failed.\n"); done: verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_VerifyRecoverInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_VERIFY_RECOVER); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->verify_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); goto done; } rc = verify_mgr_init(sess, &sess->verify_ctx, pMechanism, TRUE, hKey); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_init() failed.\n"); done: TRACE_INFO("C_VerifyRecoverInit: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_VerifyRecover(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pSignature || !pulDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if ((sess->verify_ctx.active == FALSE) || (sess->verify_ctx.recover == FALSE)) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } if (!pData) length_only = TRUE; rc = verify_mgr_verify_recover(sess, length_only, &sess->verify_ctx, pSignature, ulSignatureLen, pData, pulDataLen); if (rc != CKR_OK) TRACE_DEVEL("verify_mgr_verify_recover() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyRecover: rc = %08lx, sess = %ld, recover len = %lu, " "length_only = %d\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, *pulDataLen, length_only); return rc; } CK_RV SC_DigestEncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_DecryptDigestUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_SignEncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_DecryptVerifyUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_GenerateKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !phKey || (pTemplate == NULL && ulCount != 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_GENERATE); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = key_mgr_generate_key(sess, pMechanism, pTemplate, ulCount, phKey); if (rc != CKR_OK) TRACE_DEVEL("key_mgr_generate_key() failed.\n"); done: TRACE_INFO("C_GenerateKey: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, pMechanism->mechanism); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx,Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) { TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } } #endif return rc; } CK_RV SC_GenerateKeyPair(ST_SESSION_HANDLE *sSession, 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) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !phPublicKey || !phPrivateKey || (!pPublicKeyTemplate && (ulPublicKeyAttributeCount != 0)) || (!pPrivateKeyTemplate && (ulPrivateKeyAttributeCount != 0))) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_GENERATE_KEY_PAIR); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = key_mgr_generate_key_pair(sess, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); if (rc != CKR_OK) TRACE_DEVEL("key_mgr_generate_key_pair() failed.\n"); done: TRACE_INFO("C_GenerateKeyPair: rc = %08lx, sess = %ld, mech = %lu\n", rc, (sess == NULL) ? -1 : ((CK_LONG) sess->handle), pMechanism->mechanism); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; int i; if (rc == CKR_OK) { TRACE_DEBUG("Public handle: %lu, Private handle: %lu\n", *phPublicKey, *phPrivateKey); } TRACE_DEBUG("Public Template:\n"); attr = pPublicKeyTemplate; for (i = 0; i < ulPublicKeyAttributeCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } TRACE_DEBUG("Private Template:\n"); attr = pPublicKeyTemplate; for (i = 0; i < ulPublicKeyAttributeCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_WrapKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !pulWrappedKeyLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_WRAP); if (rc != CKR_OK) goto done; if (!pWrappedKey) length_only = TRUE; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = key_mgr_wrap_key(sess, length_only, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen); if (rc != CKR_OK) TRACE_DEVEL("key_mgr_wrap_key() failed.\n"); done: TRACE_INFO("C_WrapKey: rc = %08lx, sess = %ld, encrypting key = %lu, " "wrapped key = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, hWrappingKey, hKey); return rc; } CK_RV SC_UnwrapKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !pWrappedKey || (!pTemplate && ulCount != 0) || !phKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_UNWRAP); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = key_mgr_unwrap_key(sess, pMechanism, pTemplate, ulCount, pWrappedKey, ulWrappedKeyLen, hUnwrappingKey, phKey); if (rc != CKR_OK) TRACE_DEVEL("key_mgr_unwrap_key() failed.\n"); done: TRACE_INFO("C_UnwrapKey: rc = %08lx, sess = %ld, decrypting key = %lu," "unwrapped key = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, hUnwrappingKey, *phKey); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; CK_BYTE *ptr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_DeriveKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || (!pTemplate && ulCount != 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DERIVE); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = key_mgr_derive_key(sess, pMechanism, hBaseKey, phKey, pTemplate, ulCount ); if (rc != CKR_OK) TRACE_DEVEL("key_mgr_derive_key() failed.\n"); done: TRACE_INFO("C_DeriveKey: rc = %08lx, sess = %ld, mech = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; CK_BYTE *ptr = NULL; int i; if (rc == CKR_OK) { switch (pMechanism->mechanism) { case CKM_SSL3_KEY_AND_MAC_DERIVE: { CK_SSL3_KEY_MAT_PARAMS *pReq; CK_SSL3_KEY_MAT_OUT *pPtr; pReq = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; pPtr = pReq->pReturnedKeyMaterial; TRACE_DEBUG("Client MAC key: %lu, Server MAC key: %lu, " "Client Key: %lu, Server Key: %lu\n", pPtr->hClientMacSecret, pPtr->hServerMacSecret, pPtr->hClientKey, pPtr->hServerKey); } break; case CKM_DH_PKCS_DERIVE: { TRACE_DEBUG("DH Shared Secret:\n"); } break ; default: TRACE_DEBUG("Derived key: %lu\n", *phKey); } } attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif /* DEBUG */ return rc; } CK_RV SC_SeedRandom(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_RANDOM_SEED_NOT_SUPPORTED)); return CKR_RANDOM_SEED_NOT_SUPPORTED; } CK_RV SC_GenerateRandom(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pRandomData && ulRandomLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = rng_generate(pRandomData, ulRandomLen); if (rc != CKR_OK) TRACE_DEVEL("rng_generate() failed.\n"); done: TRACE_INFO("C_GenerateRandom: rc = %08lx, %lu bytes\n", rc, ulRandomLen); return rc; } CK_RV SC_GetFunctionStatus(ST_SESSION_HANDLE *sSession) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL)); return CKR_FUNCTION_NOT_PARALLEL; } CK_RV SC_CancelFunction(ST_SESSION_HANDLE *sSession) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL)); return CKR_FUNCTION_NOT_PARALLEL; } void SC_SetFunctionList(void) { function_list.ST_Initialize = (void *)ST_Initialize; function_list.ST_GetTokenInfo = SC_GetTokenInfo; function_list.ST_GetMechanismList = SC_GetMechanismList; function_list.ST_GetMechanismInfo = SC_GetMechanismInfo; function_list.ST_InitToken = SC_InitToken; function_list.ST_InitPIN = SC_InitPIN; function_list.ST_SetPIN = SC_SetPIN; function_list.ST_OpenSession = SC_OpenSession; function_list.ST_CloseSession = SC_CloseSession; function_list.ST_GetSessionInfo = SC_GetSessionInfo; function_list.ST_GetOperationState = SC_GetOperationState; function_list.ST_SetOperationState = SC_SetOperationState; function_list.ST_Login = SC_Login; function_list.ST_Logout = SC_Logout; function_list.ST_CreateObject = SC_CreateObject; function_list.ST_CopyObject = SC_CopyObject; function_list.ST_DestroyObject = SC_DestroyObject; function_list.ST_GetObjectSize = SC_GetObjectSize; function_list.ST_GetAttributeValue = SC_GetAttributeValue; function_list.ST_SetAttributeValue = SC_SetAttributeValue; function_list.ST_FindObjectsInit = SC_FindObjectsInit; function_list.ST_FindObjects = SC_FindObjects; function_list.ST_FindObjectsFinal = SC_FindObjectsFinal; function_list.ST_EncryptInit = SC_EncryptInit; function_list.ST_Encrypt = SC_Encrypt; function_list.ST_EncryptUpdate = SC_EncryptUpdate; function_list.ST_EncryptFinal = SC_EncryptFinal; function_list.ST_DecryptInit = SC_DecryptInit; function_list.ST_Decrypt = SC_Decrypt; function_list.ST_DecryptUpdate = SC_DecryptUpdate; function_list.ST_DecryptFinal = SC_DecryptFinal; function_list.ST_DigestInit = SC_DigestInit; function_list.ST_Digest = SC_Digest; function_list.ST_DigestUpdate = SC_DigestUpdate; function_list.ST_DigestKey = SC_DigestKey; function_list.ST_DigestFinal = SC_DigestFinal; function_list.ST_SignInit = SC_SignInit; function_list.ST_Sign = SC_Sign; function_list.ST_SignUpdate = SC_SignUpdate; function_list.ST_SignFinal = SC_SignFinal; function_list.ST_SignRecoverInit = SC_SignRecoverInit; function_list.ST_SignRecover = SC_SignRecover; function_list.ST_VerifyInit = SC_VerifyInit; function_list.ST_Verify = SC_Verify; function_list.ST_VerifyUpdate = SC_VerifyUpdate; function_list.ST_VerifyFinal = SC_VerifyFinal; function_list.ST_VerifyRecoverInit = SC_VerifyRecoverInit; function_list.ST_VerifyRecover = SC_VerifyRecover; function_list.ST_DigestEncryptUpdate = NULL; // SC_DigestEncryptUpdate; function_list.ST_DecryptDigestUpdate = NULL; // SC_DecryptDigestUpdate; function_list.ST_SignEncryptUpdate = NULL; //SC_SignEncryptUpdate; function_list.ST_DecryptVerifyUpdate = NULL; // SC_DecryptVerifyUpdate; function_list.ST_GenerateKey = SC_GenerateKey; function_list.ST_GenerateKeyPair = SC_GenerateKeyPair; function_list.ST_WrapKey = SC_WrapKey; function_list.ST_UnwrapKey = SC_UnwrapKey; function_list.ST_DeriveKey = SC_DeriveKey; function_list.ST_SeedRandom = SC_SeedRandom ; function_list.ST_GenerateRandom = SC_GenerateRandom; function_list.ST_GetFunctionStatus = NULL; // SC_GetFunctionStatus; function_list.ST_CancelFunction = NULL; // SC_CancelFunction; } opencryptoki+dfsg/usr/lib/pkcs11/soft_stdll/0000755000175000017500000000000012630407154020135 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/soft_stdll/soft_specific.c0000644000175000017500000023775112630407154023140 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ #define _BSD_SOURCE #include #include // for memcmp() et al #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "errno.h" #include "tok_specific.h" #include "tok_struct.h" #include "trace.h" #include #include #include #include #include #include #include #include #include #include typedef unsigned int uint32_t; pthread_mutex_t rngmtx = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t nextmutex = PTHREAD_MUTEX_INITIALIZER; unsigned int rnginitialized=0; #define MAX_GENERIC_KEY_SIZE 256 CK_CHAR manuf[] = "IBM Corp."; CK_CHAR model[] = "IBM SoftTok "; CK_CHAR descr[] = "IBM PKCS#11 Soft token"; CK_CHAR label[] = "IBM OS PKCS#11 "; CK_RV token_specific_init(CK_SLOT_ID SlotNumber, char *conf_name) { return CKR_OK; } CK_RV token_specific_final() { return CKR_OK; } CK_RV token_specific_des_key_gen(CK_BYTE *des_key, CK_ULONG len, CK_ULONG keysize) { // Nothing different to do for DES or TDES here as this is just // random data... Validation handles the rest // Only check for weak keys when single DES. if (len == (3 * DES_KEY_SIZE)) rng_generate(des_key,len); else { do { rng_generate(des_key, len); } while (des_check_weak_key(des_key) == TRUE); } // we really need to validate the key for parity etc... // we should do that here... The caller validates the single des keys // against the known and suspected poor keys.. return CKR_OK; } CK_RV token_specific_des_ecb(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { CK_ULONG rc; DES_key_schedule des_key2; const_DES_cblock key_val_SSL, in_key_data; DES_cblock out_key_data; unsigned int i,j; CK_ATTRIBUTE *attr = NULL; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key\n"); return CKR_FUNCTION_FAILED; } // Create the key schedule memcpy(&key_val_SSL, attr->pValue, 8); DES_set_key_unchecked(&key_val_SSL, &des_key2); // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8 ){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } // Both the encrypt and the decrypt are done 8 bytes at a time if (encrypt) { for (i=0; itemplate, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key\n"); return CKR_FUNCTION_FAILED; } // Create the key schedule memcpy(&key_val_SSL, attr->pValue, 8); DES_set_key_unchecked(&key_val_SSL, &des_key2); memcpy(&ivec, init_v, 8); // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8 ){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } if ( encrypt){ DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec, DES_ENCRYPT); *out_data_len = in_data_len; rc = CKR_OK; } else { DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec, DES_DECRYPT); *out_data_len = in_data_len; rc = CKR_OK; } return rc; } CK_RV token_specific_tdes_ecb(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_BYTE key_value[3*DES_KEY_SIZE]; CK_KEY_TYPE keytype; unsigned int k,j; DES_key_schedule des_key1; DES_key_schedule des_key2; DES_key_schedule des_key3; const_DES_cblock key_SSL1, key_SSL2, key_SSL3, in_key_data; DES_cblock out_key_data; // get the key type rc = template_attribute_find(key->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key\n"); return CKR_FUNCTION_FAILED; } if (keytype == CKK_DES2) { memcpy(key_value, attr->pValue, 2*DES_KEY_SIZE); memcpy(key_value + (2*DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); } else memcpy(key_value, attr->pValue, 3*DES_KEY_SIZE); // The key as passed is a 24 byte long string containing three des keys // pick them apart and create the 3 corresponding key schedules memcpy(&key_SSL1, key_value, 8); memcpy(&key_SSL2, key_value+8, 8); memcpy(&key_SSL3, key_value+16, 8); DES_set_key_unchecked(&key_SSL1, &des_key1); DES_set_key_unchecked(&key_SSL2, &des_key2); DES_set_key_unchecked(&key_SSL3, &des_key3); // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8 ){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } // the encrypt and decrypt are done 8 bytes at a time if (encrypt) { for(k=0;ktemplate, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key\n"); return CKR_FUNCTION_FAILED; } if (keytype == CKK_DES2) { memcpy(key_value, attr->pValue, 2*DES_KEY_SIZE); memcpy(key_value + (2*DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); } else memcpy(key_value, attr->pValue, 3*DES_KEY_SIZE); // The key as passed in is a 24 byte string containing 3 keys // pick it apart and create the key schedules memcpy(&key_SSL1, key_value, 8); memcpy(&key_SSL2, key_value+8, 8); memcpy(&key_SSL3, key_value+16, 8); DES_set_key_unchecked(&key_SSL1, &des_key1); DES_set_key_unchecked(&key_SSL2, &des_key2); DES_set_key_unchecked(&key_SSL3, &des_key3); memcpy(ivec, init_v, sizeof(ivec)); // the des decrypt will only fail if the data length is not evenly divisible // by 8 if (in_data_len % 8 ){ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); return CKR_DATA_LEN_RANGE; } // Encrypt or decrypt the data if (encrypt){ DES_ede3_cbc_encrypt(in_data, out_data, in_data_len, &des_key1, &des_key2, &des_key3, &ivec, DES_ENCRYPT); *out_data_len = in_data_len; rc = CKR_OK; }else { DES_ede3_cbc_encrypt(in_data, out_data, in_data_len, &des_key1, &des_key2, &des_key3, &ivec, DES_DECRYPT); *out_data_len = in_data_len; rc = CKR_OK; } return rc; } // convert from the local PKCS11 template representation to // the underlying requirement // returns the pointer to the local key representation void * rsa_convert_public_key( OBJECT * key_obj ) { CK_BBOOL rc; CK_ATTRIBUTE * modulus = NULL; CK_ATTRIBUTE * pub_exp = NULL; RSA *rsa; BIGNUM *bn_mod, *bn_exp; rc = template_attribute_find( key_obj->template, CKA_MODULUS, &modulus ); rc &= template_attribute_find( key_obj->template, CKA_PUBLIC_EXPONENT, &pub_exp ); if (rc == FALSE) { return NULL; } // Create an RSA key struct to return rsa = RSA_new(); if (rsa == NULL) return NULL; RSA_blinding_off(rsa); // Create and init BIGNUM structs to stick in the RSA struct bn_mod = BN_new(); bn_exp = BN_new(); if (bn_exp == NULL || bn_mod == NULL) { if (bn_mod) free(bn_mod); if (bn_exp) free(bn_exp); RSA_free(rsa); return NULL; } // Convert from strings to BIGNUMs and stick them in the RSA struct BN_bin2bn((unsigned char *)modulus->pValue, modulus->ulValueLen, bn_mod); rsa->n = bn_mod; BN_bin2bn((unsigned char *)pub_exp->pValue, pub_exp->ulValueLen, bn_exp); rsa->e = bn_exp; return (void *)rsa; } void * rsa_convert_private_key(OBJECT *key_obj) { CK_ATTRIBUTE * modulus = NULL; CK_ATTRIBUTE * priv_exp = NULL; CK_ATTRIBUTE * prime1 = NULL; CK_ATTRIBUTE * prime2 = NULL; CK_ATTRIBUTE * exp1 = NULL; CK_ATTRIBUTE * exp2 = NULL; CK_ATTRIBUTE * coeff = NULL; CK_BBOOL rc; RSA *rsa; BIGNUM *bn_mod, *bn_priv_exp, *bn_p1, *bn_p2, *bn_e1, *bn_e2, *bn_cf; rc = template_attribute_find( key_obj->template, CKA_MODULUS, &modulus ); rc &= template_attribute_find( key_obj->template, CKA_PRIVATE_EXPONENT, &priv_exp ); rc &= template_attribute_find( key_obj->template, CKA_PRIME_1, &prime1 ); rc &= template_attribute_find( key_obj->template, CKA_PRIME_2, &prime2 ); rc &= template_attribute_find( key_obj->template, CKA_EXPONENT_1, &exp1 ); rc &= template_attribute_find( key_obj->template, CKA_EXPONENT_2, &exp2 ); rc &= template_attribute_find( key_obj->template, CKA_COEFFICIENT, &coeff ); if ( !prime2 && !modulus ){ return NULL; } // Create and init all the RSA and BIGNUM structs we need. rsa = RSA_new(); if (rsa == NULL) return NULL; RSA_blinding_off(rsa); bn_mod = BN_new(); bn_priv_exp = BN_new(); bn_p1 = BN_new(); bn_p2 = BN_new(); bn_e1 = BN_new(); bn_e2 = BN_new(); bn_cf = BN_new(); if ((bn_cf == NULL) || (bn_e2 == NULL) || (bn_e1 == NULL) || (bn_p2 == NULL) || (bn_p1 == NULL) || (bn_priv_exp == NULL) || (bn_mod == NULL)) { if (rsa) RSA_free(rsa); if (bn_mod) BN_free(bn_mod); if (bn_priv_exp) BN_free(bn_priv_exp); if (bn_p1) BN_free(bn_p1); if (bn_p2) BN_free(bn_p2); if (bn_e1) BN_free(bn_e1); if (bn_e2) BN_free(bn_e2); if (bn_cf) BN_free(bn_cf); return NULL; } // CRT key? if ( prime1){ if (!prime2 || !exp1 ||!exp2 || !coeff) { return NULL; } // Even though this is CRT key, OpenSSL requires the // modulus and exponents filled in or encrypt and decrypt will // not work BN_bin2bn((unsigned char *)modulus->pValue, modulus->ulValueLen, bn_mod); rsa->n = bn_mod; BN_bin2bn((unsigned char *)priv_exp->pValue, priv_exp->ulValueLen, bn_priv_exp); rsa->d = bn_priv_exp; BN_bin2bn((unsigned char *)prime1->pValue, prime1->ulValueLen, bn_p1); rsa->p = bn_p1; BN_bin2bn((unsigned char *)prime2->pValue, prime2->ulValueLen, bn_p2); rsa->q = bn_p2; BN_bin2bn((unsigned char *)exp1->pValue, exp1->ulValueLen, bn_e1); rsa->dmp1 = bn_e1; BN_bin2bn((unsigned char *)exp2->pValue, exp2->ulValueLen, bn_e2); rsa->dmq1 = bn_e2; BN_bin2bn((unsigned char *)coeff->pValue, coeff->ulValueLen, bn_cf); rsa->iqmp = bn_cf; return rsa; } else { // must be a non-CRT key if (!priv_exp) { return NULL; } BN_bin2bn((unsigned char *)modulus->pValue, modulus->ulValueLen, bn_mod); rsa->n = bn_mod; BN_bin2bn((unsigned char *)priv_exp->pValue, priv_exp->ulValueLen, bn_priv_exp); rsa->d = bn_priv_exp; } return (void *)rsa; } #define RNG_BUF_SIZE 100 // This function is only required if public key cryptography // has been selected in your variant set up. // Set a mutex in this function and get a cache; // using the ICA device to get random numbers a byte at a // time is VERY slow.. Keygen is gated by this function. unsigned char nextRandom (void) { static unsigned char buffer[RNG_BUF_SIZE]; unsigned char byte; static int used = (RNG_BUF_SIZE); // protected access by the mutex pthread_mutex_lock(&nextmutex); if (used >= RNG_BUF_SIZE){ rng_generate(buffer,sizeof(buffer)); used = 0; } byte = buffer[used++]; pthread_mutex_unlock(&nextmutex); return((unsigned char)byte); } CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { CK_ATTRIBUTE * publ_exp = NULL; CK_ATTRIBUTE * attr = NULL; CK_ULONG mod_bits; CK_BBOOL flag; CK_RV rc; CK_ULONG BNLength; RSA *rsa; BIGNUM *bignum; CK_BYTE *ssl_ptr; unsigned long e = 0; flag = template_attribute_find( publ_tmpl, CKA_MODULUS_BITS, &attr ); if (!flag){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; // should never happen } mod_bits = *(CK_ULONG *)attr->pValue; // we don't support less than 1024 bit keys in the sw if (mod_bits < 512 || mod_bits > 4096) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); return CKR_KEY_SIZE_RANGE; } flag = template_attribute_find( publ_tmpl, CKA_PUBLIC_EXPONENT, &publ_exp ); if (!flag){ TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } if (publ_exp->ulValueLen > sizeof(CK_ULONG)) { TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID)); return CKR_ATTRIBUTE_VALUE_INVALID; } if (publ_exp->ulValueLen == sizeof(CK_ULONG)) { e = *(CK_ULONG *)publ_exp->pValue; } else { memcpy(&e, publ_exp->pValue, publ_exp->ulValueLen); if (sizeof(CK_ULONG) == 4) e = le32toh(e); else e = le64toh(e); } rsa = RSA_generate_key(mod_bits, e, NULL, NULL); if (rsa == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } RSA_blinding_off(rsa); // Now fill in the objects.. // // modulus: n // bignum = rsa->n; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc(BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_MODULUS, ssl_ptr, BNLength, &attr ); // in bytes if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( publ_tmpl, attr ); free(ssl_ptr); // Public Exponent bignum = rsa->e; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc(BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_PUBLIC_EXPONENT, ssl_ptr, BNLength, &attr ); // in bytes if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( publ_tmpl, attr ); /* add public exponent to the private template. Its already an attribute in the * private template at this point, we're just making its value correct */ rc = build_attribute( CKA_PUBLIC_EXPONENT, ssl_ptr, BNLength, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); free(ssl_ptr); // local = TRUE // flag = TRUE; rc = build_attribute( CKA_LOCAL, &flag, sizeof(CK_BBOOL), &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( publ_tmpl, attr ); // // now, do the private key // // Cheat here and put the whole original key into the CKA_VALUE... remember // to force the system to not return this for RSA keys.. // Add the modulus to the private key information bignum = rsa->n; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc(BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_MODULUS, ssl_ptr, BNLength ,&attr ); // in bytes if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); free(ssl_ptr); // Private Exponent bignum = rsa->d; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc( BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_PRIVATE_EXPONENT, ssl_ptr, BNLength, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); free(ssl_ptr); // prime #1: p // bignum = rsa->p; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc(BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_PRIME_1, ssl_ptr, BNLength, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); free(ssl_ptr); // prime #2: q // bignum = rsa->q; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc(BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_PRIME_2, ssl_ptr, BNLength, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); free(ssl_ptr); // exponent 1: d mod(p-1) // bignum = rsa->dmp1; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc(BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_EXPONENT_1, ssl_ptr, BNLength, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); free(ssl_ptr); // exponent 2: d mod(q-1) // bignum = rsa->dmq1; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc(BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_EXPONENT_2, ssl_ptr, BNLength, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); free(ssl_ptr); // CRT coefficient: q_inverse mod(p) // bignum = rsa->iqmp; BNLength = BN_num_bytes(bignum); ssl_ptr = malloc(BNLength); if (ssl_ptr == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } BNLength = BN_bn2bin(bignum, ssl_ptr); rc = build_attribute( CKA_COEFFICIENT, ssl_ptr, BNLength, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); free(ssl_ptr); flag = TRUE; rc = build_attribute( CKA_LOCAL, &flag, sizeof(CK_BBOOL), &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto done; } template_update_attribute( priv_tmpl, attr ); done: RSA_free(rsa); return rc; } CK_RV token_specific_rsa_generate_keypair( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_RV rc; rc = os_specific_rsa_keygen(publ_tmpl,priv_tmpl); if (rc != CKR_OK) TRACE_DEVEL("os_specific_rsa_keygen failed\n"); return rc; } CK_RV os_specific_rsa_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, OBJECT * key_obj ) { CK_RV rc; RSA *rsa; int size; // Convert the local representation to an RSA representation rsa = (RSA *)rsa_convert_public_key(key_obj); if (rsa==NULL) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; return rc; } // Do an RSA public encryption size = RSA_public_encrypt(in_data_len, in_data, out_data, rsa, RSA_NO_PADDING); if (size == -1) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto done; } rc = CKR_OK; done: RSA_free(rsa); return rc; } CK_RV os_specific_rsa_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, OBJECT * key_obj ) { CK_RV rc; RSA *rsa; int size; // Convert the local key representation to an RSA key representaion rsa = (RSA *)rsa_convert_private_key(key_obj); if (rsa == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; return rc; } // Do the private decryption size = RSA_private_decrypt(in_data_len, in_data, out_data, rsa, RSA_NO_PADDING); if (size == -1) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto done; } rc = CKR_OK; done: RSA_free(rsa); return rc; } CK_RV token_specific_rsa_encrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; CK_ULONG modulus_bytes; CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; CK_ATTRIBUTE *attr = NULL; /* format the data */ if (!template_attribute_find(key_obj->template, CKA_MODULUS, &attr)) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } modulus_bytes = attr->ulValueLen; rc = rsa_format_block(in_data, in_data_len, clear, modulus_bytes, PKCS_BT_2); if (rc != CKR_OK) { TRACE_DEVEL("rsa_format_block failed\n"); return rc; } // Do an RSA public encryption rc = os_specific_rsa_encrypt(clear, modulus_bytes, cipher, key_obj); if (rc == CKR_OK) { memcpy(out_data, cipher, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } CK_RV token_specific_rsa_decrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE out[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; modulus_bytes = in_data_len; rc = os_specific_rsa_decrypt(in_data, modulus_bytes, out, key_obj); if (rc != CKR_OK) { TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); return rc; } rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_2); if (rc != CKR_OK) { TRACE_DEVEL("rsa_parse_block failed\n"); return rc; } /* * For PKCS #1 v1.5 padding, out_data_len must be less than * modulus_bytes - 11. */ if (*out_data_len > (modulus_bytes - 11)) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); rc = CKR_ENCRYPTED_DATA_LEN_RANGE; } return rc; } CK_RV token_specific_rsa_sign(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_RV rc; CK_ATTRIBUTE *attr = NULL; /* format the data */ if (!template_attribute_find(key_obj->template, CKA_MODULUS, &attr)) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } modulus_bytes = attr->ulValueLen; rc = rsa_format_block(in_data, in_data_len, data, modulus_bytes, PKCS_BT_1); if (rc != CKR_OK) { TRACE_DEVEL("rsa_format_block failed\n"); return rc; } /* signing is a private key operation --> decrypt */ rc = os_specific_rsa_decrypt(data, modulus_bytes, sig, key_obj); if (rc == CKR_OK) { memcpy(out_data, sig, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); return rc; } CK_RV token_specific_rsa_verify(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { CK_ATTRIBUTE *attr = NULL; CK_BYTE out[MAX_RSA_KEYLEN], out_data[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes, out_data_len; CK_BBOOL flag; CK_RV rc; out_data_len = MAX_RSA_KEYLEN; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; // verifying is a public key operation --> encrypt // rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); if (rc == CKR_OK) { rc = rsa_parse_block(out, modulus_bytes, out_data, &out_data_len, PKCS_BT_1); if (rc == CKR_OK) { if (in_data_len != out_data_len) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } if (memcmp(in_data, out_data, out_data_len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } } else if (rc == CKR_ENCRYPTED_DATA_INVALID ) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } } else TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return rc; } CK_RV token_specific_rsa_verify_recover(CK_BYTE *signature, CK_ULONG sig_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_ATTRIBUTE *attr = NULL; CK_BYTE out[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; // verifying is a public key operation --> encrypt // rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); if (rc != CKR_OK) { TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_1); if (rc == CKR_ENCRYPTED_DATA_INVALID ) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } else if (rc != CKR_OK) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); } return rc; } CK_RV token_specific_rsa_pss_sign(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *sig, CK_ULONG *sig_len) { CK_RV rc; CK_ULONG modbytes; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; OBJECT *key_obj = NULL; CK_BYTE *emdata = NULL; CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; /* check the arguments */ if (!in_data || !sig) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!ctx) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } pssParms = (CK_RSA_PKCS_PSS_PARAMS *)ctx->mech.pParameter; /* get the key */ rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); return rc; } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modbytes = attr->ulValueLen; emdata = (CK_BYTE *)malloc(modbytes); if (emdata == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = emsa_pss_encode(pssParms, in_data, in_data_len, emdata, &modbytes); if (rc != CKR_OK) goto done; /* signing is a private key operation --> decrypt */ rc = os_specific_rsa_decrypt(emdata, modbytes, sig, key_obj); if (rc == CKR_OK) *sig_len = modbytes; else TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); done: if (emdata) free(emdata); return rc; } CK_RV token_specific_rsa_pss_verify(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_RV rc; CK_ULONG modbytes; OBJECT *key_obj = NULL; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_BYTE out[MAX_RSA_KEYLEN]; CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; /* check the arguments */ if (!in_data || !signature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!ctx) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } pssParms = (CK_RSA_PKCS_PSS_PARAMS *)ctx->mech.pParameter; /* get the key */ rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); return rc; } /* verify is a public key operation ... encrypt */ rc = os_specific_rsa_encrypt(signature, sig_len, out, key_obj); if (rc != CKR_OK) { TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modbytes = attr->ulValueLen; /* call the pss verify scheme */ rc = emsa_pss_verify(pssParms, in_data, in_data_len, out, modbytes); return rc; } CK_RV token_specific_rsa_x509_encrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_ATTRIBUTE *attr = NULL; CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; // prepad with zeros // memset(clear, 0x0, modulus_bytes - in_data_len); memcpy( &clear[modulus_bytes - in_data_len], in_data, in_data_len ); rc = os_specific_rsa_encrypt(clear, modulus_bytes, cipher, key_obj); if (rc == CKR_OK) { memcpy(out_data, cipher, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } CK_RV token_specific_rsa_x509_decrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_ATTRIBUTE *attr = NULL; CK_BYTE out[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = os_specific_rsa_decrypt(in_data, modulus_bytes, out, key_obj); if (rc == CKR_OK) { memcpy(out_data, out, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); return rc; } CK_RV token_specific_rsa_x509_sign(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_ATTRIBUTE *attr = NULL; CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; // prepad with zeros // memset(data, 0x0, modulus_bytes - in_data_len); memcpy(&data[modulus_bytes - in_data_len], in_data, in_data_len); rc = os_specific_rsa_decrypt(data, modulus_bytes, sig, key_obj); if (rc == CKR_OK) { memcpy(out_data, sig, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); return rc; } CK_RV token_specific_rsa_x509_verify(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { CK_ATTRIBUTE *attr = NULL; CK_BYTE out[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); if (rc == CKR_OK) { CK_ULONG pos1, pos2, len; // it should be noted that in_data_len is not necessarily // the same as the modulus length // for (pos1=0; pos1 < in_data_len; pos1++) if (in_data[pos1] != 0) break; for (pos2=0; pos2 < modulus_bytes; pos2++) if (out[pos2] != 0) break; // at this point, pos1 and pos2 point to the first non-zero // bytes in the input data and the decrypted signature // (the recovered data), respectively. if ((in_data_len - pos1) != (modulus_bytes - pos2)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } len = in_data_len - pos1; if (memcmp(&in_data[pos1], &out[pos2], len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } return CKR_OK; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } CK_RV token_specific_rsa_x509_verify_recover(CK_BYTE *signature, CK_ULONG sig_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_ATTRIBUTE *attr = NULL; CK_BYTE out[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_RV rc; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); if (rc == CKR_OK) { memcpy(out_data, out, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } CK_RV token_specific_rsa_oaep_encrypt(ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *hash, CK_ULONG hlen) { CK_RV rc; CK_BYTE cipher[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_BYTE *em_data = NULL; OBJECT *key_obj = NULL; CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; if (!in_data || !out_data || !hash) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR)ctx->mech.pParameter; rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); return rc; } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; /* pkcs1v2.2, section 7.1.1 Step 2: * EME-OAEP encoding. */ em_data = (CK_BYTE *)malloc(modulus_bytes*sizeof(CK_BYTE)); if (em_data == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = encode_eme_oaep(in_data, in_data_len, em_data, modulus_bytes, oaepParms->mgf, hash, hlen); if (rc != CKR_OK) goto done; rc = os_specific_rsa_encrypt(em_data, modulus_bytes, cipher, key_obj); if (rc == CKR_OK) { memcpy(out_data, cipher, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); done: if (em_data) free(em_data); return rc; } CK_RV token_specific_rsa_oaep_decrypt(ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *hash, CK_ULONG hlen) { CK_RV rc; CK_BYTE *decr_data = NULL; OBJECT *key_obj = NULL; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; if (!in_data || !out_data || !hash) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR)ctx->mech.pParameter; rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); return rc; } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else *out_data_len = attr->ulValueLen; decr_data = (CK_BYTE *)malloc(in_data_len); if (decr_data == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = os_specific_rsa_decrypt(in_data, in_data_len, decr_data, key_obj); if (rc != CKR_OK) return rc; /* pkcs1v2.2, section 7.1.2 Step 2: * EME-OAEP decoding. */ rc = decode_eme_oaep(decr_data, in_data_len, out_data, out_data_len, oaepParms->mgf, hash, hlen); if (decr_data) free(decr_data); return rc; } CK_RV token_specific_aes_key_gen( CK_BYTE *key, CK_ULONG len, CK_ULONG keysize ) { return rng_generate(key, len); } CK_RV token_specific_aes_ecb( CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { AES_KEY ssl_aes_key; unsigned int i; CK_ATTRIBUTE *attr = NULL; /* There's a previous check that in_data_len % AES_BLOCK_SIZE == 0, * so this is fine */ CK_ULONG loops = (CK_ULONG)(in_data_len/AES_BLOCK_SIZE); memset( &ssl_aes_key, 0, sizeof(AES_KEY)); // get key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key\n"); return CKR_FUNCTION_FAILED; } // AES_ecb_encrypt encrypts only a single block, so we have to break up the // input data here if (encrypt) { AES_set_encrypt_key((unsigned char *)attr->pValue, (attr->ulValueLen*8), &ssl_aes_key); for( i=0; ipValue, (attr->ulValueLen*8), &ssl_aes_key); for( i=0; itemplate, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key\n"); return CKR_FUNCTION_FAILED; } // AES_cbc_encrypt chunks the data into AES_BLOCK_SIZE blocks, unlike // AES_ecb_encrypt, so no looping required. if (encrypt) { AES_set_encrypt_key((unsigned char *)attr->pValue, (attr->ulValueLen*8), &ssl_aes_key); AES_cbc_encrypt((unsigned char *)in_data, (unsigned char *)out_data, in_data_len, &ssl_aes_key, init_v, AES_ENCRYPT); } else { AES_set_decrypt_key((unsigned char *)attr->pValue, (attr->ulValueLen*8), &ssl_aes_key); AES_cbc_encrypt((unsigned char *)in_data, (unsigned char *)out_data, in_data_len, &ssl_aes_key, init_v, AES_DECRYPT); } *out_data_len = in_data_len; return CKR_OK; } /* Begin code contributed by Corrent corp. */ // This computes DH shared secret, where: // Output: z is computed shared secret // Input: y is other party's public key // x is private key // p is prime // All length's are in number of bytes. All data comes in as Big Endian. CK_RV token_specific_dh_pkcs_derive( CK_BYTE *z, CK_ULONG *z_len, CK_BYTE *y, CK_ULONG y_len, CK_BYTE *x, CK_ULONG x_len, CK_BYTE *p, CK_ULONG p_len) { CK_RV rc ; BIGNUM *bn_z, *bn_y, *bn_x, *bn_p ; BN_CTX *ctx; // Create and Init the BIGNUM structures. bn_y = BN_new() ; bn_x = BN_new() ; bn_p = BN_new() ; bn_z = BN_new() ; if (bn_z == NULL || bn_p == NULL || bn_x == NULL || bn_y == NULL) { if (bn_y) BN_free(bn_y); if (bn_x) BN_free(bn_x); if (bn_p) BN_free(bn_p); if (bn_z) BN_free(bn_z); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // Initialize context ctx=BN_CTX_new(); if (ctx == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // Add data into these new BN structures BN_bin2bn((unsigned char *)y, y_len, bn_y); BN_bin2bn((unsigned char *)x, x_len, bn_x); BN_bin2bn((unsigned char *)p, p_len, bn_p); rc = BN_mod_exp(bn_z,bn_y,bn_x,bn_p,ctx); if (rc == 0) { BN_free(bn_z); BN_free(bn_y); BN_free(bn_x); BN_free(bn_p); BN_CTX_free(ctx); TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } *z_len = BN_num_bytes(bn_z); BN_bn2bin(bn_z, z); BN_free(bn_z); BN_free(bn_y); BN_free(bn_x); BN_free(bn_p); BN_CTX_free(ctx); return CKR_OK; } /* end token_specific_dh_pkcs_derive() */ // This computes DH key pair, where: // Output: priv_tmpl is generated private key // pub_tmpl is computed public key // Input: pub_tmpl is public key (prime and generator) // All length's are in number of bytes. All data comes in as Big Endian. CK_RV token_specific_dh_pkcs_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_BBOOL rc; CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *temp_attr = NULL ; CK_ATTRIBUTE *value_bits_attr = NULL; CK_BYTE *temp_byte; CK_ULONG temp_bn_len ; DH *dh ; BIGNUM *bn_p ; BIGNUM *bn_g ; BIGNUM *temp_bn ; rc = template_attribute_find( publ_tmpl, CKA_PRIME, &prime_attr ); rc &= template_attribute_find( publ_tmpl, CKA_BASE, &base_attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_PRIME or CKA_BASE for the key\n"); return CKR_FUNCTION_FAILED; } if ((prime_attr->ulValueLen > 256) || (prime_attr->ulValueLen < 64)) { TRACE_ERROR("CKA_PRIME attribute value is invalid.\n"); return CKR_ATTRIBUTE_VALUE_INVALID; } dh = DH_new() ; if (dh == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // Create and init BIGNUM structs to stick in the DH struct bn_p = BN_new(); bn_g = BN_new(); if (bn_g == NULL || bn_p == NULL) { if (bn_g) BN_free(bn_g); if (bn_p) BN_free(bn_p); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } // Convert from strings to BIGNUMs and stick them in the DH struct BN_bin2bn((unsigned char *)prime_attr->pValue, prime_attr->ulValueLen, bn_p); dh->p = bn_p; BN_bin2bn((unsigned char *)base_attr->pValue, base_attr->ulValueLen, bn_g); dh->g = bn_g; // Generate the DH Key if (!DH_generate_key(dh)) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // Extract the public and private key components from the DH struct, // and insert them in the publ_tmpl and priv_tmpl // // pub_key // //temp_bn = BN_new(); temp_bn = dh->pub_key; temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte); rc = build_attribute( CKA_VALUE, temp_byte, temp_bn_len, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); return CKR_FUNCTION_FAILED; } template_update_attribute( publ_tmpl, temp_attr ); free(temp_byte); // // priv_key // //temp_bn = BN_new(); temp_bn = dh->priv_key; temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte); rc = build_attribute( CKA_VALUE, temp_byte, temp_bn_len, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); return CKR_FUNCTION_FAILED; } template_update_attribute( priv_tmpl, temp_attr ); free(temp_byte); // Update CKA_VALUE_BITS attribute in the private key value_bits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); value_bits_attr->type = CKA_VALUE_BITS; value_bits_attr->ulValueLen = sizeof(CK_ULONG); value_bits_attr->pValue = (CK_BYTE *)value_bits_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_bits_attr->pValue = 8*temp_bn_len; template_update_attribute( priv_tmpl, value_bits_attr ); // Add prime and base to the private key template rc = build_attribute( CKA_PRIME,(unsigned char *)prime_attr->pValue, prime_attr->ulValueLen, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); return CKR_FUNCTION_FAILED; } template_update_attribute( priv_tmpl, temp_attr ); rc = build_attribute( CKA_BASE,(unsigned char *)base_attr->pValue, base_attr->ulValueLen, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); return CKR_FUNCTION_FAILED; } template_update_attribute( priv_tmpl, temp_attr ); // Cleanup DH key DH_free(dh) ; return CKR_OK ; } /* end token_specific_dh_key_pair_gen() */ /* End code contributed by Corrent corp. */ MECH_LIST_ELEMENT mech_list[] = { {CKM_RSA_PKCS_KEY_PAIR_GEN, {512, 4096, CKF_GENERATE_KEY_PAIR}}, #if !(NODSA) {CKM_DSA_KEY_PAIR_GEN, {512, 1024, CKF_GENERATE_KEY_PAIR}}, #endif {CKM_DES_KEY_GEN, {8, 8, CKF_GENERATE}}, {CKM_DES3_KEY_GEN, {24, 24, CKF_GENERATE}}, #if !(NOCDMF) {CKM_CDMF_KEY_GEN, {0, 0, CKF_GENERATE}}, #endif {CKM_RSA_PKCS, {512, 4096, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP|CKF_SIGN|CKF_VERIFY| CKF_SIGN_RECOVER|CKF_VERIFY_RECOVER}}, {CKM_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA1_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA256_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA384_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA512_RSA_PKCS_PSS, {1024, 4096, CKF_SIGN|CKF_VERIFY}}, #if !(NOX509) {CKM_RSA_X_509, {512, 4096, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP| CKF_SIGN|CKF_VERIFY|CKF_SIGN_RECOVER| CKF_VERIFY_RECOVER}}, #endif {CKM_RSA_PKCS_OAEP, {1024, 4096, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, #if !(NOMD2) {CKM_MD2_RSA_PKCS, {512, 4096, CKF_SIGN|CKF_VERIFY}}, #endif #if !(NOMD5) {CKM_MD5_RSA_PKCS, {512, 4096, CKF_SIGN|CKF_VERIFY}}, #endif #if !(NOSHA1) {CKM_SHA1_RSA_PKCS, {512, 4096, CKF_SIGN|CKF_VERIFY}}, #endif #if !(NODSA) {CKM_DSA, {512, 1024, CKF_SIGN|CKF_VERIFY}}, #endif /* Begin code contributed by Corrent corp. */ #if !(NODH) {CKM_DH_PKCS_DERIVE, {512, 2048, CKF_DERIVE}}, {CKM_DH_PKCS_KEY_PAIR_GEN, {512, 2048, CKF_GENERATE_KEY_PAIR}}, #endif /* End code contributed by Corrent corp. */ {CKM_DES_ECB, {8, 8, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES_CBC, {8, 8, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES_CBC_PAD, {8, 8, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, #if !(NOCDMF) {CKM_CDMF_ECB, {0, 0, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_CDMF_CBC, {0, 0, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, #endif {CKM_DES3_ECB, {24, 24, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES3_CBC, {24, 24, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_DES3_CBC_PAD, {24, 24, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, #if !(NOSHA1) {CKM_SHA_1, {0, 0, CKF_DIGEST}}, {CKM_SHA_1_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA_1_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, #endif {CKM_SHA256, {0, 0, CKF_DIGEST}}, {CKM_SHA256_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA256_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA384, {0, 0, CKF_DIGEST}}, {CKM_SHA384_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA384_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA512, {0, 0, CKF_DIGEST}}, {CKM_SHA512_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_SHA512_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, #if !(NOMD2) {CKM_MD2, {0, 0, CKF_DIGEST}}, {CKM_MD2_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_MD2_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, #endif #if !(NOMD5) {CKM_MD5, {0, 0, CKF_DIGEST}}, {CKM_MD5_HMAC, {0, 0, CKF_SIGN|CKF_VERIFY}}, {CKM_MD5_HMAC_GENERAL, {0, 0, CKF_SIGN|CKF_VERIFY}}, #endif {CKM_SSL3_PRE_MASTER_KEY_GEN, {48, 48, CKF_GENERATE}}, {CKM_SSL3_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}}, {CKM_SSL3_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}}, {CKM_SSL3_MD5_MAC, {384, 384, CKF_SIGN|CKF_VERIFY}}, {CKM_SSL3_SHA1_MAC, {384, 384, CKF_SIGN|CKF_VERIFY}}, #if !(NOAES) {CKM_AES_KEY_GEN, {16, 32, CKF_GENERATE}}, {CKM_AES_ECB, {16, 32, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_AES_CBC, {16, 32, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {CKM_AES_CBC_PAD, {16, 32, CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, #endif {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_GENERATE}} }; CK_ULONG mech_list_len = (sizeof(mech_list) / sizeof(MECH_LIST_ELEMENT)); CK_RV token_specific_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { int rc; /* common/mech_list.c */ rc = ock_generic_get_mechanism_list(pMechanismList, pulCount); return rc; } CK_RV token_specific_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { int rc; /* common/mech_list.c */ rc = ock_generic_get_mechanism_info(type, pInfo); return rc; } CK_RV token_specific_sha_init(DIGEST_CONTEXT *ctx, CK_MECHANISM *mech) { int rc; EVP_MD_CTX *mdctx = NULL; mdctx = EVP_MD_CTX_create(); if (mdctx == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } switch(mech->mechanism) { case CKM_SHA_1: rc = EVP_DigestInit_ex(mdctx, EVP_sha1(), NULL); break; case CKM_SHA256: rc = EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); break; case CKM_SHA384: rc = EVP_DigestInit_ex(mdctx, EVP_sha384(), NULL); break; case CKM_SHA512: rc = EVP_DigestInit_ex(mdctx, EVP_sha512(), NULL); break; default: EVP_MD_CTX_destroy(mdctx); return CKR_MECHANISM_INVALID; } if (!rc) { EVP_MD_CTX_destroy(mdctx); ctx->context = NULL; return CKR_FUNCTION_FAILED; } else ctx->context = (CK_BYTE *)mdctx; return CKR_OK; } CK_RV token_specific_sha(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { int rc; CK_RV rv = CKR_OK; EVP_MD_CTX *mdctx; unsigned int hlen; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; mdctx = (EVP_MD_CTX *)ctx->context; switch(ctx->mech.mechanism) { case CKM_SHA_1: hlen = SHA1_HASH_SIZE; break; case CKM_SHA256: hlen = SHA2_HASH_SIZE; break; case CKM_SHA384: hlen = SHA3_HASH_SIZE; break; case CKM_SHA512: hlen = SHA5_HASH_SIZE; break; default: rv = CKR_MECHANISM_INVALID; goto done; } if (*out_data_len < hlen) return CKR_BUFFER_TOO_SMALL; if (!in_data || !out_data) { rv = CKR_ARGUMENTS_BAD; goto done; } rc = EVP_DigestUpdate(mdctx, in_data, in_data_len); if (!rc) { rv = CKR_FUNCTION_FAILED; goto done; } rc = EVP_DigestFinal_ex(mdctx, out_data, &hlen); if (!rc) rv = CKR_FUNCTION_FAILED; else *out_data_len = hlen; done: EVP_MD_CTX_destroy(mdctx); ctx->context = NULL; return rv; } CK_RV token_specific_sha_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { int rc; EVP_MD_CTX *mdctx; CK_RV rv = CKR_OK; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; mdctx = (EVP_MD_CTX *)ctx->context; if (!in_data) { rv = CKR_ARGUMENTS_BAD; goto error; } rc = EVP_DigestUpdate(mdctx, in_data, in_data_len); if (!rc) rv = CKR_FUNCTION_FAILED; else { ctx->context = (CK_BYTE *)mdctx; return CKR_OK; } error: EVP_MD_CTX_destroy(mdctx); ctx->context = NULL; return rv; } CK_RV token_specific_sha_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len) { int rc; EVP_MD_CTX *mdctx; CK_RV rv = CKR_OK; unsigned int hlen; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; mdctx = (EVP_MD_CTX *)ctx->context; if (!out_data) { rv = CKR_ARGUMENTS_BAD; goto done; } switch(ctx->mech.mechanism) { case CKM_SHA_1: hlen = SHA1_HASH_SIZE; break; case CKM_SHA256: hlen = SHA2_HASH_SIZE; break; case CKM_SHA384: hlen = SHA3_HASH_SIZE; break; case CKM_SHA512: hlen = SHA5_HASH_SIZE; break; default: rv = CKR_MECHANISM_INVALID; goto done; } if (*out_data_len < hlen) return CKR_BUFFER_TOO_SMALL; rc = EVP_DigestFinal_ex(mdctx, out_data, &hlen); if (!rc) rv = CKR_FUNCTION_FAILED; else *out_data_len = hlen; done: EVP_MD_CTX_destroy(mdctx); ctx->context = NULL; return rv; } static CK_RV softtok_hmac_init(SIGN_VERIFY_CONTEXT *ctx, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE Hkey) { int rc; OBJECT *key = NULL; CK_ATTRIBUTE *attr = NULL; EVP_MD_CTX *mdctx = NULL; EVP_PKEY *pkey = NULL; rc = object_mgr_find_in_map1(Hkey, &key); if (rc != CKR_OK) { TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, attr->pValue, attr->ulValueLen); if (pkey == NULL) { TRACE_ERROR("EVP_PKEY_new_mac_key() failed.\n"); return CKR_FUNCTION_FAILED; } mdctx = EVP_MD_CTX_create(); if (mdctx == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } switch(mech->mechanism) { case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA_1_HMAC: rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha1(), NULL, pkey); break; case CKM_SHA256_HMAC_GENERAL: case CKM_SHA256_HMAC: rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey); break; case CKM_SHA384_HMAC_GENERAL: case CKM_SHA384_HMAC: rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha384(), NULL, pkey); break; case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_HMAC: rc = EVP_DigestSignInit(mdctx, NULL, EVP_sha512(), NULL, pkey); break; default: EVP_MD_CTX_destroy(mdctx); TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } if (rc != 1) { EVP_MD_CTX_destroy(mdctx); ctx->context = NULL; TRACE_ERROR("EVP_DigestSignInit failed.\n"); return CKR_FUNCTION_FAILED; } else ctx->context = (CK_BYTE *)mdctx; return CKR_OK; } CK_RV token_specific_hmac_sign_init (SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE Hkey) { return softtok_hmac_init(&sess->sign_ctx, mech, Hkey); } CK_RV token_specific_hmac_verify_init (SESSION *sess, CK_MECHANISM *mech, CK_OBJECT_HANDLE Hkey) { return softtok_hmac_init(&sess->verify_ctx, mech, Hkey); } static CK_RV softtok_hmac(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG *sig_len, CK_BBOOL sign) { int rc; size_t mac_len, len; unsigned char mac[MAX_SHA_HASH_SIZE]; EVP_MD_CTX *mdctx = NULL; CK_RV rv = CKR_OK; CK_BBOOL general = FALSE; if (!ctx || !ctx->context) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } if (sign && !sig_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } switch(ctx->mech.mechanism) { case CKM_SHA_1_HMAC_GENERAL: general = TRUE; case CKM_SHA_1_HMAC: mac_len = SHA1_HASH_SIZE; break; case CKM_SHA256_HMAC_GENERAL: general = TRUE; case CKM_SHA256_HMAC: mac_len = SHA2_HASH_SIZE; break; case CKM_SHA384_HMAC_GENERAL: general = TRUE; case CKM_SHA384_HMAC: mac_len = SHA3_HASH_SIZE; break; case CKM_SHA512_HMAC_GENERAL: general = TRUE; case CKM_SHA512_HMAC: mac_len = SHA5_HASH_SIZE; break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } mdctx = (EVP_MD_CTX *)ctx->context; rc = EVP_DigestSignUpdate(mdctx, in_data, in_data_len); if (rc != 1) { TRACE_ERROR("EVP_DigestSignUpdate failed.\n"); rv = CKR_FUNCTION_FAILED; goto done; } rc = EVP_DigestSignFinal(mdctx, mac, &mac_len); if (rc != 1) { TRACE_ERROR("EVP_DigestSignFinal failed.\n"); rv = CKR_FUNCTION_FAILED; goto done; } if (sign) { if (general) *sig_len = *(CK_ULONG *)ctx->mech.pParameter; else *sig_len = mac_len; memcpy(signature, mac, *sig_len); } else { if (general) len = *(CK_ULONG *)ctx->mech.pParameter; else len = mac_len; if (memcmp(signature, mac, len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rv = CKR_SIGNATURE_INVALID; } } done: EVP_MD_CTX_destroy(mdctx); ctx->context = NULL; return rv; } CK_RV token_specific_hmac_sign(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG *sig_len) { return softtok_hmac(&sess->sign_ctx, in_data, in_data_len, signature, sig_len, TRUE); } CK_RV token_specific_hmac_verify(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { return softtok_hmac(&sess->verify_ctx, in_data, in_data_len, signature, &sig_len, FALSE); } static CK_RV softtok_hmac_update(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BBOOL sign) { int rc; EVP_MD_CTX *mdctx = NULL; CK_RV rv = CKR_OK; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; mdctx = (EVP_MD_CTX *)ctx->context; rc = EVP_DigestSignUpdate(mdctx, in_data, in_data_len); if (rc != 1) { TRACE_ERROR("EVP_DigestSignUpdate failed.\n"); rv = CKR_FUNCTION_FAILED; } else { ctx->context = (CK_BYTE *)mdctx; return CKR_OK; } EVP_MD_CTX_destroy(mdctx); ctx->context = NULL; return rv; } CK_RV token_specific_hmac_sign_update(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len) { return softtok_hmac_update(&sess->sign_ctx, in_data, in_data_len, TRUE); } CK_RV token_specific_hmac_verify_update(SESSION *sess, CK_BYTE *in_data, CK_ULONG in_data_len) { return softtok_hmac_update(&sess->verify_ctx, in_data, in_data_len, FALSE); } static CK_RV softtok_hmac_final(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *signature, CK_ULONG *sig_len, CK_BBOOL sign) { int rc; size_t mac_len, len; unsigned char mac[MAX_SHA_HASH_SIZE]; EVP_MD_CTX *mdctx = NULL; CK_RV rv = CKR_OK; CK_BBOOL general = FALSE; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; if (sign && !sig_len) { TRACE_ERROR("%s received bad argument(s)\n", __FUNCTION__); return CKR_FUNCTION_FAILED; } switch(ctx->mech.mechanism) { case CKM_SHA_1_HMAC_GENERAL: general = TRUE; case CKM_SHA_1_HMAC: mac_len = SHA1_HASH_SIZE; break; case CKM_SHA256_HMAC_GENERAL: general = TRUE; case CKM_SHA256_HMAC: mac_len = SHA2_HASH_SIZE; break; case CKM_SHA384_HMAC_GENERAL: general = TRUE; case CKM_SHA384_HMAC: mac_len = SHA3_HASH_SIZE; break; case CKM_SHA512_HMAC_GENERAL: general = TRUE; case CKM_SHA512_HMAC: mac_len = SHA5_HASH_SIZE; break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } mdctx = (EVP_MD_CTX *)ctx->context; rc = EVP_DigestSignFinal(mdctx, mac, &mac_len); if (rc != 1) { TRACE_ERROR("EVP_DigestSignFinal failed.\n"); rv = CKR_FUNCTION_FAILED; goto done; } if (sign) { if (general) *sig_len = *(CK_ULONG *)ctx->mech.pParameter; else *sig_len = mac_len; memcpy(signature, mac, *sig_len); } else { if (general) len = *(CK_ULONG *)ctx->mech.pParameter; else len = mac_len; if (memcmp(signature, mac, len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); rv = CKR_SIGNATURE_INVALID; } } done: EVP_MD_CTX_destroy(mdctx); ctx->context = NULL; return rv; } CK_RV token_specific_hmac_sign_final(SESSION *sess, CK_BYTE *signature, CK_ULONG *sig_len) { return softtok_hmac_final(&sess->sign_ctx, signature, sig_len, TRUE); } CK_RV token_specific_hmac_verify_final(SESSION *sess, CK_BYTE *signature, CK_ULONG sig_len) { return softtok_hmac_final(&sess->verify_ctx, signature, &sig_len, FALSE); } CK_RV token_specific_generic_secret_key_gen(TEMPLATE *tmpl) { CK_ATTRIBUTE *attr = NULL; CK_ATTRIBUTE *gkey = NULL; CK_RV rc = CKR_OK; CK_BYTE secret_key[MAX_GENERIC_KEY_SIZE]; CK_ULONG key_length = 0; CK_ULONG key_length_in_bits = 0; rc = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr); if (rc == FALSE) { TRACE_ERROR("CKA_VALUE_LEN missing in (HMAC) key template\n"); return CKR_TEMPLATE_INCOMPLETE; } key_length = *(CK_ULONG *)attr->pValue; //app specified key length in bytes key_length_in_bits = key_length * 8; /* After looking at fips cavs test vectors for HMAC ops, * it was decided that the key length should fall between * 80 and 2048 bits inclusive. openssl does not explicitly * specify limits to key sizes for secret keys */ if ((key_length_in_bits < 80) || (key_length_in_bits > 2048 )) { TRACE_ERROR("Generic secret key size of %lu bits not within" " required range of 80-2048 bits\n", key_length_in_bits); return CKR_KEY_SIZE_RANGE; } rc = rng_generate(secret_key, key_length); if (rc != CKR_OK) { TRACE_DEVEL("Generic secret key generation failed.\n"); return rc; } rc = build_attribute(CKA_VALUE, secret_key, key_length, &gkey); if (rc != CKR_OK) { TRACE_DEVEL("build_attribute(CKA_VALUE) failed\n"); return rc; } rc = template_update_attribute(tmpl, gkey); if (rc != CKR_OK) TRACE_DEVEL("template_update_attribute(CKA_VALUE) failed.\n"); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/soft_stdll/tok_struct.h0000644000175000017500000004463612630407154022524 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ // SAB FIXME need to figure out a better way... // // to get the variant dependency out #ifndef __TOK_STRUCT_H #define __TOK_STRUCT_H #include #include "tok_spec_struct.h" // #define PK_LITE_DIR "/etc/pkcs11/lite" // // #define PK_DIR PK_LITE_DIR // #define SUB_DIR "lite" // // // #define DBGTAG "ICA_STDLL_Debug" // // // #ifndef SW_CONFIG_PATH #ifndef CONFIG_PATH #warning CONFIG_PATH not set, using default (/usr/local/var/lib/opencryptoki) #define CONFIG_PATH "/usr/local/var/lib/opencryptoki" #endif // #ifndef CONFIG_PATH #define SW_CONFIG_PATH CONFIG_PATH "/swtok" #endif // #ifndef SW_CONFIG_PATH token_spec_t token_specific = { SW_CONFIG_PATH, "swtok", 0, // keysize // Token data info: { FALSE, // Don't use per guest data store TRUE, // Use master key CKM_DES3_CBC, // Data store encryption "12345678", // Default initialization vector for pins "10293847", // Default initialization vector for objects }, NULL, // t_creatlock NULL, // t_attach_shm &token_specific_init, NULL, // init_token_data NULL, // load_token_data NULL, // save_token_data NULL, // random number generator &token_specific_final, NULL, // init_token NULL, // login NULL, // logout NULL, // init_pin NULL, // set_pin // DES &token_specific_des_key_gen, &token_specific_des_ecb, &token_specific_des_cbc, // Triple DES &token_specific_tdes_ecb, &token_specific_tdes_cbc, NULL, // des3_ofb NULL, // des3_cfb NULL, // des3_mac // RSA &token_specific_rsa_decrypt, &token_specific_rsa_encrypt, &token_specific_rsa_sign, &token_specific_rsa_verify, &token_specific_rsa_verify_recover, &token_specific_rsa_x509_decrypt, &token_specific_rsa_x509_encrypt, &token_specific_rsa_x509_sign, &token_specific_rsa_x509_verify, &token_specific_rsa_x509_verify_recover, &token_specific_rsa_oaep_decrypt, &token_specific_rsa_oaep_encrypt, &token_specific_rsa_pss_sign, &token_specific_rsa_pss_verify, &token_specific_rsa_generate_keypair, // Elliptic Curve NULL, // ec_sign NULL, // ec_verify NULL, // ec_generate_keypair /* Begin code contributed by Corrent corp. */ // DH &token_specific_dh_pkcs_derive, &token_specific_dh_pkcs_key_pair_gen, /* End code contributed by Corrent corp. */ &token_specific_sha_init, &token_specific_sha, &token_specific_sha_update, &token_specific_sha_final, // HMAC &token_specific_hmac_sign_init, &token_specific_hmac_sign, &token_specific_hmac_sign_update, &token_specific_hmac_sign_final, &token_specific_hmac_verify_init, &token_specific_hmac_verify, &token_specific_hmac_verify_update, &token_specific_hmac_verify_final, &token_specific_generic_secret_key_gen, // AES &token_specific_aes_key_gen, &token_specific_aes_ecb, &token_specific_aes_cbc, NULL, // aes_ctr NULL, // aes_gcm_init NULL, // aes_gcm NULL, // aes_gcm_update NULL, // aes_gcm_final NULL, // aes_ofb NULL, // aes_cfb NULL, // aes_mac // DSA NULL, // dsa_generate_keypair NULL, // dsa_sign NULL, // dsa_verify &token_specific_get_mechanism_list, &token_specific_get_mechanism_info, NULL // object_add }; #endif opencryptoki+dfsg/usr/lib/pkcs11/soft_stdll/Makefile.am0000644000175000017500000000502712630407154022175 0ustar xnoxxnoxnobase_lib_LTLIBRARIES = opencryptoki/stdll/libpkcs11_sw.la opencryptoki_stdll_libpkcs11_sw_la_LDFLAGS = -shared -Wl,-Bsymbolic \ -lc -lpthread -lcrypto -lrt # Not all versions of automake observe libname_CFLAGS opencryptoki_stdll_libpkcs11_sw_la_CFLAGS = -DDEV -D_THREAD_SAFE \ -DSHALLOW=0 -DSWTOK=1 -DLITE=0 \ -DNOCDMF -DNOMD2 -DNODSA -DNORIPE \ -fPIC \ -I/usr/include -I. \ -I../../../include/pkcs11/stdll \ -I../../../include/pkcs11 \ -I../common -DSTDLL_NAME=\"swtok\" opencryptoki_stdll_libpkcs11_sw_la_SOURCES = ../common/asn1.c \ ../common/btree.c \ ../common/cert.c \ ../common/hwf_obj.c \ ../common/dp_obj.c \ ../common/data_obj.c \ ../common/decr_mgr.c \ ../common/dig_mgr.c \ ../common/encr_mgr.c \ ../common/globals.c \ ../common/sw_crypt.c \ ../common/loadsave.c \ ../common/key.c \ ../common/key_mgr.c \ ../common/mech_aes.c \ ../common/mech_des.c \ ../common/mech_des3.c \ ../common/mech_dh.c \ ../common/mech_md5.c \ ../common/mech_md2.c \ ../common/mech_rng.c \ ../common/mech_rsa.c \ ../common/mech_sha.c \ ../common/mech_ssl3.c \ ../common/mech_ec.c \ ../common/new_host.c \ ../common/obj_mgr.c \ ../common/object.c \ ../common/sess_mgr.c \ ../common/sign_mgr.c \ ../common/template.c \ ../common/p11util.c \ ../common/utility.c \ ../common/verify_mgr.c \ ../common/trace.c \ ../common/mech_list.c \ ../common/shared_memory.c \ soft_specific.c install-data-hook: cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ ln -sf libpkcs11_sw.so PKCS11_SW.so $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/opencryptoki/swtok/TOK_OBJ $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/swtok/TOK_OBJ $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/swtok $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/swtok/TOK_OBJ $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/swtok $(MKDIR_P) $(DESTDIR)$(lockdir)/swtok $(CHGRP) pkcs11 $(DESTDIR)$(lockdir)/swtok $(CHMOD) 0770 $(DESTDIR)$(lockdir)/swtok uninstall-hook: if test -d $(DESTDIR)$(libdir)/opencryptoki/stdll; then \ cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ rm -f PKCS11_SW.so; fi opencryptoki+dfsg/usr/lib/pkcs11/ica_s390_stdll/0000755000175000017500000000000012630407154020474 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h0000644000175000017500000004346512630407154023062 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2002 */ // SAB FIXME need to figure out a better way... // // to get the variant dependency out #ifndef __TOK_STRUCT_H #define __TOK_STRUCT_H #include #include "tok_spec_struct.h" #ifndef LITE_CONFIG_PATH #ifndef CONFIG_PATH #warning CONFIG_PATH not set, using default (/usr/local/var/lib/opencryptoki) #define CONFIG_PATH "/usr/local/var/lib/opencryptoki" #endif // #ifndef CONFIG_PATH #define LITE_CONFIG_PATH CONFIG_PATH "/lite" #endif // #ifndef LITE_CONFIG_PATH token_spec_t token_specific = { LITE_CONFIG_PATH, "lite", 0, // keysize // Token data info: { FALSE, // Don't use per guest data store TRUE, // Use master key CKM_DES3_CBC, // Data store encryption "12345678", // Default initialization vector for pins "10293847", // Default initialization vector for objects }, NULL, // t_creatlock NULL, // t_attach_shm &token_specific_init, NULL, // init_token_data NULL, // load_token_data NULL, // save_token_data &token_specific_rng, &token_specific_final, NULL, // init_token NULL, // login NULL, // logout NULL, // init_pin NULL, // set_pin // DES &token_specific_des_key_gen, &token_specific_des_ecb, &token_specific_des_cbc, // Triple DES &token_specific_tdes_ecb, &token_specific_tdes_cbc, &token_specific_tdes_ofb, &token_specific_tdes_cfb, &token_specific_tdes_mac, // RSA &token_specific_rsa_decrypt, &token_specific_rsa_encrypt, &token_specific_rsa_sign, &token_specific_rsa_verify, &token_specific_rsa_verify_recover, &token_specific_rsa_x509_decrypt, &token_specific_rsa_x509_encrypt, &token_specific_rsa_x509_sign, &token_specific_rsa_x509_verify, &token_specific_rsa_x509_verify_recover, &token_specific_rsa_oaep_decrypt, &token_specific_rsa_oaep_encrypt, &token_specific_rsa_pss_sign, &token_specific_rsa_pss_verify, &token_specific_rsa_generate_keypair, // Elliptic Curve NULL, // ec_sign NULL, // ec_verify NULL, // ec_generate_keypaiir #ifndef NODH // DH &token_specific_dh_pkcs_derive, &token_specific_dh_pkcs_key_pair_gen, #else NULL, NULL, #endif // SHA &token_specific_sha_init, &token_specific_sha, &token_specific_sha_update, &token_specific_sha_final, //HMAC NULL, // hmac_sign_init NULL, // hmac_sign NULL, // hmac_sign_update NULL, // hmac_sign_final NULL, // hmac_verify_init NULL, // hmac_verify NULL, // hmac_verify_update NULL, // hmac_verify_final &token_specific_generic_secret_key_gen, // AES &token_specific_aes_key_gen, &token_specific_aes_ecb, &token_specific_aes_cbc, &token_specific_aes_ctr, &token_specific_aes_gcm_init, &token_specific_aes_gcm, &token_specific_aes_gcm_update, &token_specific_aes_gcm_final, &token_specific_aes_ofb, &token_specific_aes_cfb, &token_specific_aes_mac, // DSA NULL, // dsa_generate_keypair NULL, // dsa_sign NULL, // dsa_verify &token_specific_get_mechanism_list, &token_specific_get_mechanism_info, NULL // object_add }; #endif opencryptoki+dfsg/usr/lib/pkcs11/ica_s390_stdll/Makefile.am0000644000175000017500000000536612630407154022542 0ustar xnoxxnoxnobase_lib_LTLIBRARIES = opencryptoki/stdll/libpkcs11_ica.la opencryptoki_stdll_libpkcs11_ica_la_LDFLAGS = $(LCRYPTO) \ $(ICA_LIB_DIRS) \ -nostartfiles -shared \ -Wl,-Bsymbolic \ -Wl,-soname,$@ \ -Wl,-Bsymbolic -lc \ -lpthread -lica -ldl \ -lcrypto # Not all versions of automake observe libname_CFLAGS opencryptoki_stdll_libpkcs11_ica_la_CFLAGS = -DDEV \ -D_THREAD_SAFE -fPIC \ -DSHALLOW=0 -DSWTOK=0 \ -DLITE=1 -DNODH \ -DNOCDMF -DNOMD2 -DNODSA \ -DSTDLL_NAME=\"icatok\" \ -lrt opencryptoki_stdll_libpkcs11_ica_la_SOURCES = ../common/asn1.c \ ../common/btree.c \ ../common/cert.c \ ../common/hwf_obj.c \ ../common/dp_obj.c \ ../common/data_obj.c \ ../common/decr_mgr.c \ ../common/dig_mgr.c \ ../common/encr_mgr.c \ ../common/globals.c \ ../common/sw_crypt.c \ ../common/loadsave.c \ ../common/key.c \ ../common/key_mgr.c \ ../common/mech_des.c \ ../common/mech_des3.c \ ../common/mech_aes.c \ ../common/mech_md5.c \ ../common/mech_md2.c \ ../common/mech_rng.c \ ../common/mech_rsa.c \ ../common/mech_sha.c \ ../common/mech_ssl3.c \ ../common/mech_ec.c \ ../common/new_host.c \ ../common/obj_mgr.c \ ../common/object.c \ ../common/sess_mgr.c \ ../common/sign_mgr.c \ ../common/template.c \ ../common/p11util.c \ ../common/utility.c \ ../common/verify_mgr.c \ ../common/trace.c \ ../common/mech_list.c \ ../common/shared_memory.c \ ica_specific.c INCLUDES = $(ICA_INC_DIRS) -I. -I../../../include/pkcs11/stdll \ -I../../../include/pkcs11 -I../common -I../../../ica/inc \ -I../../../../ica/include -I.. -I../../../../ica/src/inc install-data-hook: cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ ln -sf libpkcs11_ica.so PKCS11_ICA.so $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/opencryptoki/lite/TOK_OBJ $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/lite/TOK_OBJ $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/lite $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/lite/TOK_OBJ $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/lite $(MKDIR_P) $(DESTDIR)$(lockdir)/lite $(CHGRP) pkcs11 $(DESTDIR)$(lockdir)/lite $(CHMOD) 0770 $(DESTDIR)$(lockdir)/lite uninstall-hook: if test -d $(DESTDIR)$(libdir)/opencryptoki/stdll; then \ cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ rm -f PKCS11_ICA.so; fi opencryptoki+dfsg/usr/lib/pkcs11/ica_s390_stdll/ica_specific.c0000755000175000017500000034033412630407154023253 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ /* Modified for S390 by Robert Burroughs */ #include #include // for memcmp() et al #include #include #ifndef NOAES #include #endif #ifndef NODH #include #endif #include "pkcs11types.h" #include "p11util.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "trace.h" #include "tok_specific.h" #include "tok_struct.h" #include "ica_specific.h" #include "ica_api.h" // declare the adapter open handle localy ICA_ADAPTER_HANDLE adapter_handle; // Linux really does not need these so we just dummy them up // so the common code across platforms is usable... #define KEYTYPE_MODEXPO 1 #define KEYTYPE_PKCSCRT 2 #define MAX_GENERIC_KEY_SIZE 256 CK_CHAR manuf[] = "IBM Corp."; CK_CHAR model[] = "IBM ICA "; CK_CHAR descr[] = "IBM PKCS#11 ICA token "; CK_CHAR label[] = "IBM ICA PKCS #11"; pthread_mutex_t rngmtx = PTHREAD_MUTEX_INITIALIZER; unsigned int rnginitialized=0; CK_RV token_specific_rng(CK_BYTE *output, CK_ULONG bytes) { unsigned int rc; pthread_mutex_lock(&rngmtx); rc = ica_random_number_generate( (unsigned int) bytes, output); if (rc != 0) { pthread_mutex_unlock(&rngmtx); return CKR_GENERAL_ERROR; /* report error */ } pthread_mutex_unlock(&rngmtx); return CKR_OK; } CK_RV token_specific_init(CK_SLOT_ID SlotNumber, char *conf_name) { return ica_open_adapter(&adapter_handle); } CK_RV token_specific_final() { ica_close_adapter(adapter_handle); return CKR_OK; } // count_ones_in_byte: for use in adjust_des_key_parity_bits below CK_BYTE count_ones_in_byte(CK_BYTE byte) { CK_BYTE and_mask, // bit selector number_of_ones = 0; for (and_mask = 1; and_mask != 0; and_mask <<= 1) // for each bit, if (byte & and_mask) // if it's a one, ++number_of_ones; // count it return number_of_ones; } #define EVEN_PARITY TRUE #define ODD_PARITY FALSE // adjust_des_key_parity_bits: to conform to NIST spec for DES and 3DES keys void adjust_des_key_parity_bits(CK_BYTE *des_key, CK_ULONG key_size, CK_BBOOL parity) { CK_BYTE *des_key_byte; for (des_key_byte = des_key; des_key_byte - des_key < key_size; ++des_key_byte) // look at each byte in the key { if ((count_ones_in_byte(*des_key_byte) % 2) ^ (parity == ODD_PARITY)) { // if parity for this byte isn't what it should be, // flip the parity (least significant) bit *des_key_byte ^= 1; } } } CK_RV token_specific_des_key_gen(CK_BYTE *des_key, CK_ULONG len, CK_ULONG keysize) { // Nothing different to do for DES or TDES here as this is just // random data... Validation handles the rest // Only check for weak keys when DES. if (len == (3 * DES_KEY_SIZE)) { rng_generate(des_key,len); adjust_des_key_parity_bits(des_key, len, ODD_PARITY); } else { do { rng_generate(des_key, len); adjust_des_key_parity_bits(des_key, len, ODD_PARITY); } while (des_check_weak_key(des_key) == TRUE); } // we really need to validate the key for parity etc... // we should do that here... The caller validates the single des keys // against the known and suspected poor keys..<< return CKR_OK; } CK_RV token_specific_des_ecb(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; /* * checks for input and output data length and block sizes * are already being carried out in mech_des.c * so we skip those */ if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if ( encrypt) { rc = ica_des_encrypt(MODE_DES_ECB, (unsigned int) in_data_len, in_data, NULL, (ica_des_key_single_t *)attr->pValue, out_data); } else { rc = ica_des_decrypt(MODE_DES_ECB, (unsigned int) in_data_len, in_data, NULL, (ica_des_key_single_t *)attr->pValue, out_data); } if (rc != 0) { rc = CKR_FUNCTION_FAILED; TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); }else { *out_data_len = in_data_len; rc = CKR_OK; } return rc; } CK_RV token_specific_des_cbc(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; /* * checks for input and output data length and block sizes * are already being carried out in mech_des.c * so we skip those */ // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if ( encrypt ){ rc = ica_des_encrypt(MODE_DES_CBC, (unsigned int) in_data_len, in_data, (ica_des_vector_t *) init_v, (ica_des_key_single_t *) attr->pValue, out_data); } else { rc = ica_des_decrypt(MODE_DES_CBC, (unsigned int) in_data_len, in_data, (ica_des_vector_t *) init_v, (ica_des_key_single_t *) attr->pValue, out_data); } if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; }else { *out_data_len = in_data_len; rc = CKR_OK; } return rc; } CK_RV token_specific_tdes_ecb(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_BYTE key_value[3*DES_KEY_SIZE]; /* * checks for input and output data length and block sizes * are already being carried out in mech_des3.c * so we skip those */ // get the key type rc = template_attribute_find(key->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if (keytype == CKK_DES2) { memcpy(key_value, attr->pValue, 2*DES_KEY_SIZE); memcpy(key_value + (2*DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); } else memcpy(key_value, attr->pValue, 3*DES_KEY_SIZE); if ( encrypt) { rc = ica_3des_encrypt(MODE_DES_ECB, (unsigned int) in_data_len, in_data, NULL, (ica_des_key_triple_t *) key_value, out_data); } else { rc = ica_3des_decrypt(MODE_DES_ECB, (unsigned int) in_data_len, in_data, NULL, (ica_des_key_triple_t *) key_value, out_data); } if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; }else { *out_data_len = in_data_len; rc = CKR_OK; } return rc; } CK_RV token_specific_tdes_cbc(CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_BYTE key_value[3*DES_KEY_SIZE]; /* * checks for input and output data length and block sizes * are already being carried out in mech_des3.c * so we skip those */ // get the key type rc = template_attribute_find(key->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if (keytype == CKK_DES2) { memcpy(key_value, attr->pValue, 2*DES_KEY_SIZE); memcpy(key_value + (2*DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); } else memcpy(key_value, attr->pValue, 3*DES_KEY_SIZE); if ( encrypt ){ rc = ica_3des_encrypt(MODE_DES_CBC, (unsigned int) in_data_len, in_data, (ica_des_vector_t *) init_v, (ica_des_key_triple_t *) key_value, out_data); } else { rc = ica_3des_decrypt(MODE_DES_CBC, (unsigned int) in_data_len, in_data, (ica_des_vector_t *) init_v, (ica_des_key_triple_t *) key_value, out_data); } if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; }else { *out_data_len = in_data_len; rc = CKR_OK; } return rc; } /* * * 0 Use the decrypt function. * 1 Use the encrypt function. */ CK_RV token_specific_tdes_ofb(CK_BYTE *in_data, CK_BYTE *out_data, CK_ULONG data_len, OBJECT *key, CK_BYTE *iv, uint_32 direction) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } rc = ica_3des_ofb(in_data, out_data, (unsigned int) data_len, (unsigned char *) attr->pValue, (unsigned char *) iv, direction); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } return rc; } /* * 0 Use the decrypt function. * 1 Use the encrypt function. */ CK_RV token_specific_tdes_cfb(CK_BYTE *in_data, CK_BYTE *out_data, CK_ULONG data_len, OBJECT *key, CK_BYTE *iv, uint_32 cfb_len, uint_32 direction) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } rc = ica_3des_cfb(in_data, out_data, (unsigned int) data_len, (unsigned char *) attr->pValue, (unsigned char *) iv, cfb_len, direction); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } return rc; } CK_RV token_specific_tdes_mac(CK_BYTE *message, CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_KEY_TYPE keytype; CK_BYTE key_value[3*DES_KEY_SIZE]; // get the key type rc = template_attribute_find(key->template, CKA_KEY_TYPE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n"); return CKR_FUNCTION_FAILED; } keytype = *(CK_KEY_TYPE *)attr->pValue; // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if (keytype == CKK_DES2) { memcpy(key_value, attr->pValue, 2*DES_KEY_SIZE); memcpy(key_value + (2*DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE); } else memcpy(key_value, attr->pValue, 3*DES_KEY_SIZE); rc = ica_3des_cmac_intermediate(message, (unsigned long) message_len, (unsigned char *) key_value, mac); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } return rc; } /* * Init SHA data structures */ CK_RV token_specific_sha_init(DIGEST_CONTEXT *ctx, CK_MECHANISM *mech) { unsigned int dev_ctx_size; struct oc_sha_ctx *sc; /* For the C_DigestInit, C_Digest case, we may have already * created ctx->context... - KEY */ if (ctx->context) { sc = (struct oc_sha_ctx *)ctx->context; if(sc->dev_ctx) free(sc->dev_ctx); free(ctx->context); } ctx->context_len = sizeof(struct oc_sha_ctx); ctx->context = malloc(sizeof(struct oc_sha_ctx)); if(ctx->context == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(ctx->context, 0, ctx->context_len); sc = (struct oc_sha_ctx *)ctx->context; switch (mech->mechanism) { case CKM_SHA_1: sc->hash_len = SHA1_HASH_SIZE; sc->hash_blksize = SHA1_BLOCK_SIZE; dev_ctx_size = sizeof(sha_context_t); break; case CKM_SHA256: sc->hash_len = SHA2_HASH_SIZE; sc->hash_blksize = SHA2_BLOCK_SIZE; dev_ctx_size = sizeof(sha256_context_t); break; case CKM_SHA384: sc->hash_len = SHA3_HASH_SIZE; sc->hash_blksize = SHA3_BLOCK_SIZE; dev_ctx_size = sizeof(sha512_context_t); break; case CKM_SHA512: sc->hash_len = SHA5_HASH_SIZE; sc->hash_blksize = SHA5_BLOCK_SIZE; dev_ctx_size = sizeof(sha512_context_t); break; default: free(ctx->context); return CKR_MECHANISM_INVALID; } sc->dev_ctx = malloc(dev_ctx_size); if(sc->dev_ctx == NULL){ free(ctx->context); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memset(sc->dev_ctx, 0, dev_ctx_size); sc->message_part = SHA_MSG_PART_ONLY; return CKR_OK; } CK_RV token_specific_sha(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { int rc; CK_RV rv = CKR_OK; struct oc_sha_ctx *oc_sha_ctx; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; if (!in_data || !out_data) return CKR_ARGUMENTS_BAD; oc_sha_ctx = (struct oc_sha_ctx *)ctx->context; if(*out_data_len < oc_sha_ctx->hash_len) return CKR_BUFFER_TOO_SMALL; oc_sha_ctx->message_part = SHA_MSG_PART_ONLY; switch (ctx->mech.mechanism) { case CKM_SHA_1: { sha_context_t *ica_sha_ctx = (sha_context_t *) oc_sha_ctx->dev_ctx; rc = ica_sha1(oc_sha_ctx->message_part, in_data_len, in_data, ica_sha_ctx, oc_sha_ctx->hash); break; } case CKM_SHA256: { sha256_context_t *ica_sha2_ctx = (sha256_context_t *)oc_sha_ctx->dev_ctx; rc = ica_sha256(oc_sha_ctx->message_part, in_data_len, in_data, ica_sha2_ctx, oc_sha_ctx->hash); break; } case CKM_SHA384: { sha512_context_t *ica_sha3_ctx = (sha512_context_t *)oc_sha_ctx->dev_ctx; rc = ica_sha384(oc_sha_ctx->message_part, in_data_len, in_data, ica_sha3_ctx, oc_sha_ctx->hash); break; } case CKM_SHA512: { sha512_context_t *ica_sha5_ctx = (sha512_context_t *)oc_sha_ctx->dev_ctx; rc = ica_sha512(oc_sha_ctx->message_part, in_data_len, in_data, ica_sha5_ctx, oc_sha_ctx->hash); break; } default: return CKR_MECHANISM_INVALID; } if (rc == CKR_OK) { memcpy(out_data, oc_sha_ctx->hash, oc_sha_ctx->hash_len); *out_data_len = oc_sha_ctx->hash_len; } else rv = CKR_FUNCTION_FAILED; /* ctx->context is freed inside digest_mgr_cleanup - KEY */ free(oc_sha_ctx->dev_ctx); return rv; } static CK_RV ica_sha_call(DIGEST_CONTEXT *ctx, CK_BYTE *data, CK_ULONG data_len) { struct oc_sha_ctx *oc_sha_ctx = (struct oc_sha_ctx *)ctx->context; CK_RV ret; switch (ctx->mech.mechanism) { case CKM_SHA_1: { sha_context_t *ica_sha_ctx = (sha_context_t *)oc_sha_ctx->dev_ctx; if (ica_sha_ctx->runningLength == 0) oc_sha_ctx->message_part = SHA_MSG_PART_FIRST; else oc_sha_ctx->message_part = SHA_MSG_PART_MIDDLE; ret = ica_sha1(oc_sha_ctx->message_part, data_len, data, ica_sha_ctx, oc_sha_ctx->hash); break; } case CKM_SHA256: { sha256_context_t *ica_sha_ctx = (sha256_context_t *)oc_sha_ctx->dev_ctx; if (ica_sha_ctx->runningLength == 0) oc_sha_ctx->message_part = SHA_MSG_PART_FIRST; else oc_sha_ctx->message_part = SHA_MSG_PART_MIDDLE; ret = ica_sha256(oc_sha_ctx->message_part, data_len, data, ica_sha_ctx, oc_sha_ctx->hash); break; } case CKM_SHA384: { sha512_context_t *ica_sha_ctx = (sha512_context_t *)oc_sha_ctx->dev_ctx; if (ica_sha_ctx->runningLengthLow == 0 && ica_sha_ctx->runningLengthHigh == 0) oc_sha_ctx->message_part = SHA_MSG_PART_FIRST; else oc_sha_ctx->message_part = SHA_MSG_PART_MIDDLE; ret = ica_sha384(oc_sha_ctx->message_part, data_len, data, ica_sha_ctx, oc_sha_ctx->hash); break; } case CKM_SHA512: { sha512_context_t *ica_sha_ctx = (sha512_context_t *)oc_sha_ctx->dev_ctx; if (ica_sha_ctx->runningLengthLow == 0 && ica_sha_ctx->runningLengthHigh == 0) oc_sha_ctx->message_part = SHA_MSG_PART_FIRST; else oc_sha_ctx->message_part = SHA_MSG_PART_MIDDLE; ret = ica_sha512(oc_sha_ctx->message_part, data_len, data, ica_sha_ctx, oc_sha_ctx->hash); break; } default: return CKR_MECHANISM_INVALID; } return(ret ? CKR_FUNCTION_FAILED : CKR_OK); } CK_RV token_specific_sha_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len) { struct oc_sha_ctx *oc_sha_ctx; int fill, len, rest, ret; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; if (!in_data_len) return CKR_OK; if (!in_data) return CKR_ARGUMENTS_BAD; oc_sha_ctx = (struct oc_sha_ctx *)ctx->context; /* if less than blocksize, save to context buffer for next time */ if (oc_sha_ctx->tail_len + in_data_len < oc_sha_ctx->hash_blksize) { memcpy(oc_sha_ctx->tail + oc_sha_ctx->tail_len, in_data, in_data_len); oc_sha_ctx->tail_len += in_data_len; return CKR_OK; } /* we have at least one block */ /* if some leftovers from the last update are available copy together one block into the tail buffer and hash it */ if (oc_sha_ctx->tail_len) { fill = oc_sha_ctx->hash_blksize - oc_sha_ctx->tail_len; memcpy(oc_sha_ctx->tail + oc_sha_ctx->tail_len, in_data, fill); /* hash blksize bytes from the tail buffer */ ret = ica_sha_call(ctx, oc_sha_ctx->tail, oc_sha_ctx->hash_blksize); if (ret != CKR_OK) return ret; /* tail buffer is empty now */ oc_sha_ctx->tail_len = 0; /* adjust input data pointer and input data len */ in_data += fill; in_data_len -= fill; /* if there is no more data to process, we are done */ if (!in_data_len) return CKR_OK; } /* The tail buffer is empty now, and in_data_len is > 0. * Calculate amount of remaining bytes... */ rest = in_data_len % oc_sha_ctx->hash_blksize; /* and amount of bytes fitting into hash blocks */ len = in_data_len - rest; /* process the full hash blocks */ if (len > 0) { /* hash len bytes from input starting at the beginning */ ret = ica_sha_call(ctx, in_data, len); if (ret != CKR_OK) return ret; /* adjust input data pointer */ in_data += len; } /* Store remaining bytes into the empty tail buffer */ if (rest > 0) { memcpy(oc_sha_ctx->tail, in_data, rest); oc_sha_ctx->tail_len = rest; } return CKR_OK; } CK_RV token_specific_sha_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len) { int rc; CK_RV rv = CKR_OK; struct oc_sha_ctx *oc_sha_ctx; if (!ctx || !ctx->context) return CKR_OPERATION_NOT_INITIALIZED; if (!out_data || !out_data_len) return CKR_ARGUMENTS_BAD; oc_sha_ctx = (struct oc_sha_ctx *)ctx->context; oc_sha_ctx->message_part = SHA_MSG_PART_FINAL; if (*out_data_len < oc_sha_ctx->hash_len) return CKR_BUFFER_TOO_SMALL; switch (ctx->mech.mechanism) { case CKM_SHA_1: { sha_context_t *ica_sha1_ctx = (sha_context_t *)oc_sha_ctx->dev_ctx; /* accommodate multi-part when input was so small * that we never got to call into libica until final */ if (ica_sha1_ctx->runningLength == 0) oc_sha_ctx->message_part = SHA_MSG_PART_ONLY; rc = ica_sha1(oc_sha_ctx->message_part, oc_sha_ctx->tail_len, (unsigned char *)oc_sha_ctx->tail, ica_sha1_ctx, oc_sha_ctx->hash); break; } case CKM_SHA256: { sha256_context_t *ica_sha2_ctx = (sha256_context_t *)oc_sha_ctx->dev_ctx; /* accommodate multi-part when input was so small * that we never got to call into libica until final */ if (ica_sha2_ctx->runningLength == 0) oc_sha_ctx->message_part = SHA_MSG_PART_ONLY; rc = ica_sha256(oc_sha_ctx->message_part, oc_sha_ctx->tail_len, oc_sha_ctx->tail, ica_sha2_ctx, oc_sha_ctx->hash); break; } case CKM_SHA384: { sha512_context_t *ica_sha3_ctx = (sha512_context_t *)oc_sha_ctx->dev_ctx; /* accommodate multi-part when input was so small * that we never got to call into libica until final */ if (ica_sha3_ctx->runningLengthLow == 0 && ica_sha3_ctx->runningLengthHigh == 0) oc_sha_ctx->message_part = SHA_MSG_PART_ONLY; rc = ica_sha384(oc_sha_ctx->message_part, oc_sha_ctx->tail_len, oc_sha_ctx->tail, ica_sha3_ctx, oc_sha_ctx->hash); break; } case CKM_SHA512: { sha512_context_t *ica_sha5_ctx = (sha512_context_t *)oc_sha_ctx->dev_ctx; /* accommodate multi-part when input was so small * that we never got to call into libica until final */ if (ica_sha5_ctx->runningLengthLow == 0 && ica_sha5_ctx->runningLengthHigh == 0) oc_sha_ctx->message_part = SHA_MSG_PART_ONLY; rc = ica_sha512(oc_sha_ctx->message_part, oc_sha_ctx->tail_len, oc_sha_ctx->tail, ica_sha5_ctx, oc_sha_ctx->hash); break; } default: return CKR_MECHANISM_INVALID; } if (rc != CKR_OK) { rv = CKR_FUNCTION_FAILED; goto out; } memcpy(out_data, oc_sha_ctx->hash, oc_sha_ctx->hash_len); *out_data_len = oc_sha_ctx->hash_len; out: /* ctx->context is freed inside digest_mgr_cleanup - KEY */ free(oc_sha_ctx->dev_ctx); return rv; } #ifndef LITE #define LITE #endif /* Creates a libICA modulus+exponent key representation using * PKCS#11 attributes */ ica_rsa_key_mod_expo_t * rsa_convert_mod_expo_key( CK_ATTRIBUTE * modulus, CK_ATTRIBUTE * mod_bits, CK_ATTRIBUTE * exponent) { CK_BYTE * ptr = NULL; ica_rsa_key_mod_expo_t * modexpokey = NULL; /* We need at least the modulus and a (public|private) exponent */ if (!modulus || !exponent) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return NULL; } modexpokey = (ica_rsa_key_mod_expo_t *) calloc(1, sizeof(ica_rsa_key_mod_expo_t)); if (modexpokey == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto err; } /* We can't rely solely on CKA_MODULUS_BITS here since Private Keys * using the modulus + private exponent representation may also go * through this path. Use modulus length in bytes as key_length if * no mod_bits is present */ if (mod_bits != NULL && mod_bits->ulValueLen && (*(CK_ULONG *)mod_bits->pValue)) { modexpokey->key_length = ((* (CK_ULONG *) mod_bits->pValue) + 7 ) / 8; } else { modexpokey->key_length = modulus->ulValueLen; } /* maybe I'm over-cautious here */ if ( (modulus->ulValueLen > modexpokey->key_length) || (exponent->ulValueLen > modexpokey->key_length)) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); goto err; } modexpokey->modulus = (unsigned char *) calloc(1, modexpokey->key_length); if (modexpokey->modulus == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto err; } /* right-justified fields */ ptr = modexpokey->modulus + modexpokey->key_length - modulus->ulValueLen; memcpy(ptr, modulus->pValue, modexpokey->key_length); modexpokey->exponent = (unsigned char *) calloc(1, modexpokey->key_length); if (modexpokey->exponent == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto err; } ptr = modexpokey->exponent + modexpokey->key_length - exponent->ulValueLen; memcpy(ptr, exponent->pValue, exponent->ulValueLen); return modexpokey; err: free(modexpokey->modulus); free(modexpokey->exponent); free(modexpokey); return NULL; } /* Creates a libICA CRT key representation using * PKCS#11 attributes */ ica_rsa_key_crt_t * rsa_convert_crt_key( CK_ATTRIBUTE * modulus, CK_ATTRIBUTE * prime1, CK_ATTRIBUTE * prime2, CK_ATTRIBUTE * exp1, CK_ATTRIBUTE * exp2, CK_ATTRIBUTE * coeff) { CK_BYTE * ptr = NULL; ica_rsa_key_crt_t * crtkey = NULL; /* All the above params are required to build a CRT key * that can be used by libICA. Private Keys with modulus * and private exponent should use rsa_convert_mod_expo_key() */ if (!modulus || !prime1 || !prime2 || !exp1 || !exp2 || !coeff ) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return NULL; } else { crtkey = (ica_rsa_key_crt_t *) calloc(1, sizeof(ica_rsa_key_crt_t)); if (crtkey == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return NULL; } /* use modulus length in bytes as key_length */ crtkey->key_length = modulus->ulValueLen; /* buffers pointed by p, q, dp, dq and qInverse in struct * ica_rsa_key_crt_t must be of size key_legth/2 or larger. * p, dp and qInverse have an additional 8-byte padding. */ /* need to allocate the buffers. Also, all fields are * right-aligned, thus the use for ptr */ /* FIXME: if individual components lengths are bigger then * what we support in libICA then we're in trouble, * but maybe explicitly checking them is being over-zealous? */ if ( (prime1->ulValueLen > (crtkey->key_length/2)) || (prime2->ulValueLen > (crtkey->key_length/2)) || (exp1->ulValueLen > (crtkey->key_length/2)) || (exp2->ulValueLen > (crtkey->key_length/2)) || (coeff->ulValueLen > (crtkey->key_length/2)) ) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); goto err_crtkey; } crtkey->p = (unsigned char *) calloc(1, (crtkey->key_length/2) + 8); if (crtkey->p == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto err_crtkey; } ptr = crtkey->p + (crtkey->key_length/2) + 8 - prime1->ulValueLen; memcpy(ptr, prime1->pValue, prime1->ulValueLen); crtkey->q = (unsigned char *) calloc(1, crtkey->key_length/2); if (crtkey->q == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto err_crtkey; } ptr = crtkey->q + (crtkey->key_length/2) - prime2->ulValueLen; memcpy(ptr, prime2->pValue, prime2->ulValueLen); crtkey->dp = (unsigned char *) calloc(1, (crtkey->key_length/2) + 8); if (crtkey->dp == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto err_crtkey; } ptr = crtkey->dp + (crtkey->key_length/2) + 8 - exp1->ulValueLen; memcpy(ptr, exp1->pValue, exp1->ulValueLen); crtkey->dq = (unsigned char *) calloc(1, crtkey->key_length/2); if (crtkey->dq == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto err_crtkey; } ptr = crtkey->dq + (crtkey->key_length/2) - exp2->ulValueLen; memcpy(ptr, exp2->pValue, exp2->ulValueLen); crtkey->qInverse = (unsigned char *) calloc(1, (crtkey->key_length/2) + 8); if (crtkey->qInverse == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); goto err_crtkey; } ptr = crtkey->qInverse + (crtkey->key_length/2) + 8 - coeff->ulValueLen; memcpy(ptr, coeff->pValue, coeff->ulValueLen); return crtkey; } err_crtkey: free(crtkey->p); free(crtkey->q); free(crtkey->dp); free(crtkey->dq); free(crtkey->qInverse); free(crtkey); return NULL; } // CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl) { CK_ATTRIBUTE * publ_exp = NULL; CK_ATTRIBUTE * attr = NULL; CK_BYTE * ptr = NULL; CK_ULONG mod_bits; CK_BBOOL flag; unsigned long tmpsize; CK_RV rc; ica_rsa_key_mod_expo_t * publKey = NULL; ica_rsa_key_crt_t * privKey = NULL; flag = template_attribute_find( publ_tmpl, CKA_MODULUS_BITS, &attr ); if (!flag) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; // should never happen } mod_bits = *(CK_ULONG *)attr->pValue; flag = template_attribute_find( publ_tmpl, CKA_PUBLIC_EXPONENT, &publ_exp ); if (!flag) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE)); return CKR_TEMPLATE_INCOMPLETE; } // FIXME: is this check really necessary? if (mod_bits < 512 || mod_bits > 4096) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); return CKR_KEY_SIZE_RANGE; } /* libICA replicates the openSSL requirement that the public exponent * can't be larger than the size of an unsigned long */ if (publ_exp->ulValueLen > sizeof (unsigned long)) { TRACE_ERROR("%s\n", ock_err(ERR_KEY_SIZE_RANGE)); return CKR_KEY_SIZE_RANGE; } /* Build publKey: * The buffers in ica_rsa_key_mod_expo_t must be * allocated by the caller, with key_length size * use calloc() so that memory is zeroed (right alignment) */ publKey = (ica_rsa_key_mod_expo_t *) calloc(1, sizeof(ica_rsa_key_mod_expo_t)); if (publKey == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } /* key_length is in terms of bytes */ publKey->key_length = ((mod_bits + 7) / 8); publKey->modulus = (unsigned char *) calloc(1, publKey->key_length); if (publKey->modulus == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto pubkey_cleanup; } publKey->exponent = (unsigned char *) calloc(1, publKey->key_length); if (publKey->exponent == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto pubkey_cleanup; } /* Use the provided public exponent: * all fields must be right-aligned, so make * sure we only use the rightmost part */ /* We know the pub_exp attribute has it's value in BIG ENDIAN * * byte order, and we're assuming we're on s390(x) which is also * * BIG ENDIAN, so no byte swapping required. * * FIXME: Will need to fix that if porting for little endian */ ptr = publKey->exponent + publKey->key_length - publ_exp->ulValueLen; memcpy(ptr, publ_exp->pValue, publ_exp->ulValueLen); /* If the public exponent is zero, libica will generate a random one * * If it is an even number, then we have a problem. Use ptr to cast * * to unsigned int and check */ ptr = publKey->exponent + publKey->key_length - sizeof (unsigned long); if ( *( (unsigned long *)ptr) != 0 && *( (unsigned long *)ptr) % 2 == 0 ) { TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT)); return CKR_TEMPLATE_INCONSISTENT; } /* Build privKey: * buffers pointed by p, q, dp, dq and qInverse in struct * ica_rsa_key_crt_t must be of size key_legth/2 or larger. * p, dp and qInverse have an additional 8-byte padding */ privKey = (ica_rsa_key_crt_t *) calloc(1, sizeof(ica_rsa_key_crt_t)); if (privKey == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto pubkey_cleanup; } /* modexpo and crt key lengths are always the same */ privKey->key_length = publKey->key_length; privKey->p = (unsigned char *) calloc(1, (privKey->key_length/2) + 8); if (privKey->p == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto privkey_cleanup; } privKey->q = (unsigned char *) calloc(1, privKey->key_length/2); if (privKey->q == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto privkey_cleanup; } privKey->dp = (unsigned char *) calloc(1, (privKey->key_length/2) + 8); if (privKey->dp == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto privkey_cleanup; } privKey->dq = (unsigned char *) calloc(1, privKey->key_length/2); if (privKey->dq == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto privkey_cleanup; } privKey->qInverse = (unsigned char *) calloc(1, (privKey->key_length/2) + 8); if (privKey->qInverse == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto privkey_cleanup; } rc = ica_rsa_key_generate_crt(adapter_handle, (unsigned int)mod_bits, publKey, privKey); if(rc){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto privkey_cleanup; } /* Build the PKCS#11 public key */ // modulus: n // tmpsize = publKey->key_length; ptr = p11_bigint_trim(publKey->modulus, &tmpsize); if (tmpsize != publKey->key_length) { /* This is bad */ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto privkey_cleanup; } rc = build_attribute( CKA_MODULUS, ptr, tmpsize, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( publ_tmpl, attr ); // public exponent // tmpsize = publKey->key_length; ptr = p11_bigint_trim(publKey->exponent, &tmpsize); rc = build_attribute( CKA_PUBLIC_EXPONENT, ptr, tmpsize, &attr); if (rc != CKR_OK){ TRACE_DEVEL("build attribute failed\n"); goto privkey_cleanup; } template_update_attribute( publ_tmpl, attr ); // local = TRUE // flag = TRUE; rc = build_attribute( CKA_LOCAL, &flag, sizeof(CK_BBOOL), &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( publ_tmpl, attr ); // // now, do the private key // // public exponent: e // tmpsize = publKey->key_length; ptr = p11_bigint_trim(publKey->exponent, &tmpsize); rc = build_attribute( CKA_PUBLIC_EXPONENT, ptr, tmpsize, &attr ); if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( priv_tmpl, attr ); // modulus: n // tmpsize = publKey->key_length; ptr = p11_bigint_trim(publKey->modulus, &tmpsize); if (tmpsize != publKey->key_length) { /* This is bad */ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto privkey_cleanup; } rc = build_attribute( CKA_MODULUS, ptr, tmpsize, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( priv_tmpl, attr ); // exponent 1: d mod(p-1) // tmpsize = privKey->key_length/2; ptr = p11_bigint_trim(privKey->dp + 8, &tmpsize); rc = build_attribute( CKA_EXPONENT_1, ptr, tmpsize, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( priv_tmpl, attr ); // exponent 2: d mod(q-1) // tmpsize = privKey->key_length/2; ptr = p11_bigint_trim(privKey->dq, &tmpsize); rc = build_attribute( CKA_EXPONENT_2, ptr, tmpsize, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( priv_tmpl, attr ); // prime #1: p // tmpsize = privKey->key_length/2; ptr = p11_bigint_trim(privKey->p + 8, &tmpsize); rc = build_attribute( CKA_PRIME_1, ptr, tmpsize, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( priv_tmpl, attr ); // prime #2: q // tmpsize = privKey->key_length/2; ptr = p11_bigint_trim(privKey->q, &tmpsize); rc = build_attribute( CKA_PRIME_2, privKey->q, privKey->key_length/2, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( priv_tmpl, attr ); // CRT coefficient: q_inverse mod(p) // tmpsize = privKey->key_length/2; ptr = p11_bigint_trim(privKey->qInverse + 8, &tmpsize); rc = build_attribute( CKA_COEFFICIENT, ptr, tmpsize, &attr ); if (rc != CKR_OK){ TRACE_DEVEL("build_attribute failed\n"); goto privkey_cleanup; } template_update_attribute( priv_tmpl, attr ); privkey_cleanup: free(privKey->p); free(privKey->q); free(privKey->dp); free(privKey->dq); free(privKey->qInverse); free(privKey); pubkey_cleanup: free(publKey->modulus); free(publKey->exponent); free(publKey); return rc; } CK_RV token_specific_rsa_generate_keypair( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_RV rc; rc = os_specific_rsa_keygen(publ_tmpl,priv_tmpl); if (rc != CKR_OK) TRACE_DEVEL("os_specific_rsa_keygen failed\n"); return rc; } // // CK_RV os_specific_rsa_encrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, OBJECT * key_obj ) { CK_ATTRIBUTE * modulus = NULL; CK_ATTRIBUTE * pub_exp = NULL; CK_ATTRIBUTE * mod_bits = NULL; ica_rsa_key_mod_expo_t * publKey = NULL; CK_RV rc; /* mech_sra.c:ckm_rsa_encrypt accepts only CKO_PUBLIC_KEY */ template_attribute_find( key_obj->template, CKA_MODULUS, &modulus ); template_attribute_find( key_obj->template, CKA_MODULUS_BITS, &mod_bits ); template_attribute_find( key_obj->template, CKA_PUBLIC_EXPONENT, &pub_exp ); publKey = rsa_convert_mod_expo_key(modulus, mod_bits, pub_exp); if (publKey == NULL) { TRACE_ERROR("rsa_convert_mod_expo_key failed\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* in_data must be in big endian format. 'in_data' size in bits must not * exceed the bit length of the key, and size in bytes must * be of the same length of the key */ // FIXME: we're not cheking the size in bits of in_data - but how could we? if (publKey->key_length != in_data_len) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); rc = CKR_DATA_LEN_RANGE; goto cleanup_pubkey; } rc = ica_rsa_mod_expo(adapter_handle, in_data, publKey, out_data); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } else { rc = CKR_OK; } cleanup_pubkey: free(publKey->modulus); free(publKey->exponent); free(publKey); done: return rc; } // // CK_RV os_specific_rsa_decrypt( CK_BYTE * in_data, CK_ULONG in_data_len, CK_BYTE * out_data, OBJECT * key_obj ) { CK_ATTRIBUTE * modulus = NULL; CK_ATTRIBUTE * prime1 = NULL; CK_ATTRIBUTE * prime2 = NULL; CK_ATTRIBUTE * exp1 = NULL; CK_ATTRIBUTE * exp2 = NULL; CK_ATTRIBUTE * coeff = NULL; CK_ATTRIBUTE * priv_exp = NULL; ica_rsa_key_crt_t * crtKey = NULL; ica_rsa_key_mod_expo_t * modexpoKey = NULL; CK_RV rc; /* mech_rsa.c:ckm_rsa_decrypt accepts only CKO_PRIVATE_KEY, * but Private Key can have 2 representations (see PKCS#1): * - Modulus + private exponent * - p, q, dp, dq and qInv (CRT format) * The former should use ica_rsa_key_mod_expo_t and the latter * ica_rsa_key_crt_t. Detect what representation this * key_obj has and use the proper convert function */ template_attribute_find( key_obj->template, CKA_MODULUS, &modulus ); template_attribute_find( key_obj->template, CKA_PRIVATE_EXPONENT, &priv_exp ); template_attribute_find( key_obj->template, CKA_PRIME_1, &prime1 ); template_attribute_find( key_obj->template, CKA_PRIME_2, &prime2 ); template_attribute_find( key_obj->template, CKA_EXPONENT_1, &exp1 ); template_attribute_find( key_obj->template, CKA_EXPONENT_2, &exp2 ); template_attribute_find( key_obj->template, CKA_COEFFICIENT, &coeff ); /* Need to check for CRT Key format *BEFORE* check for mod_expo key, * that's because opencryptoki *HAS* a CKA_PRIVATE_EXPONENT attribute * even in CRT keys (but with zero length) */ // FIXME: Checking for non-zero lengths anyway (might be overkill) if (modulus && modulus->ulValueLen && prime1 && prime1->ulValueLen && prime2 && prime2->ulValueLen && exp1 && exp1->ulValueLen && exp2 && exp2->ulValueLen && coeff && coeff->ulValueLen ) { /* ica_rsa_key_crt_t representation */ crtKey = rsa_convert_crt_key(modulus, prime1, prime2, exp1, exp2, coeff); if (crtKey == NULL) { TRACE_ERROR("rsa_convert_crt_key failed\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* same check as above */ if (crtKey->key_length != in_data_len) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); rc = CKR_ENCRYPTED_DATA_LEN_RANGE; goto crt_cleanup; } rc = ica_rsa_crt(adapter_handle, in_data, crtKey, out_data); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } else { rc = CKR_OK; } goto crt_cleanup; } else if (modulus && modulus->ulValueLen && priv_exp && priv_exp->ulValueLen ) { /* ica_rsa_key_mod_expo_t representation */ modexpoKey = rsa_convert_mod_expo_key(modulus, NULL, priv_exp); if (modexpoKey == NULL) { TRACE_ERROR("rsa_convert_mod_expo_key failed\n"); rc = CKR_FUNCTION_FAILED; goto done; } /* in_data must be in big endian format. Size in bits must not * exceed the bit length of the key, and size in bytes must * be the same */ // FIXME: we're not cheking the size in bits of in_data - but how could we? if (modexpoKey->key_length != in_data_len) { TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); rc = CKR_ENCRYPTED_DATA_LEN_RANGE; goto modexpo_cleanup; } rc = ica_rsa_mod_expo(adapter_handle, in_data, modexpoKey, out_data); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } else { rc = CKR_OK; } goto modexpo_cleanup; } else { /* should never happen */ TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_PARAM_INVALID)); rc = CKR_MECHANISM_PARAM_INVALID; goto done; } crt_cleanup: free(crtKey->p); free(crtKey->q); free(crtKey->dp); free(crtKey->dq); free(crtKey->qInverse); free(crtKey); goto done; modexpo_cleanup: free(modexpoKey->modulus); free(modexpoKey->exponent); free(modexpoKey); done: return rc; } CK_RV token_specific_rsa_encrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; /* format the data */ rc = rsa_format_block(in_data, in_data_len, clear, modulus_bytes, PKCS_BT_2); if (rc != CKR_OK) { TRACE_DEVEL("rsa_format_block failed\n"); return rc; } rc = os_specific_rsa_encrypt(clear, modulus_bytes, cipher, key_obj); if (rc == CKR_OK) { memcpy(out_data, cipher, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } CK_RV token_specific_rsa_decrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_BYTE out[MAX_RSA_KEYLEN]; CK_RV rc; rc = os_specific_rsa_decrypt(in_data, in_data_len, out, key_obj); if (rc != CKR_OK) { TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); return rc; } rc = rsa_parse_block(out,in_data_len,out_data,out_data_len,PKCS_BT_2); if (rc != CKR_OK) { TRACE_DEVEL("rsa_parse_block failed\n"); return rc; } /* * For PKCS #1 v1.5 padding, out_data_len must be less * than in_data_len (which is modulus_bytes) - 11. */ if (*out_data_len > (in_data_len - 11)) { TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE)); rc = CKR_ENCRYPTED_DATA_LEN_RANGE; } return rc; } CK_RV token_specific_rsa_sign(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_ATTRIBUTE *attr = NULL; CK_BBOOL flag; CK_RV rc; CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = rsa_format_block(in_data, in_data_len, data, modulus_bytes, PKCS_BT_1); if (rc != CKR_OK) { TRACE_DEVEL("rsa_format_block failed\n"); return rc; } /* signing is a private key operation --> decrypt */ rc = os_specific_rsa_decrypt(data, modulus_bytes, sig, key_obj); if (rc == CKR_OK) { memcpy( out_data, sig, modulus_bytes ); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); return rc; } CK_RV token_specific_rsa_verify (CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE out[MAX_RSA_KEYLEN], out_data[MAX_RSA_KEYLEN]; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes, out_data_len; out_data_len = MAX_RSA_KEYLEN; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); if (rc == CKR_OK) { rc = rsa_parse_block(out, modulus_bytes, out_data, &out_data_len, PKCS_BT_1); if (rc == CKR_OK) { if (in_data_len != out_data_len) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } if (memcmp(in_data, out_data, out_data_len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } } else if (rc == CKR_ENCRYPTED_DATA_INVALID ) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } else { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } } else TRACE_DEVEL("rsa_parse_block failed\n"); return rc; } CK_RV token_specific_rsa_verify_recover(CK_BYTE *signature, CK_ULONG sig_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE out[MAX_RSA_KEYLEN]; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); if (rc != CKR_OK) { TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_1); if (rc == CKR_ENCRYPTED_DATA_INVALID ) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } else if (rc != CKR_OK) TRACE_DEVEL("rsa_parse_block failed\n"); return rc; } CK_RV token_specific_rsa_x509_encrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE clear[MAX_RSA_KEYLEN], cipher[MAX_RSA_KEYLEN]; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; // prepad with zeros // memset(clear, 0x0, modulus_bytes - in_data_len); memcpy(&clear[modulus_bytes - in_data_len], in_data, in_data_len); rc = os_specific_rsa_encrypt(clear, modulus_bytes, cipher, key_obj); if (rc == CKR_OK) { memcpy(out_data, cipher, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } CK_RV token_specific_rsa_x509_decrypt(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE out[MAX_RSA_KEYLEN]; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = os_specific_rsa_decrypt(in_data, modulus_bytes, out, key_obj); if (rc == CKR_OK) { memcpy(out_data, out, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); return rc; } CK_RV token_specific_rsa_x509_sign(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE data[MAX_RSA_KEYLEN], sig[MAX_RSA_KEYLEN]; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; // prepad with zeros // memset(data, 0x0, modulus_bytes - in_data_len); memcpy(&data[modulus_bytes - in_data_len], in_data, in_data_len); rc = os_specific_rsa_decrypt(data, modulus_bytes, sig ,key_obj); if (rc == CKR_OK) { memcpy(out_data, sig, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); return rc; } CK_RV token_specific_rsa_x509_verify(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE out[MAX_RSA_KEYLEN]; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = os_specific_rsa_encrypt(signature, modulus_bytes, out ,key_obj); if (rc == CKR_OK) { CK_ULONG pos1, pos2, len; // it should be noted that in_data_len is not necessarily // the same as the modulus length // for (pos1=0; pos1 < in_data_len; pos1++) if (in_data[pos1] != 0) break; for (pos2=0; pos2 < modulus_bytes; pos2++) if (out[pos2] != 0) // at this point, pos1 and pos2 point to the first non-zero // bytes in the input data and the decrypted signature // (the recovered data), respectively. // if ((in_data_len - pos1) != (modulus_bytes - pos2)) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } len = in_data_len - pos1; if (memcmp(&in_data[pos1], &out[pos2], len) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID)); return CKR_SIGNATURE_INVALID; } return CKR_OK; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } CK_RV token_specific_rsa_x509_verify_recover(CK_BYTE *signature, CK_ULONG sig_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key_obj) { CK_RV rc; CK_BYTE out[MAX_RSA_KEYLEN]; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_ULONG modulus_bytes; flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; rc = os_specific_rsa_encrypt(signature, modulus_bytes, out, key_obj); if (rc == CKR_OK) { memcpy(out_data, out, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } CK_RV token_specific_rsa_oaep_encrypt(ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *hash, CK_ULONG hlen) { CK_RV rc; CK_BYTE cipher[MAX_RSA_KEYLEN]; CK_ULONG modulus_bytes; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_BYTE *em_data = NULL; OBJECT *key_obj = NULL; CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; if (!in_data || !out_data || !hash) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR)ctx->mech.pParameter; rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); return rc; } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modulus_bytes = attr->ulValueLen; /* pkcs1v2.2, section 7.1.1 Step 2: * EME-OAEP encoding. */ em_data = (CK_BYTE *)malloc(modulus_bytes); if (em_data == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = encode_eme_oaep(in_data, in_data_len, em_data, modulus_bytes, oaepParms->mgf, hash, hlen); if (rc != CKR_OK) goto done; rc = os_specific_rsa_encrypt(em_data, modulus_bytes, cipher, key_obj); if (rc == CKR_OK) { memcpy(out_data, cipher, modulus_bytes); *out_data_len = modulus_bytes; } else TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); done: if (em_data) free(em_data); return rc; } CK_RV token_specific_rsa_oaep_decrypt(ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE *hash, CK_ULONG hlen) { CK_RV rc; CK_BYTE *decr_data = NULL; OBJECT *key_obj = NULL; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_RSA_PKCS_OAEP_PARAMS_PTR oaepParms = NULL; if (!in_data || !out_data || !hash) { TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } oaepParms = (CK_RSA_PKCS_OAEP_PARAMS_PTR)ctx->mech.pParameter; rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); return rc; } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else *out_data_len = attr->ulValueLen; decr_data = (CK_BYTE *)malloc(in_data_len); if (decr_data == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = os_specific_rsa_decrypt(in_data, in_data_len, decr_data, key_obj); if (rc != CKR_OK) return rc; /* pkcs1v2.2, section 7.1.2 Step 2: * EME-OAEP decoding. */ rc = decode_eme_oaep(decr_data, in_data_len, out_data, out_data_len, oaepParms->mgf, hash, hlen); if (decr_data) free(decr_data); return rc; } CK_RV token_specific_rsa_pss_sign(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *sig, CK_ULONG *sig_len) { CK_RV rc; CK_ULONG modbytes; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; OBJECT *key_obj = NULL; CK_BYTE *emdata = NULL; CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; /* check the arguments */ if (!in_data || !sig) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!ctx) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } pssParms = (CK_RSA_PKCS_PSS_PARAMS *)ctx->mech.pParameter; /* get the key */ rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); return rc; } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modbytes = attr->ulValueLen; emdata = (CK_BYTE *)malloc(modbytes); if (emdata == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } rc = emsa_pss_encode(pssParms, in_data, in_data_len, emdata, &modbytes); if (rc != CKR_OK) goto done; /* signing is a private key operation --> decrypt */ rc = os_specific_rsa_decrypt(emdata, modbytes, sig, key_obj); if (rc == CKR_OK) *sig_len = modbytes; else TRACE_DEVEL("os_specific_rsa_decrypt failed\n"); done: if (emdata) free(emdata); return rc; } CK_RV token_specific_rsa_pss_verify(SIGN_VERIFY_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_RV rc; CK_ULONG modbytes; OBJECT *key_obj = NULL; CK_BBOOL flag; CK_ATTRIBUTE *attr = NULL; CK_BYTE out[MAX_RSA_KEYLEN]; CK_RSA_PKCS_PSS_PARAMS *pssParms = NULL; /* check the arguments */ if (!in_data || !signature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); return CKR_ARGUMENTS_BAD; } if (!ctx) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } pssParms = (CK_RSA_PKCS_PSS_PARAMS *)ctx->mech.pParameter; /* get the key */ rc = object_mgr_find_in_map1(ctx->key, &key_obj); if (rc != CKR_OK) { TRACE_DEVEL("object_mgr_find_in_map1 failed\n"); return rc; } /* verify is a public key operation ... encrypt */ rc = os_specific_rsa_encrypt(signature, sig_len, out, key_obj); if (rc != CKR_OK) { TRACE_DEVEL("os_specific_rsa_encrypt failed\n"); return rc; } flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr); if (flag == FALSE) { TRACE_ERROR("Could not find CKA_MODULUS for the key.\n"); return CKR_FUNCTION_FAILED; } else modbytes = attr->ulValueLen; /* call the pss verify scheme */ rc = emsa_pss_verify(pssParms, in_data, in_data_len, out, modbytes); return rc; } #ifndef NOAES CK_RV token_specific_aes_key_gen(CK_BYTE *key, CK_ULONG len, CK_ULONG keysize) { return rng_generate(key, len); } CK_RV token_specific_aes_ecb(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE encrypt) { int rc = CKR_OK; CK_ATTRIBUTE *attr = NULL; /* * checks for input and output data length and block sizes * are already being carried out in mech_aes.c * so we skip those */ // get the key value rc = template_attribute_find(key->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if (encrypt) { rc = ica_aes_encrypt(MODE_AES_ECB, (unsigned int) in_data_len, in_data, NULL, (unsigned int) attr->ulValueLen, attr->pValue, out_data); } else { rc = ica_aes_decrypt(MODE_AES_ECB, (unsigned int) in_data_len, in_data, NULL, (unsigned int) attr->ulValueLen, attr->pValue, out_data); } if (rc != 0) { (*out_data_len) = 0; rc = CKR_FUNCTION_FAILED; } else { (*out_data_len) = in_data_len; rc = CKR_OK; } return rc; } CK_RV token_specific_aes_cbc(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; /* * checks for input and output data length and block sizes * are already being carried out in mech_aes.c * so we skip those */ // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if (encrypt) { rc = ica_aes_encrypt(MODE_AES_CBC, (unsigned int) in_data_len, in_data, (ica_aes_vector_t *) init_v, (unsigned int) attr->ulValueLen, attr->pValue, out_data); } else { rc = ica_aes_decrypt(MODE_AES_CBC, (unsigned int) in_data_len, in_data, (ica_aes_vector_t *) init_v, (unsigned int) attr->ulValueLen, attr->pValue, out_data); } if (rc != 0) { (*out_data_len) = 0; rc = CKR_FUNCTION_FAILED; } else { (*out_data_len) = in_data_len; rc = CKR_OK; } return rc; } CK_RV token_specific_aes_ctr(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, OBJECT *key, CK_BYTE *counterblock, CK_ULONG counter_width, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; /* * checks for input and output data length and block sizes * are already being carried out in mech_aes.c * so we skip those */ /* in libica for AES-Counter Mode if uses one function for both encrypt and decrypt * so they use variable direction to know if the data is to be encrypted or decrypted * 0 -- Decrypt * 1 -- Encrypt */ // get the key value if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if (encrypt){ rc = ica_aes_ctr( in_data, out_data, (unsigned int) in_data_len, attr->pValue, (unsigned int) attr->ulValueLen, counterblock, (unsigned int ) counter_width, 1); } else{ rc = ica_aes_ctr( in_data, out_data, (unsigned int) in_data_len, attr->pValue, (unsigned int) attr->ulValueLen, counterblock, (unsigned int ) counter_width, 0); } if( rc != 0){ (*out_data_len) = 0; rc = CKR_FUNCTION_FAILED; } else { (*out_data_len) = in_data_len; rc = CKR_OK; } return rc; } CK_RV token_specific_aes_gcm_init(SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_MECHANISM *mech, CK_OBJECT_HANDLE key, CK_BYTE encrypt) { CK_RV rc = CKR_OK; OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr = NULL; CK_GCM_PARAMS *aes_gcm_param = NULL; AES_GCM_CONTEXT *context = NULL; CK_BYTE *icv, *icb, *ucb, *subkey; CK_ULONG icv_length; /* find key object */ rc = object_mgr_find_in_map1 (key, &key_obj); if (rc != CKR_OK){ TRACE_ERROR("Failed to find specified object.\n"); return rc; } /* get the key value */ rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_KEY_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } /* prepare initial counterblock */ aes_gcm_param = (CK_GCM_PARAMS *)mech->pParameter; context = (AES_GCM_CONTEXT *)ctx->context; context->ulAlen = aes_gcm_param->ulAADLen; icb = (CK_BYTE *)context->icb; ucb = (CK_BYTE *)context->ucb; subkey = (CK_BYTE *)context->subkey; icv = (CK_BYTE *)aes_gcm_param->pIv; icv_length = aes_gcm_param->ulIvLen; if (encrypt) { rc = ica_aes_gcm_initialize(icv, icv_length, (char *)attr->pValue, attr->ulValueLen, icb, ucb, subkey, 1); } else { rc = ica_aes_gcm_initialize(icv, icv_length, (char *)attr->pValue, attr->ulValueLen, icb, ucb, subkey, 0); } if (rc != 0) { TRACE_ERROR("ica_aes_gcm_initialize() failed.\n"); return CKR_FUNCTION_FAILED; } else return CKR_OK; } CK_RV token_specific_aes_gcm(SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE encrypt) { CK_RV rc; OBJECT *key = NULL; CK_ATTRIBUTE *attr = NULL; CK_GCM_PARAMS *aes_gcm_param = NULL; CK_BYTE *counterblock; CK_ULONG counter_width; CK_BYTE *tag_data,*auth_data; CK_ULONG auth_data_len; CK_ULONG tag_data_len; /* * Checks for input and output data length and block sizes are already * being carried out in mech_aes.c, so we skip those * * libica for AES-GCM Mode uses one function for both encrypt * and decrypt, so they use the variable 'direction' to know if * the data is to be encrypted or decrypted. * 0 -- Decrypt * 1 -- Encrypt */ aes_gcm_param = (CK_GCM_PARAMS *)ctx->mech.pParameter; counterblock = (CK_BYTE *)aes_gcm_param->pIv; counter_width = aes_gcm_param->ulIvLen; auth_data = (CK_BYTE *)aes_gcm_param->pAAD; auth_data_len = aes_gcm_param->ulAADLen; tag_data_len = (aes_gcm_param->ulTagBits + 7) / 8; /* find key object */ rc = object_mgr_find_in_map1(ctx->key, &key); if (rc != CKR_OK) { TRACE_ERROR("Failed to find specified object.\n"); return rc; } /* get key value */ if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } if (encrypt) { tag_data = out_data + in_data_len; rc = ica_aes_gcm(in_data, (unsigned int) in_data_len, out_data, counterblock, (unsigned int) counter_width, auth_data, (unsigned int) auth_data_len, tag_data, AES_BLOCK_SIZE, attr->pValue, (unsigned int) attr->ulValueLen, 1); if (rc == 0) { (*out_data_len) = in_data_len + tag_data_len; rc = CKR_OK; } } else { unsigned int len; tag_data = in_data + in_data_len - tag_data_len; len = in_data_len - tag_data_len; rc = ica_aes_gcm(out_data, (unsigned int)len, in_data, counterblock, (unsigned int ) counter_width, auth_data, (unsigned int) auth_data_len, tag_data, (unsigned int)tag_data_len, attr->pValue, (unsigned int) attr->ulValueLen, 0); if (rc == 0) { (*out_data_len) = len; rc = CKR_OK; } } if (rc != 0) { TRACE_ERROR("ica_aes_gcm failed with %lx.\n", rc); (*out_data_len) = 0; rc = CKR_FUNCTION_FAILED; } return rc; } CK_RV token_specific_aes_gcm_update(SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE encrypt) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; OBJECT *key = NULL; AES_GCM_CONTEXT *context = NULL; CK_GCM_PARAMS *aes_gcm_param = NULL; CK_ULONG total, tag_data_len, remain, auth_data_len; CK_ULONG out_len; CK_BYTE *auth_data, *tag_data; CK_BYTE *ucb, *subkey; CK_BYTE *buffer = NULL; context = (AES_GCM_CONTEXT *)ctx->context; total = (context->len + in_data_len); ucb = (CK_BYTE *)context->ucb; tag_data = context->hash; auth_data_len = context->ulAlen; subkey = (CK_BYTE *)context->subkey; aes_gcm_param = (CK_GCM_PARAMS *)ctx->mech.pParameter; tag_data_len = (aes_gcm_param->ulTagBits + 7) / 8; auth_data = (CK_BYTE *)aes_gcm_param->pAAD; /* if there isn't enough data to make a block, just save it */ if (encrypt) { remain = (total % AES_BLOCK_SIZE); if (total < AES_BLOCK_SIZE) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; *out_data_len = 0; return CKR_OK; } } else { /* decrypt */ remain = ((total - tag_data_len) % AES_BLOCK_SIZE) + tag_data_len; if (total < AES_BLOCK_SIZE + tag_data_len) { memcpy(context->data + context->len, in_data, in_data_len); context->len += in_data_len; *out_data_len = 0; return CKR_OK; } } /* At least we have 1 block */ /* find key object */ rc = object_mgr_find_in_map_nocache(ctx->key, &key); if(rc != CKR_OK) { TRACE_ERROR("Failed to find specified object.\n"); return rc; } /* get key value */ if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } out_len = total - remain; buffer = (CK_BYTE*)malloc(out_len); if (!buffer) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } if (encrypt) { /* copy all the leftover data from previous encryption first */ memcpy (buffer, context->data, context->len); memcpy (buffer+context->len, in_data, out_len - context->len); TRACE_DEVEL("Ciphertext length (%02ld bytes).\n", in_data_len); rc = ica_aes_gcm_intermediate(buffer, (unsigned int)out_len, out_data, ucb, auth_data, (unsigned int)auth_data_len, tag_data, AES_BLOCK_SIZE, attr->pValue, (unsigned int)attr->ulValueLen, subkey, 1); /* save any remaining data */ if (remain != 0) memcpy(context->data, in_data + (in_data_len - remain), remain); context->len = remain; } else { /* decrypt */ /* copy all the leftover data from previous encryption first */ if (in_data_len >= tag_data_len) { /* case 1 */ /* copy complete context to buffer first*/ memcpy (buffer, context->data, context->len); /* Append in_data to buffer */ memcpy (buffer + context->len, in_data, out_len - context->len); /* copy remaining data to context */ memcpy(context->data, in_data + out_len - context->len, remain); context->len = remain; } else { /* case 2 - partial data */ memcpy(buffer, context->data, AES_BLOCK_SIZE); memcpy(context->data, context->data + AES_BLOCK_SIZE, context->len - AES_BLOCK_SIZE); memcpy(context->data + context->len - AES_BLOCK_SIZE, in_data, in_data_len); context->len = context->len - AES_BLOCK_SIZE + in_data_len; } rc = ica_aes_gcm_intermediate(out_data, (unsigned int)out_len, buffer, ucb, auth_data, (unsigned int)auth_data_len, tag_data, (unsigned int)tag_data_len, attr->pValue, (unsigned int)attr->ulValueLen, subkey, 0); } if( rc != 0) { TRACE_ERROR("ica_aes_gcm_update failed with %lx.\n", rc); rc = CKR_FUNCTION_FAILED; goto done; } (*out_data_len) = out_len; context->ulClen += out_len; /* AAD only processed in first update seuence, * mark it empty for all subsequent calls */ context->ulAlen = 0; done: if (buffer) free(buffer); return rc; } CK_RV token_specific_aes_gcm_final(SESSION *sess, ENCR_DECR_CONTEXT *ctx, CK_BYTE *out_data, CK_ULONG *out_data_len, CK_BYTE encrypt) { CK_RV rc = CKR_OK; CK_ATTRIBUTE *attr = NULL; OBJECT *key = NULL; AES_GCM_CONTEXT *context = NULL; CK_GCM_PARAMS *aes_gcm_param = NULL; CK_BYTE *icb, *ucb; CK_BYTE *tag_data, *subkey, *auth_data, *final_tag_data; CK_ULONG auth_data_len, tag_data_len; CK_BYTE *buffer = NULL; /* find key object */ rc = object_mgr_find_in_map_nocache(ctx->key, &key); if(rc != CKR_OK) { TRACE_ERROR("Failed to find specified object.\n"); return rc; } if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } context = (AES_GCM_CONTEXT *)ctx->context; ucb = (CK_BYTE *)context->ucb; icb = (CK_BYTE *)context->icb; tag_data = context->hash; subkey = (CK_BYTE *)context->subkey; aes_gcm_param = (CK_GCM_PARAMS *)ctx->mech.pParameter; auth_data = (CK_BYTE *)aes_gcm_param->pAAD; auth_data_len = aes_gcm_param->ulAADLen; tag_data_len = (aes_gcm_param->ulTagBits + 7) / 8; if (encrypt) { if (context->len != 0) { buffer = (CK_BYTE*) malloc (AES_BLOCK_SIZE); if (!buffer) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } memcpy(buffer, context->data, context->len); rc = ica_aes_gcm_intermediate(buffer, context->len, out_data, ucb, auth_data, context->ulAlen, tag_data, AES_BLOCK_SIZE, attr->pValue, (unsigned int)attr->ulValueLen, subkey, 1); if (rc != 0) { TRACE_ERROR("ica_aes_gcm_intermediate() " "failed to encrypt\n"); rc = CKR_FUNCTION_FAILED; goto done; } context->ulClen += context->len; *out_data_len = context->len + tag_data_len; } else *out_data_len = tag_data_len; TRACE_DEVEL("GCM Final: context->len=%ld, tag_data_len=%ld, out_data_len=%ld\n", context->len, tag_data_len, *out_data_len); rc = ica_aes_gcm_last(icb, (unsigned int)auth_data_len, (unsigned int)context->ulClen, tag_data, NULL, 0, attr->pValue, (unsigned int) attr->ulValueLen, subkey, 1); if (rc != 0) { TRACE_ERROR("ica_aes_gcm_final failed with %lx.\n", rc); rc = CKR_FUNCTION_FAILED; goto done; } memcpy(out_data + context->len, tag_data, tag_data_len); } else { /* decrypt */ if (context->len > tag_data_len) { buffer = (CK_BYTE*) malloc(AES_BLOCK_SIZE); if (!buffer) { TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); rc = CKR_HOST_MEMORY; goto done; } memcpy(buffer, context->data, context->len - tag_data_len); rc = ica_aes_gcm_intermediate(out_data, (unsigned int)context->len-tag_data_len, buffer, ucb, auth_data, (unsigned int)context->ulAlen, tag_data, AES_BLOCK_SIZE, attr->pValue, (unsigned int) attr->ulValueLen, subkey, 0); if (rc != 0) { TRACE_ERROR("ica_aes_gcm_intermediate() " "failed to decrypt.\n"); rc = CKR_FUNCTION_FAILED; goto done; } (*out_data_len) = context->len - tag_data_len; context->ulClen += context->len - tag_data_len; } else if (context->len == tag_data_len) { /* remaining data are tag data */ *out_data_len = 0; } else { /* (context->len < tag_data_len) */ TRACE_ERROR("Incoming data are not consistent.\n"); rc = CKR_DATA_INVALID; goto done; } final_tag_data = context->data + context->len - tag_data_len; rc = ica_aes_gcm_last(icb, aes_gcm_param->ulAADLen, context->ulClen, tag_data, final_tag_data, tag_data_len, attr->pValue, (unsigned int)attr->ulValueLen, subkey, 0); if (rc != 0) { TRACE_ERROR("ica_aes_gcm_final failed with %lx.\n", rc); rc = CKR_FUNCTION_FAILED; } } done: if (buffer) free(buffer); return rc; } /** * In libica for AES-OFB Mode it uses one function for both encrypt and decrypt * The variable direction is used as an indicator either for encrypt or decrypt * 0 -- Decrypt * 1 -- Encrypt */ CK_RV token_specific_aes_ofb(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, OBJECT *key, CK_BYTE *init_v, uint_32 direction) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } rc = ica_aes_ofb(in_data, out_data, (unsigned long) in_data_len, attr->pValue, (unsigned int) attr->ulValueLen, init_v, direction); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } return rc; } /** * In libica for AES-CFB Mode it uses one function for both encrypt and decrypt * The variable direction is used as an indicator either for encrypt or decrypt * 0 -- Decrypt * 1 -- Encrypt */ CK_RV token_specific_aes_cfb(CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, OBJECT *key, CK_BYTE *init_v, uint_32 lcfb, uint_32 direction) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } rc = ica_aes_cfb(in_data, out_data, (unsigned long) in_data_len, attr->pValue, (unsigned int) attr->ulValueLen, init_v, lcfb, direction); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } return rc; } CK_RV token_specific_aes_mac(CK_BYTE *message, CK_ULONG message_len, OBJECT *key, CK_BYTE *mac) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; if (template_attribute_find(key->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("Could not find CKA_VALUE for the key.\n"); return CKR_FUNCTION_FAILED; } rc = ica_aes_cmac_intermediate(message, (unsigned long) message_len, attr->pValue, (unsigned int) attr->ulValueLen, mac); if (rc != 0) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; } return rc; } #endif #ifndef NODH // This computes DH shared secret, where: // Output: z is computed shared secret // Input: y is other party's public key // x is private key // p is prime // All length's are in number of bytes. All data comes in as Big Endian. CK_RV token_specific_dh_pkcs_derive( CK_BYTE *z, CK_ULONG *z_len, CK_BYTE *y, CK_ULONG y_len, CK_BYTE *x, CK_ULONG x_len, CK_BYTE *p, CK_ULONG p_len) { CK_RV rc ; BIGNUM *bn_z, *bn_y, *bn_x, *bn_p ; BN_CTX *ctx; // Create and Init the BIGNUM structures. bn_y = BN_new() ; bn_x = BN_new() ; bn_p = BN_new() ; bn_z = BN_new() ; if (bn_z == NULL || bn_p == NULL || bn_x == NULL || bn_y == NULL) { if (bn_y) BN_free(bn_y); if (bn_x) BN_free(bn_x); if (bn_p) BN_free(bn_p); if (bn_z) BN_free(bn_z); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } BN_init(bn_y) ; BN_init(bn_x) ; BN_init(bn_p) ; // Initialize context ctx=BN_CTX_new(); if (ctx == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // Add data into these new BN structures BN_bin2bn((char *)y, y_len, bn_y); BN_bin2bn((char *)x, x_len, bn_x); BN_bin2bn((char *)p, p_len, bn_p); rc = BN_mod_exp(bn_z,bn_y,bn_x,bn_p,ctx); if (rc == 0) { BN_free(bn_z); BN_free(bn_y); BN_free(bn_x); BN_free(bn_p); BN_CTX_free(ctx); TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } *z_len = BN_num_bytes(bn_z); BN_bn2bin(bn_z, z); BN_free(bn_z); BN_free(bn_y); BN_free(bn_x); BN_free(bn_p); BN_CTX_free(ctx); return CKR_OK; } /* end token_specific_dh_pkcs_derive() */ // This computes DH key pair, where: // Output: priv_tmpl is generated private key // pub_tmpl is computed public key // Input: pub_tmpl is public key (prime and generator) // All length's are in number of bytes. All data comes in as Big Endian. CK_RV token_specific_dh_pkcs_key_pair_gen( TEMPLATE * publ_tmpl, TEMPLATE * priv_tmpl ) { CK_BBOOL rc; CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *temp_attr = NULL ; CK_ATTRIBUTE *value_bits_attr = NULL; CK_BYTE *temp_byte; CK_ULONG temp_bn_len ; DH *dh ; BIGNUM *bn_p ; BIGNUM *bn_g ; BIGNUM *temp_bn ; rc = template_attribute_find( publ_tmpl, CKA_PRIME, &prime_attr ); rc &= template_attribute_find( publ_tmpl, CKA_BASE, &base_attr ); if (rc == FALSE) { TRACE_ERROR("Could not find CKA_PRIME or CKA_BASE for the key.\n"); return CKR_FUNCTION_FAILED; } if ((prime_attr->ulValueLen > 256) || (prime_attr->ulValueLen < 64)) { TRACE_ERROR("CKA_PRIME attribute value is invalid.\n"); return CKR_ATTRIBUTE_VALUE_INVALID; } dh = DH_new() ; if (dh == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // Create and init BIGNUM structs to stick in the DH struct bn_p = BN_new(); bn_g = BN_new(); if (bn_g == NULL || bn_p == NULL) { if (bn_g) BN_free(bn_g); if (bn_p) BN_free(bn_p); TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY)); return CKR_HOST_MEMORY; } BN_init(bn_p); BN_init(bn_g); // Convert from strings to BIGNUMs and stick them in the DH struct BN_bin2bn((char *)prime_attr->pValue, prime_attr->ulValueLen, bn_p); dh->p = bn_p; BN_bin2bn((char *)base_attr->pValue, base_attr->ulValueLen, bn_g); dh->g = bn_g; // Generate the DH Key if (!DH_generate_key(dh)) { TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); return CKR_FUNCTION_FAILED; } // Extract the public and private key components from the DH struct, // and insert them in the publ_tmpl and priv_tmpl // // pub_key // //temp_bn = BN_new(); temp_bn = dh->pub_key; temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte); rc = build_attribute( CKA_VALUE, temp_byte, temp_bn_len, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); return rc; } template_update_attribute( publ_tmpl, temp_attr ); free(temp_byte); // // priv_key // //temp_bn = BN_new(); temp_bn = dh->priv_key; temp_bn_len = BN_num_bytes(temp_bn); temp_byte = malloc(temp_bn_len); temp_bn_len = BN_bn2bin(temp_bn, temp_byte); rc = build_attribute( CKA_VALUE, temp_byte, temp_bn_len, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); return rc; } template_update_attribute( priv_tmpl, temp_attr ); free(temp_byte); // Update CKA_VALUE_BITS attribute in the private key value_bits_attr = (CK_ATTRIBUTE *)malloc( sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG) ); value_bits_attr->type = CKA_VALUE_BITS; value_bits_attr->ulValueLen = sizeof(CK_ULONG); value_bits_attr->pValue = (CK_BYTE *)value_bits_attr + sizeof(CK_ATTRIBUTE); *(CK_ULONG *)value_bits_attr->pValue = 8*temp_bn_len; template_update_attribute( priv_tmpl, value_bits_attr ); // Add prime and base to the private key template rc = build_attribute( CKA_PRIME,(char *)prime_attr->pValue, prime_attr->ulValueLen, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); return rc; } template_update_attribute( priv_tmpl, temp_attr ); rc = build_attribute( CKA_BASE,(char *)base_attr->pValue, base_attr->ulValueLen, &temp_attr ); // in bytes if (rc != CKR_OK) { TRACE_DEVEL("build_attribute failed\n"); return rc; } template_update_attribute( priv_tmpl, temp_attr ); // Cleanup DH key DH_free(dh) ; return CKR_OK ; } /* end token_specific_dh_key_pair_gen() */ #endif /* #ifndef NODH */ REF_MECH_LIST_ELEMENT ref_mech_list[] = { {92, CKM_RSA_PKCS_KEY_PAIR_GEN, {512, 4096, CKF_HW|CKF_GENERATE_KEY_PAIR}}, #if !(NODSA) // {1, CKM_DSA_KEY_PAIR_GEN, {512, 1024, CKF_HW|CKF_GENERATE_KEY_PAIR}}, #endif #if !(NOCDMF) // {4, CKM_CDMF_KEY_GEN, {0, 0, CKF_HW|CKF_GENERATE}}, #endif {80, CKM_DES_KEY_GEN, {8, 8, CKF_HW|CKF_GENERATE}}, {80, CKM_DES3_KEY_GEN, {24, 24, CKF_HW|CKF_GENERATE}}, {90, CKM_RSA_PKCS, {512, 4096, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP| CKF_SIGN|CKF_VERIFY|CKF_SIGN_RECOVER|CKF_VERIFY_RECOVER}}, #if !(NOX509) {90, CKM_RSA_X_509, {512, 4096, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP| CKF_SIGN|CKF_VERIFY|CKF_SIGN_RECOVER|CKF_VERIFY_RECOVER}}, #endif {90, CKM_RSA_PKCS_OAEP, {512, 4096, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {90, CKM_RSA_PKCS_PSS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {107, CKM_MD2_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {108, CKM_MD5_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {190, CKM_SHA1_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {190, CKM_SHA256_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {190, CKM_SHA384_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {190, CKM_SHA512_RSA_PKCS, {512, 4096, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {20, CKM_DES_ECB, {8, 8, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {21, CKM_DES_CBC, {8, 8, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT| CKF_WRAP|CKF_UNWRAP}}, {21, CKM_DES_CBC_PAD, {8, 8, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {41, CKM_DES3_ECB, {24, 24, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {42, CKM_DES3_CBC, {24, 24, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {42, CKM_DES3_CBC_PAD, {24, 24, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {49, CKM_DES3_MAC, {24, 24, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {49, CKM_DES3_MAC_GENERAL, {24, 24, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {24, CKM_DES_CFB8, {8, 8, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {44, CKM_DES_OFB64, {8, 8, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {45, CKM_DES_CFB64, {8, 8, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {01, CKM_SHA_1, {0, 0, CKF_HW|CKF_DIGEST}}, {01, CKM_SHA_1_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {01, CKM_SHA_1_HMAC_GENERAL, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {03, CKM_SHA256, {0, 0, CKF_HW|CKF_DIGEST}}, {03, CKM_SHA256_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {03, CKM_SHA256_HMAC_GENERAL, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {04, CKM_SHA384, {0, 0, CKF_HW|CKF_DIGEST}}, {04, CKM_SHA384_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {04, CKM_SHA384_HMAC_GENERAL, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {05, CKM_SHA512, {0, 0, CKF_HW|CKF_DIGEST}}, {05, CKM_SHA512_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {05, CKM_SHA512_HMAC_GENERAL, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, #if !(NOMD5) {53, CKM_MD5, {0, 0, CKF_HW|CKF_DIGEST}}, {54, CKM_MD5_HMAC, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {55, CKM_MD5_HMAC_GENERAL, {0, 0, CKF_HW|CKF_SIGN|CKF_VERIFY}}, #endif #if !(NOAES) {80, CKM_AES_KEY_GEN, {16, 32, CKF_HW|CKF_GENERATE}}, {60, CKM_AES_ECB, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {61, CKM_AES_CBC, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {61, CKM_AES_CBC_PAD, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {63, CKM_AES_OFB, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {64, CKM_AES_CFB8, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP| CKF_UNWRAP}}, {64, CKM_AES_CFB64, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {64, CKM_AES_CFB128, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {65, CKM_AES_CTR, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}}, {70, CKM_AES_GCM, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {70, CKM_AES_GCM, {16, 32, CKF_HW|CKF_ENCRYPT|CKF_DECRYPT}}, {68, CKM_AES_MAC, {16, 32, CKF_HW|CKF_SIGN|CKF_VERIFY}}, {68, CKM_AES_MAC_GENERAL, {16, 32, CKF_HW|CKF_SIGN|CKF_VERIFY}}, #endif {80, CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW|CKF_GENERATE}}, }; CK_ULONG ref_mech_list_len = (sizeof(ref_mech_list) / sizeof(MECH_LIST_ELEMENT)); /** * new ica-token mechanism table * this list will be initialized the first time * when ica_get_functionlist (from libica) is called. * (preinitialized with software only supported mechanisms) */ MECH_LIST_ELEMENT mech_list[] = { {CKM_MD5, {0, 0, CKF_DIGEST}}, {CKM_MD5_HMAC, {0, 0, CKF_SIGN | CKF_VERIFY}}, {CKM_MD5_HMAC_GENERAL, {0, 0, CKF_SIGN | CKF_VERIFY}}, {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,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,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,{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}} }; CK_ULONG mech_list_len = 3; CK_RV token_specific_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { CK_ULONG rc = CKR_OK; rc = ica_specific_get_mechanism_list(pMechanismList, pulCount); if (rc != CKR_OK) { return CKR_FUNCTION_FAILED; } return rc; } CK_RV ica_specific_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { unsigned int i; CK_ULONG rc = CKR_OK; if (pulCount == NULL) { return CKR_ARGUMENTS_BAD; } if (!mech_list_ica_init) { rc = mech_list_ica_initialize(); if (rc != CKR_OK) { TRACE_ERROR("mech_list_ica_initialize failed\n"); return rc; } } if (pMechanismList == NULL) { *pulCount = mech_list_len; return CKR_OK; } if ((*pulCount) < mech_list_len) { (*pulCount) = mech_list_len; TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL)); return CKR_BUFFER_TOO_SMALL; } /* copy mechanisms from the internal mech_ica_list */ for (i=0; i < mech_list_len; i++) { pMechanismList[i] = mech_list[i].mech_type; } (*pulCount) = mech_list_len; return CKR_OK; } CK_RV token_specific_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_ULONG rc = CKR_OK; rc = ica_specific_get_mechanism_info(type, pInfo); return rc; } CK_RV ica_specific_get_mechanism_info (CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { int rc = CKR_OK; unsigned int i; if (!mech_list_ica_init) { rc = mech_list_ica_initialize(); if (rc != CKR_OK) { TRACE_ERROR("mech_list_ica_initialize failed\n"); return rc; } } /* * find the requested mechanism and grab additional * mechanism specific information (mech_info) from mech_list_ica */ for (i=0; i < mech_list_len; i++) { if (mech_list[i].mech_type == type) { pInfo->flags = mech_list[i].mech_info.flags; pInfo->ulMinKeySize = mech_list[i].mech_info.ulMinKeySize; pInfo->ulMaxKeySize = mech_list[i].mech_info.ulMaxKeySize; return CKR_OK; } } TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); return CKR_MECHANISM_INVALID; } CK_RV getRefListIdxfromId(CK_ULONG ica_idx, CK_ULONG_PTR pRefIdx) { unsigned int n; for (n=*pRefIdx; n < ref_mech_list_len; n++) { if (ica_idx == ref_mech_list[n].lica_idx) { *pRefIdx = n; return CKR_OK; } } return CKR_MECHANISM_INVALID; } CK_RV getRefListIdxfromMech(CK_ULONG mech, CK_ULONG_PTR pRefIdx) { unsigned int n; for (n=*pRefIdx; n < ref_mech_list_len; n++) { if (mech == ref_mech_list[n].mech_type) { *pRefIdx = n; return CKR_OK; } } return CKR_MECHANISM_INVALID; } CK_BBOOL isMechanismAvailable(CK_ULONG mechanism) { unsigned int i; for (i = 0; i < mech_list_len; i++) { if (mech_list[i].mech_type == mechanism) return TRUE; } return FALSE; } CK_RV addMechanismToList(CK_ULONG mechanism) { CK_ULONG ret; CK_ULONG refIdx = 0; ret = getRefListIdxfromMech(mechanism, &refIdx); if (ret != CKR_OK) { return CKR_FUNCTION_FAILED; } mech_list[mech_list_len].mech_type = ref_mech_list[refIdx].mech_type; mech_list[mech_list_len].mech_info.flags = (ref_mech_list[refIdx].mech_info.flags & 0xfffffffe); mech_list[mech_list_len].mech_info.ulMinKeySize = ref_mech_list[refIdx].mech_info.ulMinKeySize; mech_list[mech_list_len].mech_info.ulMaxKeySize = ref_mech_list[refIdx].mech_info.ulMaxKeySize; mech_list_len++; return CKR_OK; } /* * call libica to receive list of supported mechanisms * This method is called once per opencryptoki instance (application context) */ CK_RV mech_list_ica_initialize(void) { CK_ULONG ret, rc = CKR_OK; unsigned int i, n; unsigned int ica_specific_mech_list_len; CK_ULONG tmp, ulActMechCtr, ulPreDefMechCtr, refIdx; rc = ica_get_functionlist(NULL, &ica_specific_mech_list_len); if (rc != CKR_OK) { TRACE_ERROR("ica_get_functionlist failed\n"); return CKR_FUNCTION_FAILED; } libica_func_list_element libica_func_list[ica_specific_mech_list_len]; rc = ica_get_functionlist(libica_func_list, &ica_specific_mech_list_len); if (rc != CKR_OK) { TRACE_ERROR("ica_get_functionlist failed\n"); return CKR_FUNCTION_FAILED; } /* * grab the mechanism of the corresponding ID returned by libICA * from the internel reference list put the mechanism ID and the * HW support indication into an internel ica_mech_list and get * additional flag information from the reference list */ ulPreDefMechCtr = mech_list_len; for (i=0; i < ica_specific_mech_list_len; i++) { // loop over libica supported list ulActMechCtr = -1; /* --- walk through the whole reflist and fetch all * matching mechanism's (if present) --- */ refIdx = 0; while (refIdx >= 0) { ret = getRefListIdxfromId(libica_func_list[i].mech_mode_id, &refIdx); if (ret != CKR_OK) { // continue with the next libica mechanism break; } /* Loop over the predefined mechanism list and check * if we have to overrule a software implemented * mechanism from token by libica HW supported * mechanism. */ for (n=0; n < ulPreDefMechCtr; n++) { if (mech_list[n].mech_type == ref_mech_list[refIdx].mech_type){ ulActMechCtr = n; break; } } if (ulActMechCtr == -1) { /* add a new entry */ mech_list[mech_list_len].mech_type = ref_mech_list[refIdx].mech_type; mech_list[mech_list_len].mech_info.flags = (libica_func_list[i].flags & 0x01) | (ref_mech_list[refIdx].mech_info.flags & 0xfffffffe); mech_list[mech_list_len].mech_info.ulMinKeySize = ref_mech_list[refIdx].mech_info.ulMinKeySize; mech_list[mech_list_len].mech_info.ulMaxKeySize = ref_mech_list[refIdx].mech_info.ulMaxKeySize; mech_list_len++; } else { /* replace existing entry */ mech_list[ulActMechCtr].mech_info.flags = (libica_func_list[i].flags & 0x01) | mech_list[ulActMechCtr].mech_info.flags ; } refIdx++; } } /* * check if special combined mechanisms are supported * if SHA1 and RSA is available -> insert CKM_SHA1_RSA_PKCS * if SHA256 and RSA is available -> insert CKM_SHA256_RSA_PKCS * if MD2 and RSA is available -> insert CKM_MD2_RSA_PKCS * if MD5 and RSA is available -> insert CKM_MD5_RSA_PKCS */ if (isMechanismAvailable(CKM_SHA_1) && isMechanismAvailable(CKM_RSA_PKCS)) addMechanismToList(CKM_SHA1_RSA_PKCS); if (isMechanismAvailable(CKM_SHA256) && isMechanismAvailable(CKM_RSA_PKCS)) addMechanismToList(CKM_SHA256_RSA_PKCS); if (isMechanismAvailable(CKM_SHA384) && isMechanismAvailable(CKM_RSA_PKCS)) addMechanismToList(CKM_SHA384_RSA_PKCS); if (isMechanismAvailable(CKM_SHA512) && isMechanismAvailable(CKM_RSA_PKCS)) addMechanismToList(CKM_SHA512_RSA_PKCS); if (isMechanismAvailable(CKM_MD2) && isMechanismAvailable(CKM_RSA_PKCS)) addMechanismToList(CKM_MD2_RSA_PKCS); if (isMechanismAvailable(CKM_MD5) && isMechanismAvailable(CKM_RSA_PKCS)) addMechanismToList(CKM_MD5_RSA_PKCS); /* sort the mech_list_ica by mechanism ID's (bubble sort) */ for(i=0;i < mech_list_len ; i++) { for (n=i; n < mech_list_len; n++) { if (mech_list[i].mech_type > mech_list[n].mech_type) { tmp = mech_list[i].mech_type; mech_list[i].mech_type = mech_list[n].mech_type; mech_list[n].mech_type = tmp; tmp = mech_list[i].mech_info.ulMinKeySize; mech_list[i].mech_info.ulMinKeySize = mech_list[n].mech_info.ulMinKeySize; mech_list[n].mech_info.ulMinKeySize = tmp; tmp = mech_list[i].mech_info.ulMaxKeySize; mech_list[i].mech_info.ulMaxKeySize = mech_list[n].mech_info.ulMaxKeySize; mech_list[n].mech_info.ulMaxKeySize = tmp; tmp = mech_list[i].mech_info.flags; mech_list[i].mech_info.flags = mech_list[n].mech_info.flags; mech_list[n].mech_info.flags = tmp; } } } mech_list_ica_init = TRUE; return rc; } CK_RV token_specific_generic_secret_key_gen(TEMPLATE *tmpl) { CK_ATTRIBUTE *attr = NULL; CK_RV rc = CKR_OK; CK_BYTE secret_key[MAX_GENERIC_KEY_SIZE]; CK_ULONG key_length = 0; CK_ULONG key_length_in_bits = 0; CK_ATTRIBUTE *value_attr = NULL; rc = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr); if (rc == FALSE) { TRACE_ERROR("CKA_VALUE_LEM missing in key template\n"); return CKR_TEMPLATE_INCOMPLETE; } key_length = *(CK_ULONG *)attr->pValue; //app specified key length in bytes key_length_in_bits = key_length * 8; /* After looking at fips cavs test vectors for HMAC ops, * it was decided that the key length should fall between * 80 and 2048 bits inclusive. */ if ((key_length_in_bits < 80) || (key_length_in_bits > 2048 )) { TRACE_ERROR("Generic secret key size of %lu bits not within" " required range of 80-2048 bits\n", key_length_in_bits); return CKR_KEY_SIZE_RANGE; } /* libica does not have generic secret key generation, * so call token rng here. */ rc = rng_generate(secret_key, key_length); if (rc != CKR_OK) { TRACE_DEVEL("Generic secret key generation failed.\n"); return rc; } rc = build_attribute(CKA_VALUE, secret_key, key_length, &value_attr); if (rc != CKR_OK) { TRACE_DEVEL("build_attribute(CKA_VALUE) failed\n"); return rc; } rc = template_update_attribute(tmpl, value_attr); if (rc != CKR_OK) TRACE_DEVEL("template_update_attribute(CKA_VALUE) failed\n"); return rc; } opencryptoki+dfsg/usr/lib/pkcs11/ica_s390_stdll/ica_specific.h0000644000175000017500000003672212630407154023260 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2013 */ #ifndef __ICA_SPECIFIC_H #define __ICA_SPECIFIC_H CK_BBOOL mech_list_ica_init = FALSE; typedef struct _REF_MECH_LIST_ELEMENT { CK_ULONG lica_idx; CK_MECHANISM_TYPE mech_type; CK_MECHANISM_INFO mech_info; } REF_MECH_LIST_ELEMENT; extern REF_MECH_LIST_ELEMENT ref_mech_list[]; extern CK_ULONG ref_mech_list_len; CK_RV ica_specific_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount); CK_RV ica_specific_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); CK_RV mech_list_ica_initialize(void); #endif opencryptoki+dfsg/usr/lib/pkcs11/ep11_stdll/0000755000175000017500000000000012630407154017730 5ustar xnoxxnoxopencryptoki+dfsg/usr/lib/pkcs11/ep11_stdll/ep11_specific.h0000644000175000017500000000726612630407154022527 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki EP11 token - EP11 token functions * * (C) COPYRIGHT International Business Machines Corp. 2015 * */ #ifndef EP11_SPECIFIC_H #define EP11_SPECIFIC_H CK_RV ep11tok_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount); CK_RV ep11tok_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); CK_RV ep11tok_init(CK_SLOT_ID SlotNumber, char *conf_name); CK_RV ep11tok_final(void); CK_RV ep11tok_generate_key(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle); CK_RV ep11tok_derive_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE hBaseKey, CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len); CK_RV ep11tok_generate_key_pair(SESSION * sess, 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); CK_RV ep11tok_sign_init(SESSION *session, CK_MECHANISM *mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key); CK_RV ep11tok_sign(SESSION *session, CK_BBOOL length_only, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG *sig_len); CK_RV ep11tok_sign_update(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV ep11tok_sign_final(SESSION *session, CK_BBOOL length_only, CK_BYTE *signature, CK_ULONG *sig_len); CK_RV ep11tok_verify_init(SESSION *session, CK_MECHANISM *mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key); CK_RV ep11tok_verify(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len); CK_RV ep11tok_verify_update(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len); CK_RV ep11tok_verify_final(SESSION *session, CK_BYTE *signature, CK_ULONG sig_len); CK_RV ep11tok_decrypt_final(SESSION *session, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len); CK_RV ep11tok_decrypt(SESSION *session, CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len); CK_RV ep11tok_decrypt_update(SESSION *session, CK_BYTE_PTR input_part, CK_ULONG input_part_len, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len); CK_RV ep11tok_encrypt_final(SESSION *session, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len); CK_RV ep11tok_encrypt(SESSION *session, CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len); CK_RV ep11tok_encrypt_update(SESSION *session, CK_BYTE_PTR input_part, CK_ULONG input_part_len, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len); CK_RV ep11tok_encrypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key); CK_RV ep11tok_decrypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key); CK_RV ep11tok_wrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR p_wrapped_key_len); CK_RV ep11tok_wrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR p_wrapped_key_len); CK_RV ep11tok_unwrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE_PTR p_key); #endif opencryptoki+dfsg/usr/lib/pkcs11/ep11_stdll/ep11.h0000644000175000017500000003054212630407154020653 0ustar xnoxxnox/*---------------------------------------------------------------------- * (C) COPYRIGHT INTERNATIONAL BUSINESS MACHINES CORPORATION 2005-2013 * ALL RIGHTS RESERVED * IBM Research & Development *---------------------------------------------------------------------- * Author: Urban, Volker (volker.urban@de.ibm.com) *----------------------------------------------------------------------*/ #if ! defined(__EP11_H__) #define __EP11_H__ #if !defined(CKR_OK) /* don't assume include guards */ #include "pkcs11.h" #endif #if !defined(INT64_MIN) #error "We need 64-bit types, please include before this file." #endif // SHA224 etc. are additions to PKCS#11 2.20 // remove these when host migrates beyond 2.20 // #if !defined(CKM_SHA224) #define CKM_SHA224 0x00000255 #define CKM_SHA224_HMAC 0x00000256 #define CKM_SHA224_HMAC_GENERAL 0x00000257 #define CKM_SHA224_RSA_PKCS 0x00000046 #define CKM_SHA224_RSA_PKCS_PSS 0x00000047 #define CKM_SHA224_KEY_DERIVATION 0x00000396 #define CKM_AES_CTR 0x00001086 #define CKG_MGF1_SHA224 0x00000005 #endif #if !defined(CKM_AES_CMAC) #define CKM_AES_CMAC 0x0000108a #endif #if !defined(CKM_ALG_DES3_CMAC) #define CKM_DES3_CMAC 0x00000138 #endif /*---------------------------------------------------------------------- * CK_... type arguments correspond to the original PKCS#11 call's * arguments. Standard types mean PKCS#11 objects (session, token etc.) * are mapped to a native type (key blob, mechanism) etc. * * As an example, for _Encrypt and _Decrypt, a session is passed to * the PKCS#11 function. This session needs to be matched to a key blob, * so our _Encrypt interface takes a key/keylen buffer instead of the * session. All other parameters should be passed through unchanged. * * For certain operations, such as _GenerateKey, there are no real * PKCS#11 type parameters at this level. */ CK_RV m_GenerateRandom (CK_BYTE_PTR rnd, CK_ULONG len, uint64_t target) ; /**/ /* note: external seeding not supported */ CK_RV m_SeedRandom (CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen, uint64_t target) ; CK_RV m_DigestInit (unsigned char *state, size_t *len, const CK_MECHANISM_PTR pmech, uint64_t target) ; /**/ CK_RV m_Digest (const unsigned char *state, size_t slen, CK_BYTE_PTR data, CK_ULONG len, CK_BYTE_PTR digest, CK_ULONG_PTR dglen, uint64_t target) ; CK_RV m_DigestUpdate (unsigned char *state, size_t slen, CK_BYTE_PTR data, CK_ULONG dlen, uint64_t target) ; CK_RV m_DigestKey (unsigned char *state, size_t slen, const unsigned char *key, size_t klen, uint64_t target) ; CK_RV m_DigestFinal (const unsigned char *state, size_t slen, CK_BYTE_PTR digest, CK_ULONG_PTR dlen, uint64_t target) ; CK_RV m_DigestSingle (CK_MECHANISM_PTR pmech, CK_BYTE_PTR data, CK_ULONG len, CK_BYTE_PTR digest, CK_ULONG_PTR dlen, uint64_t target) ; CK_RV m_EncryptInit (unsigned char *state, size_t *slen, CK_MECHANISM_PTR pmech, const unsigned char *key, size_t klen, uint64_t target) ; CK_RV m_DecryptInit (unsigned char *state, size_t *slen, CK_MECHANISM_PTR pmech, const unsigned char *key, size_t klen, uint64_t target) ; /**/ CK_RV m_EncryptUpdate (unsigned char *state, size_t slen, CK_BYTE_PTR plain, CK_ULONG plen, CK_BYTE_PTR cipher, CK_ULONG_PTR clen, uint64_t target) ; CK_RV m_DecryptUpdate (unsigned char *state, size_t slen, CK_BYTE_PTR cipher, CK_ULONG clen, CK_BYTE_PTR plain, CK_ULONG_PTR plen, uint64_t target) ; /**/ /* one-pass en/decrypt with key blob */ CK_RV m_Encrypt (const unsigned char *state, size_t slen, CK_BYTE_PTR plain, CK_ULONG plen, CK_BYTE_PTR cipher, CK_ULONG_PTR clen, uint64_t target) ; CK_RV m_Decrypt (const unsigned char *state, size_t slen, CK_BYTE_PTR cipher, CK_ULONG clen, CK_BYTE_PTR plain, CK_ULONG_PTR plen, uint64_t target) ; /**/ CK_RV m_EncryptFinal (const unsigned char *state, size_t slen, CK_BYTE_PTR output, CK_ULONG_PTR len, uint64_t target) ; CK_RV m_DecryptFinal (const unsigned char *state, size_t slen, CK_BYTE_PTR output, CK_ULONG_PTR len, uint64_t target) ; /**/ /* en/decrypt directly with key blob */ CK_RV m_EncryptSingle (const unsigned char *key, size_t klen, CK_MECHANISM_PTR mech, CK_BYTE_PTR plain, CK_ULONG plen, CK_BYTE_PTR cipher, CK_ULONG_PTR clen, uint64_t target) ; CK_RV m_DecryptSingle (const unsigned char *key, size_t klen, CK_MECHANISM_PTR mech, CK_BYTE_PTR cipher, CK_ULONG clen, CK_BYTE_PTR plain, CK_ULONG_PTR plen, uint64_t target) ; /**/ /* de+encrypt in one pass, without exposing cleartext */ CK_RV m_ReencryptSingle (const unsigned char *dkey, size_t dklen, const unsigned char *ekey, size_t eklen, CK_MECHANISM_PTR pdecrmech, CK_MECHANISM_PTR pencrmech, CK_BYTE_PTR in, CK_ULONG ilen, CK_BYTE_PTR out, CK_ULONG_PTR olen, uint64_t target) ; CK_RV m_GenerateKey (CK_MECHANISM_PTR pmech, CK_ATTRIBUTE_PTR ptempl, CK_ULONG templcount, const unsigned char *pin, size_t pinlen, unsigned char *key, size_t *klen, unsigned char *csum, size_t *clen, uint64_t target) ; /**/ CK_RV m_GenerateKeyPair (CK_MECHANISM_PTR pmech, CK_ATTRIBUTE_PTR ppublic, CK_ULONG pubattrs, CK_ATTRIBUTE_PTR pprivate, CK_ULONG prvattrs, const unsigned char *pin, size_t pinlen, unsigned char *key, size_t *klen, unsigned char *pubkey, size_t *pklen, uint64_t target) ; CK_RV m_SignInit (unsigned char *state, size_t *slen, CK_MECHANISM_PTR alg, const unsigned char *key, size_t klen, uint64_t target) ; CK_RV m_VerifyInit (unsigned char *state, size_t *slen, CK_MECHANISM_PTR alg, const unsigned char *key, size_t klen, uint64_t target) ; /**/ CK_RV m_SignUpdate (unsigned char *state, size_t slen, CK_BYTE_PTR data, CK_ULONG dlen, uint64_t target) ; CK_RV m_VerifyUpdate (unsigned char *state, size_t slen, CK_BYTE_PTR data, CK_ULONG dlen, uint64_t target) ; /**/ CK_RV m_SignFinal (const unsigned char *state, size_t stlen, CK_BYTE_PTR sig, CK_ULONG_PTR siglen, uint64_t target) ; CK_RV m_VerifyFinal (const unsigned char *state, size_t stlen, CK_BYTE_PTR sig, CK_ULONG siglen, uint64_t target) ; /**/ CK_RV m_Sign (const unsigned char *state, size_t stlen, CK_BYTE_PTR data, CK_ULONG dlen, CK_BYTE_PTR sig, CK_ULONG_PTR siglen, uint64_t target) ; CK_RV m_Verify (const unsigned char *state, size_t stlen, CK_BYTE_PTR data, CK_ULONG dlen, CK_BYTE_PTR sig, CK_ULONG siglen, uint64_t target) ; /**/ CK_RV m_SignSingle (const unsigned char *key, size_t klen, CK_MECHANISM_PTR pmech, CK_BYTE_PTR data, CK_ULONG dlen, CK_BYTE_PTR sig, CK_ULONG_PTR slen, uint64_t target) ; CK_RV m_VerifySingle (const unsigned char *key, size_t klen, CK_MECHANISM_PTR pmech, CK_BYTE_PTR data, CK_ULONG dlen, CK_BYTE_PTR sig, CK_ULONG slen, uint64_t target) ; /* mackey is NULL for PKCS#11 formats, not for authenticated ones */ CK_RV m_WrapKey (const unsigned char *key, size_t keylen, const unsigned char *kek, size_t keklen, const unsigned char *mackey, size_t mklen, const CK_MECHANISM_PTR pmech, CK_BYTE_PTR wrapped, CK_ULONG_PTR wlen, uint64_t target) ; /**/ /* mackey is NULL for PKCS#11 formats, not for authenticated ones */ CK_RV m_UnwrapKey (const CK_BYTE_PTR wrapped, CK_ULONG wlen, const unsigned char *kek, size_t keklen, const unsigned char *mackey, size_t mklen, const unsigned char *pin, size_t pinlen, const CK_MECHANISM_PTR uwmech, const CK_ATTRIBUTE_PTR ptempl, CK_ULONG pcount, unsigned char *unwrapped, size_t *uwlen, CK_BYTE_PTR csum, CK_ULONG *cslen, uint64_t target) ; CK_RV m_DeriveKey ( CK_MECHANISM_PTR pderivemech, CK_ATTRIBUTE_PTR ptempl, CK_ULONG templcount, const unsigned char *basekey, size_t bklen, const unsigned char *data, size_t dlen, const unsigned char *pin, size_t pinlen, unsigned char *newkey, size_t *nklen, unsigned char *csum, size_t *cslen, uint64_t target) ; /**/ CK_RV m_GetMechanismList (CK_SLOT_ID slot, CK_MECHANISM_TYPE_PTR mechs, CK_ULONG_PTR count, uint64_t target) ; CK_RV m_GetMechanismInfo (CK_SLOT_ID slot, CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR pmechinfo, uint64_t target) ; CK_RV m_GetAttributeValue (const unsigned char *obj, size_t olen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, uint64_t target) ; CK_RV m_SetAttributeValue (unsigned char *obj, size_t olen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, uint64_t target) ; CK_RV m_Login ( CK_UTF8CHAR_PTR pin, CK_ULONG pinlen, const unsigned char *nonce, size_t nlen, unsigned char *pinblob, size_t *pinbloblen, uint64_t target) ; CK_RV m_Logout ( const unsigned char *pin, size_t len, uint64_t target) ; CK_RV m_admin (unsigned char *response1, size_t *r1len, unsigned char *response2, size_t *r2len, const unsigned char *cmd, size_t clen, const unsigned char *sigs, size_t slen, uint64_t target) ; /*-------------------------------------------------------------------------- * Module management. */ int m_add_backend(const char *name, unsigned int port) ; int m_init (void) ; int m_shutdown (void) ; #endif /* n defined(__EP11_H__) */ opencryptoki+dfsg/usr/lib/pkcs11/ep11_stdll/ep11_specific.c0000644000175000017500000036100412630407154022513 0ustar xnoxxnox/* Common Public License Version 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001,2002,2013 */ /*************************************************************************** Change Log ========== ****************************************************************************/ #define _BSD_SOURCE #include #include #include #include #include #include "pkcs11types.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "errno.h" #include "tok_specific.h" #include "tok_struct.h" #include "stdll.h" #include "attributes.h" #include "trace.h" #include #include #include #include #include #include #include #include #include #ifdef DEBUG #include #endif #include "ep11.h" #define EP11SHAREDLIB "libep11.so" CK_RV ep11tok_get_mechanism_list(CK_MECHANISM_TYPE_PTR mlist, CK_ULONG_PTR count); CK_RV ep11tok_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); #ifdef DEBUG /* a simple function for dumping out a memory area */ inline void hexdump(void *buf, size_t buflen) { /* 1 2 3 4 5 6 0123456789012345678901234567890123456789012345678901234567890123456789 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ................ */ int i, j; char line[68]; for (i=0; i < buflen; i += 16) { for (j=0; j < 16; j++) { if (i+j < buflen) { unsigned char b = ((unsigned char*)buf)[i+j]; sprintf(line + j*3, "%02hhx ", b); line[51+j] = (isalnum(b) ? b : '.'); } else { sprintf(line + j*3, " "); line[51+j] = ' '; } } line[47] = line[48] = line[49] = line[50] = ' '; line[67] = '\0'; TRACE_DEBUG("%s\n", line); } } #define TRACE_DEBUG_DUMP(_buf, _buflen) hexdump(_buf, _buflen) #endif /* DEBUG */ CK_CHAR manuf[] = "IBM Corp."; CK_CHAR model[] = "IBM EP11Tok "; CK_CHAR descr[] = "IBM PKCS#11 EP11 token"; CK_CHAR label[] = "IBM OS PKCS#11 "; /* largest blobsize ever seen is about 5k (for 4096 mod bits RSA keys) */ #define MAX_BLOBSIZE 8192 #define MAX_CSUMSIZE 64 #define MAX_DIGEST_STATE_BYTES 1024 #define MAX_CRYPT_STATE_BYTES 8192 #define MAX_SIGN_STATE_BYTES 8192 #define MAX_APQN 256 /* wrap_key is used for importing keys */ char wrap_key_name[] = "EP11_wrapkey"; /* blob and blobsize of wrap key */ CK_BYTE raw2key_wrap_blob[MAX_BLOBSIZE]; size_t raw2key_wrap_blob_l = 0; /* target list of adapters/domains, specified in a config file by user, tells the device driver which adapter/domain pairs should be used, they must have the same master key */ typedef struct { short format; short length; short apqns[2*MAX_APQN]; } __attribute__((packed)) ep11_target_t; static ep11_target_t ep11_targets; /* defined in the makefile, ep11 library can run standalone (without HW card), crypto algorithms are implemented in software then (no secure key) */ #ifdef EP11_STANDALONE static uint64_t ep11tok_target = 0x0000000100000008ull; #else #ifdef __s390x__ static uint64_t ep11tok_target = (uint64_t) &ep11_targets; #else #define ep11tok_target (uint64_t)(long)(&ep11_targets) #endif #endif /* */ static unsigned char *ep11_pin_blob = NULL; static CK_ULONG ep11_pin_blob_len = 0; /* mechanisms yet unknown by ock, but known by EP11 */ #define CKM_SHA224_RSA_PKCS 0x00000046 #define CKM_SHA224_RSA_PKCS_PSS 0x00000047 #define CKM_SHA384_RSA_PKCS_PSS 0x00000044 #define CKM_SHA512_RSA_PKCS_PSS 0x00000045 #define CKM_SHA224 0x00000255 #define CKM_SHA224_KEY_DERIVATION 0x00000396 #define CKM_SHA256_RSA_PKCS_PSS 0x00000043 #define CKM_SHA224_HMAC 0x00000256 #define CKM_SHA384_KEY_DERIVATION 0x00000394 #define CKM_SHA512_KEY_DERIVATION 0x00000395 static CK_BBOOL ep11_initialized = FALSE; static CK_RV check_key_attributes(CK_KEY_TYPE kt, CK_OBJECT_CLASS kc, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_ATTRIBUTE_PTR *p_attrs, CK_ULONG *p_attrs_len) { CK_RV rc; CK_ULONG i; CK_BBOOL true = TRUE; CK_ULONG check_types_pub[] = {CKA_VERIFY, CKA_ENCRYPT, CKA_WRAP }; CK_ULONG check_types_priv[] = {CKA_SIGN, CKA_DECRYPT, CKA_UNWRAP }; CK_ULONG check_types_sec[] = {CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP}; CK_ULONG check_types_gen_sec[] = {CKA_SIGN, CKA_VERIFY, CKA_ENCRYPT, CKA_DECRYPT}; CK_ULONG check_types_derive[] = {CKA_DERIVE}; CK_ULONG *check_types = NULL; CK_BBOOL *check_values[] = { &true, &true, &true, &true }; CK_ULONG attr_cnt = 0; /* check/add attributes for public key template */ if ((rc = dup_attribute_array(attrs, attrs_len, p_attrs, p_attrs_len))) return rc; switch (kc) { case CKO_SECRET_KEY: if (kt == CKK_GENERIC_SECRET) { check_types = &check_types_gen_sec[0]; attr_cnt = sizeof(check_types_gen_sec)/sizeof(CK_ULONG); } else { check_types = &check_types_sec[0]; attr_cnt = sizeof(check_types_sec)/sizeof(CK_ULONG); } break; case CKO_PUBLIC_KEY: if ((kt == CKK_EC) || (kt == CKK_ECDSA) || (kt == CKK_DSA)) { check_types = &check_types_pub[0]; attr_cnt = 1; /* only CKA_VERIFY */ } else if (kt == CKK_RSA) { check_types = &check_types_pub[0]; attr_cnt = sizeof(check_types_pub)/sizeof(CK_ULONG); } /* do nothing for CKM_DH_PKCS_KEY_PAIR_GEN and CKM_DH_PKCS_PARAMETER_GEN */ break; case CKO_PRIVATE_KEY: if ((kt == CKK_EC) || (kt == CKK_ECDSA) || (kt == CKK_DSA)) { check_types = &check_types_priv[0]; attr_cnt = 1; /* only CKA_SIGN */ } else if (kt == CKK_RSA) { check_types = &check_types_priv[0]; attr_cnt = sizeof(check_types_priv)/sizeof(CK_ULONG); } else if (kt == CKK_DH) { check_types = &check_types_derive[0]; attr_cnt = sizeof(check_types_derive)/sizeof(CK_ULONG); } break; default: return CKR_OK; } for (i = 0; i < attr_cnt; i++, check_types++) { CK_ATTRIBUTE_PTR attr = get_attribute_by_type(*p_attrs, *p_attrs_len, *check_types); if (!attr) { rc = add_to_attribute_array(p_attrs, p_attrs_len, *check_types, (CK_BYTE *) check_values[i], sizeof(*check_values[i])); if (rc) goto cleanup; } } return CKR_OK; cleanup: if (rc) { free_attribute_array(*p_attrs, *p_attrs_len); *p_attrs = NULL; *p_attrs_len = 0; } return rc; } CK_RV ber_encode_RSAPublicKey(CK_BBOOL length_only, CK_BYTE **data, CK_ULONG *data_len, CK_ATTRIBUTE *modulus, CK_ATTRIBUTE *publ_exp) { CK_ULONG len, offset, total, total_len; CK_RV rc; CK_BYTE *buf = NULL; CK_BYTE *buf2 = NULL; CK_BYTE *buf3 = NULL; BerValue *val; BerElement *ber; offset = 0; rc = 0; total_len = ber_AlgIdRSAEncryptionLen; total = 0; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, modulus->ulValueLen); offset += len; rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, publ_exp->ulValueLen); offset += len; if (rc != CKR_OK) { TRACE_DEVEL("%s ber_encode_Int failed with rc=0x%lx\n", __func__, rc); return CKR_FUNCTION_FAILED; } buf = (CK_BYTE *)malloc(offset); if (!buf) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } offset = 0; rc = 0; rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)modulus + sizeof(CK_ATTRIBUTE), modulus->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("%s ber_encode_Int failed with rc=0x%lx\n", __func__, rc); return rc; } memcpy(buf+offset, buf2, len); offset += len; free(buf2); rc = ber_encode_INTEGER(FALSE, &buf2, &len, (CK_BYTE *)publ_exp + sizeof(CK_ATTRIBUTE), publ_exp->ulValueLen); if (rc != CKR_OK) { TRACE_DEVEL("%s ber_encode_Int failed with rc=0x%lx\n", __func__, rc); return rc; } memcpy(buf+offset, buf2, len); offset += len; free(buf2); rc = ber_encode_SEQUENCE(FALSE, &buf2, &len, buf, offset); if (rc != CKR_OK) { TRACE_DEVEL("%s ber_encode_Seq failed with rc=0x%lx\n", __func__, rc); return rc; } /* length of outer sequence */ rc = ber_encode_OCTET_STRING(TRUE, NULL, &total, buf2, len); if (rc != CKR_OK) { TRACE_DEVEL("%s ber_encode_Oct_Str failed with rc=0x%lx\n", __func__, rc); return rc; } else total_len += total + 1; /* mem for outer sequence */ buf3 = (CK_BYTE *)malloc(total_len); if (!buf3) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } total_len = 0; /* copy alg id */ memcpy(buf3+total_len, ber_AlgIdRSAEncryption, ber_AlgIdRSAEncryptionLen); total_len += ber_AlgIdRSAEncryptionLen; /* need a bitstring */ ber = ber_alloc_t(LBER_USE_DER); rc = ber_put_bitstring(ber, buf2, len*8, 0x03); rc = ber_flatten(ber, &val); memcpy(buf3+total_len, val->bv_val, val->bv_len); total_len += val->bv_len; rc = ber_encode_SEQUENCE(FALSE, data, data_len, buf3, total_len); if (rc != CKR_OK) TRACE_DEVEL("%s ber_encode_Seq failed with rc=0x%lx\n", __func__, rc); return rc; } /* get the public key from a SPKI * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING * } * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } */ CK_RV ep11_spki_key(CK_BYTE *spki, CK_BYTE **key, CK_ULONG *bit_str_len) { CK_BYTE *out_seq, *id_seq, *bit_str; CK_BYTE *data; CK_ULONG data_len; CK_ULONG field_len; CK_ULONG key_len_bytes; CK_RV rc; CK_ULONG length_octets = 0; CK_ULONG len = 0; *bit_str_len = 0; out_seq = spki; rc = ber_decode_SEQUENCE(out_seq, &data, &data_len, &field_len); if (rc != CKR_OK) { TRACE_ERROR("%s ber_decode_SEQUENCE #1 failed rc=0x%lx\n", __func__, rc); return CKR_FUNCTION_FAILED; } id_seq = out_seq + field_len - data_len; /* get id seq length */ rc = ber_decode_SEQUENCE(id_seq, &data, &data_len, &field_len); if (rc != CKR_OK) { TRACE_ERROR("%s ber_decode_SEQUENCE #2 failed rc=0x%lx\n", __func__, rc); return CKR_FUNCTION_FAILED; } bit_str = id_seq + field_len; /* we should be at a bistring */ if (bit_str[0] != 0x03) { TRACE_ERROR("%s ber_decode no BITSTRING\n", __func__); return CKR_GENERAL_ERROR; } if ((bit_str[1] & 0x80) == 0) { key_len_bytes = 1; *bit_str_len = bit_str[1] & 0x7F; } else { key_len_bytes = 1 + (bit_str[1] & 0x7F); } *key = bit_str + key_len_bytes + 2; /* one 'unused bits' byte */ if (*bit_str_len == 0) { length_octets = bit_str[1] & 0x7F; if (length_octets == 1) { len = bit_str[2]; } if (length_octets == 2) { len = bit_str[2]; len = len << 8; len |= bit_str[3]; } if (length_octets == 3) { len = bit_str[2]; len = len << 8; len |= bit_str[3]; len = len << 8; len |= bit_str[4]; } *bit_str_len = len; } return CKR_OK; } CK_RV ep11_get_keytype(CK_ATTRIBUTE *attrs, CK_ULONG attrs_len, CK_MECHANISM_PTR mech, CK_ULONG *type, CK_ULONG *class) { int i; CK_RV rc = CKR_TEMPLATE_INCONSISTENT; *type = 0; *class = 0; for (i = 0; i < attrs_len; i++) { if (attrs[i].type == CKA_CLASS) *class = *(CK_ULONG *)attrs[i].pValue; } for (i = 0; i < attrs_len; i++) { if (attrs[i].type == CKA_KEY_TYPE) { *type = *(CK_ULONG *)attrs[i].pValue; return CKR_OK; } } /* no CKA_KEY_TYPE found, derive from mech */ switch (mech->mechanism) { case CKM_DES_KEY_GEN: *type = CKK_DES; break; case CKM_DES3_KEY_GEN: *type = CKK_DES3; break; case CKM_CDMF_KEY_GEN: *type = CKK_CDMF; break; case CKM_AES_KEY_GEN: *type = CKK_AES; break; case CKM_RSA_PKCS_KEY_PAIR_GEN: *type = CKK_RSA; break; case CKM_EC_KEY_PAIR_GEN: *type = CKK_EC; break; case CKM_DSA_KEY_PAIR_GEN: *type = CKK_DSA; break; case CKM_DH_PKCS_KEY_PAIR_GEN: *type = CKK_DH; break; default: return CKR_MECHANISM_INVALID; } rc = CKR_OK; return rc; } /* for logging, debugging */ static const char* ep11_get_ckm(CK_ULONG mechanism) { switch(mechanism) { case CKM_RSA_PKCS_KEY_PAIR_GEN: return "CKM_RSA_PKCS_KEY_PAIR_GEN"; case CKM_RSA_PKCS: return "CKM_RSA_PKCS"; case CKM_RSA_9796: return "CKM_RSA_9796"; case CKM_RSA_X_509: return "CKM_RSA_X_509"; case CKM_MD2_RSA_PKCS: return "CKM_MD2_RSA_PKCS"; case CKM_MD5_RSA_PKCS: return "CKM_MD5_RSA_PKCS"; case CKM_SHA1_RSA_PKCS: return "CKM_SHA1_RSA_PKCS"; case CKM_RIPEMD128_RSA_PKCS: return "CKM_RIPEMD128_RSA_PKCS"; case CKM_RIPEMD160_RSA_PKCS: return "CKM_RIPEMD160_RSA_PKCS"; case CKM_RSA_PKCS_OAEP: return "CKM_RSA_PKCS_OAEP"; case CKM_RSA_X9_31_KEY_PAIR_GEN: return "CKM_RSA_X9_31_KEY_PAIR_GEN"; case CKM_RSA_X9_31: return "CKM_RSA_X9_31"; case CKM_SHA1_RSA_X9_31: return "CKM_SHA1_RSA_X9_31"; case CKM_RSA_PKCS_PSS: return "CKM_RSA_PKCS_PSS"; case CKM_SHA1_RSA_PKCS_PSS: return "CKM_SHA1_RSA_PKCS_PSS"; case CKM_DSA_KEY_PAIR_GEN: return "CKM_DSA_KEY_PAIR_GEN"; case CKM_DSA: return "CKM_DSA"; case CKM_DSA_SHA1: return "CKM_DSA_SHA1"; case CKM_DH_PKCS_KEY_PAIR_GEN: return "CKM_DH_PKCS_KEY_PAIR_GEN"; case CKM_DH_PKCS_DERIVE: return "CKM_DH_PKCS_DERIVE"; case CKM_X9_42_DH_KEY_PAIR_GEN: return "CKM_X9_42_DH_KEY_PAIR_GEN"; case CKM_X9_42_DH_DERIVE: return "CKM_X9_42_DH_DERIVE"; case CKM_X9_42_DH_HYBRID_DERIVE: return "CKM_X9_42_DH_HYBRID_DERIVE"; case CKM_X9_42_MQV_DERIVE: return "CKM_X9_42_MQV_DERIVE"; case CKM_SHA256_RSA_PKCS: return "CKM_SHA256_RSA_PKCS"; case CKM_SHA384_RSA_PKCS: return "CKM_SHA384_RSA_PKCS"; case CKM_SHA512_RSA_PKCS: return "CKM_SHA512_RSA_PKCS"; case CKM_RC2_KEY_GEN: return "CKM_RC2_KEY_GEN"; case CKM_RC2_ECB: return "CKM_RC2_ECB"; case CKM_RC2_CBC: return "CKM_RC2_CBC"; case CKM_RC2_MAC: return "CKM_RC2_MAC"; case CKM_RC2_MAC_GENERAL: return "CKM_RC2_MAC_GENERAL"; case CKM_RC2_CBC_PAD: return "CKM_RC2_CBC_PAD"; case CKM_RC4_KEY_GEN: return "CKM_RC4_KEY_GEN"; case CKM_RC4: return "CKM_RC4"; case CKM_DES_KEY_GEN: return "CKM_DES_KEY_GEN"; case CKM_DES_ECB: return "CKM_DES_ECB"; case CKM_DES_CBC: return "CKM_DES_CBC"; case CKM_DES_MAC: return "CKM_DES_MAC"; case CKM_DES_MAC_GENERAL: return "CKM_DES_MAC_GENERAL"; case CKM_DES_CBC_PAD: return "CKM_DES_CBC_PAD"; case CKM_DES2_KEY_GEN: return "CKM_DES2_KEY_GEN"; case CKM_DES3_KEY_GEN: return "CKM_DES3_KEY_GEN"; case CKM_DES3_ECB: return "CKM_DES3_ECB"; case CKM_DES3_CBC: return "CKM_DES3_CBC"; case CKM_DES3_MAC: return "CKM_DES3_MAC"; case CKM_DES3_MAC_GENERAL: return "CKM_DES3_MAC_GENERAL"; case CKM_DES3_CBC_PAD: return "CKM_DES3_CBC_PAD"; case CKM_CDMF_KEY_GEN: return "CKM_CDMF_KEY_GEN"; case CKM_CDMF_ECB: return "CKM_CDMF_ECB"; case CKM_CDMF_CBC: return "CKM_CDMF_CBC"; case CKM_CDMF_MAC: return "CKM_CDMF_MAC"; case CKM_CDMF_MAC_GENERAL: return "CKM_CDMF_MAC_GENERAL"; case CKM_CDMF_CBC_PAD: return "CKM_CDMF_CBC_PAD"; case CKM_MD2: return "CKM_MD2"; case CKM_MD2_HMAC: return "CKM_MD2_HMAC"; case CKM_MD2_HMAC_GENERAL: return "CKM_MD2_HMAC_GENERAL"; case CKM_MD5: return "CKM_MD5"; case CKM_MD5_HMAC: return "CKM_MD5_HMAC"; case CKM_MD5_HMAC_GENERAL: return "CKM_MD5_HMAC_GENERAL"; case CKM_SHA_1: return "CKM_SHA_1"; case CKM_SHA_1_HMAC: return "CKM_SHA_1_HMAC"; case CKM_SHA_1_HMAC_GENERAL: return "CKM_SHA_1_HMAC_GENERAL"; case CKM_RIPEMD128: return "CKM_RIPEMD128"; case CKM_RIPEMD128_HMAC: return "CKM_RIPEMD128_HMAC"; case CKM_RIPEMD128_HMAC_GENERAL: return "CKM_RIPEMD128_HMAC_GENERAL"; case CKM_RIPEMD160: return "CKM_RIPEMD160"; case CKM_RIPEMD160_HMAC: return "CKM_RIPEMD160_HMAC"; case CKM_RIPEMD160_HMAC_GENERAL: return "CKM_RIPEMD160_HMAC_GENERAL"; case CKM_SHA256: return "CKM_SHA256"; case CKM_SHA256_HMAC: return "CKM_SHA256_HMAC"; case CKM_SHA256_HMAC_GENERAL: return "CKM_SHA256_HMAC_GENERAL"; case CKM_SHA384: return "CKM_SHA384"; case CKM_SHA384_HMAC: return "CKM_SHA384_HMAC"; case CKM_SHA384_HMAC_GENERAL: return "CKM_SHA384_HMAC_GENERAL"; case CKM_SHA512: return "CKM_SHA512"; case CKM_SHA512_HMAC: return "CKM_SHA512_HMAC"; case CKM_SHA512_HMAC_GENERAL: return "CKM_SHA512_HMAC_GENERAL"; case CKM_CAST_KEY_GEN: return "CKM_CAST_KEY_GEN"; case CKM_CAST_ECB: return "CKM_CAST_ECB"; case CKM_CAST_CBC: return "CKM_CAST_CBC"; case CKM_CAST_MAC: return "CKM_CAST_MAC"; case CKM_CAST_MAC_GENERAL: return "CKM_CAST_MAC_GENERAL"; case CKM_CAST_CBC_PAD: return "CKM_CAST_CBC_PAD"; case CKM_CAST3_KEY_GEN: return "CKM_CAST3_KEY_GEN"; case CKM_CAST3_ECB: return "CKM_CAST3_ECB"; case CKM_CAST3_CBC: return "CKM_CAST3_CBC"; case CKM_CAST3_MAC: return "CKM_CAST3_MAC"; case CKM_CAST3_MAC_GENERAL: return "CKM_CAST3_MAC_GENERAL"; case CKM_CAST3_CBC_PAD: return "CKM_CAST3_CBC_PAD"; case CKM_CAST5_KEY_GEN: return "CKM_CAST5_KEY_GEN"; case CKM_CAST5_ECB: return "CKM_CAST5_ECB"; case CKM_CAST5_CBC: return "CKM_CAST5_CBC"; case CKM_CAST5_MAC: return "CKM_CAST5_MAC"; case CKM_CAST5_MAC_GENERAL: return "CKM_CAST5_MAC_GENERAL"; case CKM_CAST5_CBC_PAD: return "CKM_CAST5_CBC_PAD"; case CKM_RC5_KEY_GEN: return "CKM_RC5_KEY_GEN"; case CKM_RC5_ECB: return "CKM_RC5_ECB"; case CKM_RC5_CBC: return "CKM_RC5_CBC"; case CKM_RC5_MAC: return "CKM_RC5_MAC"; case CKM_RC5_MAC_GENERAL: return "CKM_RC5_MAC_GENERAL"; case CKM_RC5_CBC_PAD: return "CKM_RC5_CBC_PAD"; case CKM_IDEA_KEY_GEN: return "CKM_IDEA_KEY_GEN"; case CKM_IDEA_ECB: return "CKM_IDEA_ECB"; case CKM_IDEA_CBC: return "CKM_IDEA_CBC"; case CKM_IDEA_MAC: return "CKM_IDEA_MAC"; case CKM_IDEA_MAC_GENERAL: return "CKM_IDEA_MAC_GENERAL"; case CKM_IDEA_CBC_PAD: return "CKM_IDEA_CBC_PAD"; case CKM_GENERIC_SECRET_KEY_GEN: return "CKM_GENERIC_SECRET_KEY_GEN"; case CKM_CONCATENATE_BASE_AND_KEY: return "CKM_CONCATENATE_BASE_AND_KEY"; case CKM_CONCATENATE_BASE_AND_DATA: return "CKM_CONCATENATE_BASE_AND_DATA"; case CKM_CONCATENATE_DATA_AND_BASE: return "CKM_CONCATENATE_DATA_AND_BASE"; case CKM_XOR_BASE_AND_DATA: return "CKM_XOR_BASE_AND_DATA"; case CKM_EXTRACT_KEY_FROM_KEY: return "CKM_EXTRACT_KEY_FROM_KEY"; case CKM_SSL3_PRE_MASTER_KEY_GEN: return "CKM_SSL3_PRE_MASTER_KEY_GEN"; case CKM_SSL3_MASTER_KEY_DERIVE: return "CKM_SSL3_MASTER_KEY_DERIVE"; case CKM_SSL3_KEY_AND_MAC_DERIVE: return "CKM_SSL3_KEY_AND_MAC_DERIVE"; case CKM_SSL3_MASTER_KEY_DERIVE_DH: return "CKM_SSL3_MASTER_KEY_DERIVE_DH"; case CKM_TLS_PRE_MASTER_KEY_GEN: return "CKM_TLS_PRE_MASTER_KEY_GEN"; case CKM_TLS_MASTER_KEY_DERIVE: return "CKM_TLS_MASTER_KEY_DERIVE"; case CKM_TLS_KEY_AND_MAC_DERIVE: return "CKM_TLS_KEY_AND_MAC_DERIVE"; case CKM_TLS_MASTER_KEY_DERIVE_DH: return "CKM_TLS_MASTER_KEY_DERIVE_DH"; case CKM_SSL3_MD5_MAC: return "CKM_SSL3_MD5_MAC"; case CKM_SSL3_SHA1_MAC: return "CKM_SSL3_SHA1_MAC"; case CKM_MD5_KEY_DERIVATION: return "CKM_MD5_KEY_DERIVATION"; case CKM_MD2_KEY_DERIVATION: return "CKM_MD2_KEY_DERIVATION"; case CKM_SHA1_KEY_DERIVATION: return "CKM_SHA1_KEY_DERIVATION"; case CKM_SHA256_KEY_DERIVATION: return "CKM_SHA256_KEY_DERIVATION"; case CKM_PBE_MD2_DES_CBC: return "CKM_PBE_MD2_DES_CBC"; case CKM_PBE_MD5_DES_CBC: return "CKM_PBE_MD5_DES_CBC"; case CKM_PBE_MD5_CAST_CBC: return "CKM_PBE_MD5_CAST_CBC"; case CKM_PBE_MD5_CAST3_CBC: return "CKM_PBE_MD5_CAST3_CBC"; case CKM_PBE_MD5_CAST5_CBC: return "CKM_PBE_MD5_CAST5_CBC"; case CKM_PBE_SHA1_CAST5_CBC: return "CKM_PBE_SHA1_CAST5_CBC"; case CKM_PBE_SHA1_RC4_128: return "CKM_PBE_SHA1_RC4_128"; case CKM_PBE_SHA1_RC4_40: return "CKM_PBE_SHA1_RC4_40"; case CKM_PBE_SHA1_DES3_EDE_CBC: return "CKM_PBE_SHA1_DES3_EDE_CBC"; case CKM_PBE_SHA1_DES2_EDE_CBC: return "CKM_PBE_SHA1_DES2_EDE_CBC"; case CKM_PBE_SHA1_RC2_128_CBC: return "CKM_PBE_SHA1_RC2_128_CBC"; case CKM_PBE_SHA1_RC2_40_CBC: return "CKM_PBE_SHA1_RC2_40_CBC"; case CKM_PKCS5_PBKD2: return "CKM_PKCS5_PBKD2"; case CKM_PBA_SHA1_WITH_SHA1_HMAC: return "CKM_PBA_SHA1_WITH_SHA1_HMAC"; case CKM_KEY_WRAP_LYNKS: return "CKM_KEY_WRAP_LYNKS"; case CKM_KEY_WRAP_SET_OAEP: return "CKM_KEY_WRAP_SET_OAEP"; case CKM_SKIPJACK_KEY_GEN: return "CKM_SKIPJACK_KEY_GEN"; case CKM_SKIPJACK_ECB64: return "CKM_SKIPJACK_ECB64"; case CKM_SKIPJACK_CBC64: return "CKM_SKIPJACK_CBC64"; case CKM_SKIPJACK_OFB64: return "CKM_SKIPJACK_OFB64"; case CKM_SKIPJACK_CFB64: return "CKM_SKIPJACK_CFB64"; case CKM_SKIPJACK_CFB32: return "CKM_SKIPJACK_CFB32"; case CKM_SKIPJACK_CFB16: return "CKM_SKIPJACK_CFB16"; case CKM_SKIPJACK_CFB8: return "CKM_SKIPJACK_CFB8"; case CKM_SKIPJACK_WRAP: return "CKM_SKIPJACK_WRAP"; case CKM_SKIPJACK_PRIVATE_WRAP: return "CKM_SKIPJACK_PRIVATE_WRAP"; case CKM_SKIPJACK_RELAYX: return "CKM_SKIPJACK_RELAYX"; case CKM_KEA_KEY_PAIR_GEN: return "CKM_KEA_KEY_PAIR_GEN"; case CKM_KEA_KEY_DERIVE: return "CKM_KEA_KEY_DERIVE"; case CKM_FORTEZZA_TIMESTAMP: return "CKM_FORTEZZA_TIMESTAMP"; case CKM_BATON_KEY_GEN: return "CKM_BATON_KEY_GEN"; case CKM_BATON_ECB128: return "CKM_BATON_ECB128"; case CKM_BATON_ECB96: return "CKM_BATON_ECB96"; case CKM_BATON_CBC128: return "CKM_BATON_CBC128"; case CKM_BATON_COUNTER: return "CKM_BATON_COUNTER"; case CKM_BATON_SHUFFLE: return "CKM_BATON_SHUFFLE"; case CKM_BATON_WRAP: return "CKM_BATON_WRAP"; case CKM_EC_KEY_PAIR_GEN: return "CKM_EC_KEY_PAIR_GEN"; case CKM_ECDSA: return "CKM_ECDSA"; case CKM_ECDSA_SHA1: return "CKM_ECDSA_SHA1"; case CKM_ECDH1_DERIVE: return "CKM_ECDH1_DERIVE"; case CKM_ECDH1_COFACTOR_DERIVE: return "CKM_ECDH1_COFACTOR_DERIVE"; case CKM_ECMQV_DERIVE: return "CKM_ECMQV_DERIVE"; case CKM_JUNIPER_KEY_GEN: return "CKM_JUNIPER_KEY_GEN"; case CKM_JUNIPER_ECB128: return "CKM_JUNIPER_ECB128"; case CKM_JUNIPER_CBC128: return "CKM_JUNIPER_CBC128"; case CKM_JUNIPER_COUNTER: return "CKM_JUNIPER_COUNTER"; case CKM_JUNIPER_SHUFFLE: return "CKM_JUNIPER_SHUFFLE"; case CKM_JUNIPER_WRAP: return "CKM_JUNIPER_WRAP"; case CKM_FASTHASH: return "CKM_FASTHASH"; case CKM_AES_KEY_GEN: return "CKM_AES_KEY_GEN"; case CKM_AES_ECB: return "CKM_AES_ECB"; case CKM_AES_CBC: return "CKM_AES_CBC"; case CKM_AES_MAC: return "CKM_AES_MAC"; case CKM_AES_MAC_GENERAL: return "CKM_AES_MAC_GENERAL"; case CKM_AES_CBC_PAD: return "CKM_AES_CBC_PAD"; case CKM_AES_CTR: return "CKM_AES_CTR"; case CKM_DSA_PARAMETER_GEN: return "CKM_DSA_PARAMETER_GEN"; case CKM_DH_PKCS_PARAMETER_GEN: return "CKM_DH_PKCS_PARAMETER_GEN"; case CKM_X9_42_DH_PARAMETER_GEN: return "CKM_X9_42_DH_PARAMETER_GEN"; case CKM_VENDOR_DEFINED: return "CKM_VENDOR_DEFINED"; case CKM_SHA256_RSA_PKCS_PSS : return "CKM_SHA256_RSA_PKCS_PSS"; case CKM_SHA224_RSA_PKCS: return "CKM_SHA224_RSA_PKCS"; case CKM_SHA224_RSA_PKCS_PSS: return "CKM_SHA224_RSA_PKCS_PSS"; case CKM_SHA384_RSA_PKCS_PSS: return "CKM_SHA384_RSA_PKCS_PSS"; case CKM_SHA512_RSA_PKCS_PSS: return "CKM_SHA512_RSA_PKCS_PSS"; case CKM_SHA224: return "CKM_SHA224"; case CKM_SHA224_KEY_DERIVATION: return "CKM_SHA224_KEY_DERIVATION"; case CKM_SHA224_HMAC: return "CKM_SHA224_HMAC"; case CKM_SHA384_KEY_DERIVATION: return "CKM_SHA384_KEY_DERIVATION"; case CKM_SHA512_KEY_DERIVATION: return "CKM_SHA512_KEY_DERIVATION"; case CKM_VENDOR_DEFINED + 0x10007: return "CKA_IBM_MACKEY"; case CKM_VENDOR_DEFINED + 0x10008: return "CKM_IBM_ECDSA_SHA224"; case CKM_VENDOR_DEFINED + 0x10009: return "CKM_IBM_ECDSA_SHA256"; case CKM_VENDOR_DEFINED + 0x1000a: return "CKM_IBM_ECDSA_SHA384"; case CKM_VENDOR_DEFINED + 0x1000b: return "CKM_IBM_ECDSA_SHA512"; case CKR_VENDOR_DEFINED + 0x1000c: return "CKM_IBM_EC_MULTIPLY"; case CKM_VENDOR_DEFINED + 0x1000d: return "CKM_IBM_EAC"; case CKM_VENDOR_DEFINED + 0x10012: return "CKM_IBM_SHA512_256"; case CKM_VENDOR_DEFINED + 0x10013: return "CKM_IBM_SHA512_224"; case CKM_VENDOR_DEFINED + 0x10014: return "CKM_IBM_SHA512_256_HMAC"; case CKM_VENDOR_DEFINED + 0x10015: return "CKM_IBM_SHA512_224_HMAC"; case CKM_VENDOR_DEFINED + 0x10016: return "CKM_IBM_SHA512_256_KEY_DERIVATION"; case CKM_VENDOR_DEFINED + 0x10017: return "CKM_IBM_SHA512_224_KEY_DERIVATION"; case CKM_VENDOR_DEFINED + 0x20004: return "CKM_IBM_ATTRIBUTEBOUND_WRAP"; case CKM_VENDOR_DEFINED + 0x20005: return "CKM_IBM_TRANSPORTKEY"; case CKM_VENDOR_DEFINED + 0x20006: return "CKM_IBM_DH_PKCS_DERIVE_RAW"; case CKM_VENDOR_DEFINED + 0x20007: return "CKM_IBM_ECDH1_DERIVE_RAW"; case CKM_VENDOR_DEFINED + 0x40001: return "CKM_IBM_RETAINKEY"; default: TRACE_WARNING("%s unknown mechanism %lx\n", __func__, mechanism); return "UNKNOWN"; } } static CK_RV h_opaque_2_blob(CK_OBJECT_HANDLE handle, CK_BYTE **blob, size_t *blob_len, OBJECT **kobj); #define EP11_DEFAULT_CFG_FILE "ep11tok.conf" #define EP11_CFG_FILE_SIZE 4096 /* error rc for reading the adapter config file */ static const int APQN_FILE_INV_0 = 1; static const int APQN_FILE_INV_1 = 2; static const int APQN_FILE_INV_2 = 3; static const int APQN_FILE_INV_3 = 4; static const int APQN_FILE_INV_FILE_SIZE = 5; static const int APQN_FILE_FILE_ACCESS = 6; static const int APQN_FILE_SYNTAX_ERROR_0 = 7; static const int APQN_FILE_SYNTAX_ERROR_1 = 8; static const int APQN_FILE_SYNTAX_ERROR_2 = 9; static const int APQN_FILE_SYNTAX_ERROR_3 = 10; static const int APQN_FILE_SYNTAX_ERROR_4 = 11; static const int APQN_FILE_SYNTAX_ERROR_5 = 12; static const int APQN_FILE_NO_APQN_GIVEN = 13; static const int APQN_FILE_NO_APQN_MODE = 14; static int read_adapter_config_file(const char* conf_name); /* import a DES/AES key, that is, make a blob for a DES/AES key * that was not created by EP11 hardware, encrypt the key by the wrap key, * unwrap it by the wrap key */ static CK_RV rawkey_2_blob(unsigned char *key, CK_ULONG ksize, CK_KEY_TYPE ktype, unsigned char *blob, size_t *blen, OBJECT *key_obj) { char cipher[MAX_BLOBSIZE]; CK_ULONG clen = sizeof(cipher); CK_BYTE csum[MAX_CSUMSIZE]; size_t cslen = sizeof(csum); CK_BYTE iv[AES_BLOCK_SIZE]; CK_MECHANISM mech = { CKM_AES_CBC_PAD, iv, AES_BLOCK_SIZE }; DL_NODE *node = key_obj->template->attribute_list; CK_RV rc; CK_ATTRIBUTE_PTR p_attrs = NULL; CK_ULONG attrs_len = 0; CK_ATTRIBUTE_PTR new_p_attrs = NULL; CK_ULONG new_attrs_len = 0; /* tell ep11 the attributes the user specified */ node = key_obj->template->attribute_list; while (node != NULL) { CK_ATTRIBUTE_PTR a = node->data; /* ep11 handles this as 'read only' and reports * an error if specified */ if (CKA_NEVER_EXTRACTABLE == a->type || CKA_MODIFIABLE == a->type || CKA_LOCAL == a->type) ; else { rc = add_to_attribute_array(&p_attrs, &attrs_len, a->type, a->pValue, a->ulValueLen); if (rc != CKR_OK) { TRACE_ERROR("%s adding attribute failed type=0x%lx rc=0x%lx\n", __func__, a->type, rc); goto rawkey_2_blob_end; } } node = node->next; } memset(cipher, 0, sizeof(cipher)); memcpy(iv, "1234567812345678", AES_BLOCK_SIZE); /* * calls the ep11 lib (which in turns sends the request to the card), * all m_ function are ep11 functions */ rc = m_EncryptSingle(raw2key_wrap_blob, raw2key_wrap_blob_l, &mech, key, ksize, cipher, &clen, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s encrypt ksize=0x%lx clen=0x%lx rc=0x%lx\n", __func__, ksize, clen, rc); goto rawkey_2_blob_end; } TRACE_INFO("%s encrypt ksize=0x%lx clen=0x%lx rc=0x%lx\n", __func__, ksize, clen, rc); rc = check_key_attributes(ktype, CKO_SECRET_KEY, p_attrs, attrs_len, &new_p_attrs, &new_attrs_len); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check private key attributes failed with rc=0x%lx\n", __func__, rc); return rc; } /* the encrypted key is decrypted and a blob is build, * card accepts only blobs as keys */ rc = m_UnwrapKey(cipher, clen, raw2key_wrap_blob, raw2key_wrap_blob_l, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, &mech, new_p_attrs, new_attrs_len, blob, blen, csum, &cslen, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s unwrap blen=%zd rc=0x%lx\n", __func__, *blen, rc); } else { TRACE_INFO("%s unwrap blen=%zd rc=0x%lx\n", __func__, *blen, rc); } rawkey_2_blob_end: if (p_attrs != NULL) free_attribute_array(p_attrs, attrs_len); if (new_p_attrs) free_attribute_array(new_p_attrs, new_attrs_len); return rc; } static const char* print_flags(CK_ULONG flags) { switch(flags) { case CKF_ENCRYPT: return "ENCRYPT"; case CKF_DECRYPT: return "DECRYPT"; case CKF_DIGEST : return "DIGEST"; case CKF_SIGN : return "SIGN"; case CKF_SIGN_RECOVER : return "SIGN_RECOVER"; case CKF_VERIFY : return "VERIFY"; case CKF_VERIFY_RECOVER : return "VERIFY_RECOVER"; case CKF_GENERATE : return "GENERATE"; case CKF_GENERATE_KEY_PAIR : return "GENERATE_KEY_PAIR"; case CKF_WRAP : return "WRAP"; case CKF_UNWRAP : return "UNWRAP"; case CKF_DERIVE : return "DERIVE"; /* The following are new for v2.11 */ case CKF_EC_F_P : return "CKF_EC_F_P"; case CKF_EC_F_2M : return "CKF_EC_F_2M"; case CKF_EC_ECPARAMETERS : return "EC_ECPARAMETERS"; case CKF_EC_NAMEDCURVE : return "EC_NAMEDCURVE"; case CKF_EC_UNCOMPRESS : return "EC_UNCOMPRESS"; case CKF_EC_COMPRESS : return "EC_COMPRESS"; default : return "UNKNOWN"; } } static CK_RV print_mechanism(void) { CK_MECHANISM_TYPE_PTR list = NULL; CK_ULONG count = 0; int i; CK_MECHANISM_INFO m_info; CK_RV rc; /* first call is just to fetch the count value */ rc = ep11tok_get_mechanism_list(list, &count); if (rc != CKR_OK) { TRACE_ERROR("%s can't fetch mechanism list (get_mech_list rc=0x%lx)\n", __func__, rc); return rc; } list = (CK_MECHANISM_TYPE_PTR)malloc(sizeof(CK_MECHANISM_TYPE) * count); if (!list) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } /* now really fill the list */ rc = ep11tok_get_mechanism_list(list, &count); if (rc != CKR_OK) { TRACE_ERROR("%s can't fetch mechanism list (get_mech_list rc=0x%lx)\n", __func__, rc); free(list); return rc; } TRACE_INFO("%s EP11 token mechanism list, %lu entries:\n", __func__, count); for (i = 0; i < count; i++) { char strflags[1024]; strflags[0] = 0; memset(&m_info, 0, sizeof(m_info)); ep11tok_get_mechanism_info(list[i], &m_info); if (m_info.flags) { CK_ULONG flag; for (flag = 1; flag < 0x80000000; flag = flag * 2) { if ((flag & m_info.flags) != 0) { strcat(strflags, ","); strcat(strflags, print_flags(flag & m_info.flags)); } } } TRACE_INFO(" %s {%lu,%lu%s}\n", ep11_get_ckm(list[i]), m_info.ulMinKeySize, m_info.ulMaxKeySize, strflags); } free(list); return CKR_OK; } /* random number generator */ CK_RV token_specific_rng(CK_BYTE *output, CK_ULONG bytes) { CK_RV rc = m_GenerateRandom(output, bytes, ep11tok_target); if (rc != CKR_OK) TRACE_ERROR("%s output=%p bytes=%lu rc=0x%lx\n", __func__, output, bytes, rc); return rc; } /* * for importing keys we need to encrypt the keys and build the blob by * m_UnwrapKey, use one wrap key for this purpose, can be any key, * we use an AES key */ static CK_RV make_wrapblob(CK_ATTRIBUTE *tmpl_in, CK_ULONG tmpl_len) { CK_MECHANISM mech = {CKM_AES_KEY_GEN, NULL_PTR, 0}; unsigned char csum[MAX_CSUMSIZE]; size_t csum_l = sizeof(csum); CK_RV rc; if (raw2key_wrap_blob_l != 0) { TRACE_INFO("%s blob already exists raw2key_wrap_blob_l=0x%zx\n", __func__, raw2key_wrap_blob_l); return CKR_OK; } raw2key_wrap_blob_l = sizeof(raw2key_wrap_blob); rc = m_GenerateKey(&mech, tmpl_in, tmpl_len, NULL, 0, raw2key_wrap_blob, &raw2key_wrap_blob_l, csum, &csum_l, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s end raw2key_wrap_blob_l=0x%zx rc=0x%lx\n", __func__, raw2key_wrap_blob_l, rc); } else { TRACE_INFO("%s end raw2key_wrap_blob_l=0x%zx rc=0x%lx\n", __func__, raw2key_wrap_blob_l, rc); } return rc; } CK_RV ep11tok_init(CK_SLOT_ID SlotNumber, char *conf_name) { CK_RV rc; void *lib_ep11; CK_ULONG len = 16; CK_BBOOL cktrue = 1; CK_ATTRIBUTE wrap_tmpl[] = {{CKA_VALUE_LEN, &len, sizeof(CK_ULONG)}, {CKA_WRAP, (void*)&cktrue, sizeof(cktrue)}, {CKA_UNWRAP, (void*)&cktrue, sizeof(cktrue)}, {CKA_ENCRYPT, (void*)&cktrue, sizeof(cktrue)}, {CKA_DECRYPT, (void*)&cktrue, sizeof(cktrue)}, {CKA_EXTRACTABLE, (void*)&cktrue, sizeof(cktrue)}, {CKA_LABEL, (void*)wrap_key_name, sizeof(wrap_key_name)}, {CKA_TOKEN, (void*)&cktrue, sizeof(cktrue)}}; TRACE_INFO("%s init running\n", __func__); /* read ep11 specific config file with user specified adapter/domain pairs, ... */ rc = read_adapter_config_file(conf_name); if (rc != CKR_OK) { TRACE_ERROR("%s ep11 config file error rc=0x%lx\n", __func__, rc); return CKR_GENERAL_ERROR; } /* dynamically load in the ep11 shared library */ lib_ep11 = dlopen(EP11SHAREDLIB, RTLD_GLOBAL | RTLD_NOW); if (!lib_ep11) { OCK_SYSLOG(LOG_ERR, "%s: Error loading shared library '%s' [%s]\n", __func__, EP11SHAREDLIB, dlerror()); TRACE_ERROR("%s Error loading shared library '%s' [%s]\n", __func__, EP11SHAREDLIB, dlerror()); return CKR_FUNCTION_FAILED; } #ifndef XCP_STANDALONE /* call ep11 shared lib init */ if (m_init() < 0) { TRACE_ERROR("%s ep11 lib init failed\n", __func__); return CKR_DEVICE_ERROR; } #endif /* print mechanismlist to log file */ rc = print_mechanism(); if (rc != CKR_OK) { TRACE_ERROR("%s failure on fetching mechanism list rc=0x%lx, maybe wrong config ?\n", __func__, rc); return CKR_GENERAL_ERROR; } /* create an AES key needed for importing keys * (encrypt by wrap_key and m_UnwrapKey by wrap key) */ rc = make_wrapblob(wrap_tmpl, 8); if (rc != CKR_OK) { TRACE_ERROR("%s make_wrapblob failed rc=0x%lx\n", __func__, rc); if (rc == 0x80010009) { TRACE_ERROR("%s rc is CKR_IBM_WK_NOT_INITIALIZED, " "no master key set ?\n", __func__); OCK_SYSLOG(LOG_ERR, "%s: CKR_IBM_WK_NOT_INITIALIZED occured, no " "master key set ?\n", __func__); } return CKR_GENERAL_ERROR; } TRACE_INFO("%s init done successfully\n", __func__); return CKR_OK; } CK_RV ep11tok_final() { TRACE_INFO("%s final running\n", __func__); return CKR_OK; } /* * makes blobs for private imported RSA keys and * SPKIs for public imported RSA keys. * Similar to rawkey_2_blob, but keys must follow a standard BER encoding. */ static CK_RV import_RSA_key(OBJECT *rsa_key_obj, CK_BYTE *blob, size_t *blob_size) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_BYTE iv[AES_BLOCK_SIZE]; CK_MECHANISM mech_w = {CKM_AES_CBC_PAD, iv, AES_BLOCK_SIZE}; CK_BYTE cipher[MAX_BLOBSIZE]; CK_ULONG cipher_l = sizeof(cipher); DL_NODE *node; CK_ATTRIBUTE_PTR p_attrs = NULL; CK_ULONG attrs_len = 0; CK_ATTRIBUTE_PTR new_p_attrs = NULL; CK_ULONG new_attrs_len = 0; char csum[MAX_BLOBSIZE]; CK_ULONG cslen = sizeof(csum); CK_OBJECT_CLASS class; CK_BYTE *data = NULL; CK_ULONG data_len; memcpy(iv, "1234567812345678", AES_BLOCK_SIZE); /* need class for private/public key info */ if (!template_attribute_find(rsa_key_obj->template, CKA_CLASS, &attr)) { TRACE_ERROR("%s no CKA_CLASS\n", __func__); return CKR_TEMPLATE_INCOMPLETE; } /* m_Unwrap builds key blob in the card, * tell ep11 the attributes the user specified for that key. */ node = rsa_key_obj->template->attribute_list; while (node != NULL) { CK_ATTRIBUTE_PTR a = node->data; /* ep11 handles this as 'read only' */ if (CKA_NEVER_EXTRACTABLE == a->type || CKA_MODIFIABLE == a->type || CKA_LOCAL == a->type) ; else { rc = add_to_attribute_array(&p_attrs, &attrs_len, a->type, a->pValue, a->ulValueLen); if (rc != CKR_OK) { TRACE_ERROR("%s adding attribute failed type=0x%lx rc=0x%lx\n", __func__, a->type, rc); goto import_RSA_key_end; } } node = node->next; } class = *(CK_OBJECT_CLASS *)attr->pValue; if (class != CKO_PRIVATE_KEY) { /* an imported public RSA key, we need a SPKI for it. */ CK_ATTRIBUTE *modulus; CK_ATTRIBUTE *publ_exp; if (!template_attribute_find(rsa_key_obj->template, CKA_MODULUS, &modulus)) { rc = CKR_TEMPLATE_INCOMPLETE; goto import_RSA_key_end; } if (!template_attribute_find(rsa_key_obj->template, CKA_PUBLIC_EXPONENT, &publ_exp)) { rc = CKR_TEMPLATE_INCOMPLETE; goto import_RSA_key_end; } /* our contribution to asn1.c, * builds the BER encoding that is a SPKI. */ rc = ber_encode_RSAPublicKey(0, &data, &data_len, modulus, publ_exp); if (rc != CKR_OK) { TRACE_ERROR("%s public key import class=0x%lx rc=0x%lx " "data_len=0x%lx\n", __func__, class, rc, data_len); goto import_RSA_key_end; } else { TRACE_INFO("%s public key import class=0x%lx rc=0x%lx " "data_len=0x%lx\n", __func__, class, rc, data_len); } /* save the SPKI as blob although it is not a blob. * The card expects SPKIs as public keys. */ memcpy(blob, data, data_len); *blob_size = data_len; } else { /* imported private RSA key goes here */ /* extract the secret data to be wrapped * since this is AES_CBC_PAD, padding is done in mechanism. */ rc = rsa_priv_wrap_get_data(rsa_key_obj->template, FALSE, &data, &data_len); if (rc != CKR_OK) { TRACE_DEVEL("%s RSA wrap get data failed\n", __func__); goto import_RSA_key_end; } /* encrypt */ rc = m_EncryptSingle(raw2key_wrap_blob, raw2key_wrap_blob_l, &mech_w, data, data_len, cipher, &cipher_l, ep11tok_target); TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n", __func__, rc, cipher_l); if (rc != CKR_OK) { TRACE_ERROR("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n", __func__, rc, cipher_l); goto import_RSA_key_end; } rc = check_key_attributes(CKK_RSA, CKO_PRIVATE_KEY, p_attrs, attrs_len, &new_p_attrs, &new_attrs_len); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check private key attributes failed with rc=0x%lx\n", __func__, rc); return rc; } /* calls the card, it decrypts the private RSA key, * reads its BER format and builds a blob. */ rc = m_UnwrapKey(cipher, cipher_l, raw2key_wrap_blob, raw2key_wrap_blob_l, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, &mech_w, new_p_attrs, new_attrs_len, blob, blob_size, csum, &cslen, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s wrapping unwrap key rc=0x%lx blob_size=0x%zx\n", __func__, rc, *blob_size); } else { TRACE_INFO("%s wrapping unwrap key rc=0x%lx blob_size=0x%zx\n", __func__, rc, *blob_size); } } import_RSA_key_end: if (data) free(data); if (p_attrs != NULL) free_attribute_array(p_attrs, attrs_len); if (new_p_attrs) free_attribute_array(new_p_attrs, new_attrs_len); return rc; } CK_RV token_specific_object_add(OBJECT *obj) { CK_KEY_TYPE keytype; CK_ATTRIBUTE *attr = NULL; CK_BYTE blob[MAX_BLOBSIZE]; size_t blobsize = sizeof(blob); CK_RV rc; /* get key type */ if (template_attribute_find(obj->template, CKA_KEY_TYPE, &attr) == FALSE) { /* not a key, so nothing to do. Just return. */ return CKR_OK; } keytype = *(CK_KEY_TYPE *)attr->pValue; memset(blob, 0, sizeof(blob)); /* only these keys can be imported */ switch(keytype) { case CKK_RSA: rc = import_RSA_key(obj, blob, &blobsize); if (rc != CKR_OK) { TRACE_ERROR("%s import RSA key rc=0x%lx blobsize=0x%zx\n", __func__, rc, blobsize); return CKR_FUNCTION_FAILED; } TRACE_INFO("%s import RSA key rc=0x%lx blobsize=0x%zx\n", __func__, rc, blobsize); break; case CKK_DES2: case CKK_DES3: case CKK_AES: case CKK_GENERIC_SECRET: /* get key value */ if (template_attribute_find(obj->template, CKA_VALUE, &attr) == FALSE) { TRACE_ERROR("%s token_specific_object_add incomplete template\n", __func__); return CKR_TEMPLATE_INCOMPLETE; } /* attr holds key value specified by user, * import that key (make a blob) */ rc = rawkey_2_blob(attr->pValue, attr->ulValueLen, keytype, blob, &blobsize, obj); if (rc != CKR_OK) { TRACE_ERROR("%s rawkey_2_blob rc=0x%lx " "blobsize=0x%zx\n", __func__, rc, blobsize); return CKR_FUNCTION_FAILED; } /* clear value attribute */ memset(attr->pValue, 0, attr->ulValueLen); TRACE_INFO("%s rawkey_2_blob rc=0x%lx blobsize=0x%zx\n", __func__, rc, blobsize); break; default: return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* store the blob in the key obj */ rc = build_attribute(CKA_IBM_OPAQUE, blob, blobsize, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); return rc; } rc = template_update_attribute(obj->template, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); return rc; } return CKR_OK; } CK_RV ep11tok_generate_key(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle) { CK_BYTE blob[MAX_BLOBSIZE]; size_t blobsize = sizeof(blob); CK_BYTE csum[MAX_CSUMSIZE]; size_t csum_len = sizeof(csum); CK_ATTRIBUTE *attr = NULL; OBJECT *key_obj = NULL; CK_ULONG ktype; CK_ULONG class; CK_ATTRIBUTE_PTR new_attrs = NULL; CK_ULONG new_attrs_len = 0; CK_RV rc; memset(blob, 0, sizeof(blob)); memset(csum, 0, sizeof(csum)); /* Get the keytype to use when creating the key object */ rc = ep11_get_keytype(attrs, attrs_len, mech, &ktype, &class); if (rc != CKR_OK) { TRACE_ERROR("%s get_subclass failed with rc=0x%lx\n", __func__, rc); goto error; } rc = check_key_attributes(ktype, CKO_SECRET_KEY, attrs, attrs_len, &new_attrs, &new_attrs_len); if (rc != CKR_OK) { TRACE_ERROR("%s check secret key attributes failed: rc=0x%lx\n", __func__, rc); return rc; } rc = m_GenerateKey(mech, new_attrs, new_attrs_len, ep11_pin_blob, ep11_pin_blob_len, blob, &blobsize, csum, &csum_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s m_GenerateKey rc=0x%lx mech='%s' attrs_len=0x%lx\n", __func__, rc, ep11_get_ckm(mech->mechanism), attrs_len); return rc; } TRACE_INFO("%s m_GenerateKey rc=0x%lx mech='%s' attrs_len=0x%lx\n", __func__, rc, ep11_get_ckm(mech->mechanism), attrs_len); /* Start creating the key object */ rc = object_mgr_create_skel(session, new_attrs, new_attrs_len, MODE_KEYGEN, CKO_SECRET_KEY, ktype, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s object_mgr_create_skel failed with rc=0x%lx\n", __func__, rc); goto error; } rc = build_attribute(CKA_IBM_OPAQUE, blob, blobsize, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(key_obj->template, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } /* key should be fully constructed. * Assign an object handle and store key */ rc = object_mgr_create_final(session, key_obj, handle); if (rc != CKR_OK) { TRACE_ERROR("%s object_mgr_create_final with rc=0x%lx\n", __func__, rc); goto error; } goto done; error: if (key_obj) object_free(key_obj); *handle = 0; done: if (new_attrs) free_attribute_array(new_attrs, new_attrs_len); return rc; } CK_RV token_specific_sha_init(DIGEST_CONTEXT *c, CK_MECHANISM *mech) { CK_RV rc; size_t state_len = MAX_DIGEST_STATE_BYTES; CK_BYTE *state; state = malloc(state_len); /* freed by dig_mgr.c */ if (!state) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } rc = m_DigestInit (state, &state_len, mech, ep11tok_target) ; if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); free(state); } else { /* DIGEST_CONTEXT will show up with following * requests (sha_update), 'state' is build by the card * and holds all to continue, even by another adapter */ c->mech.ulParameterLen = mech->ulParameterLen; c->mech.mechanism = mech->mechanism; c->mech.pParameter = NULL; c->context = state; c->context_len = state_len; TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV token_specific_sha(DIGEST_CONTEXT *c, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len) { CK_RV rc; rc = m_Digest(c->context, c->context_len, in_data, in_data_len, out_data, out_data_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV token_specific_sha_update(DIGEST_CONTEXT *c, CK_BYTE *in_data, CK_ULONG in_data_len) { CK_RV rc; rc = m_DigestUpdate(c->context, c->context_len, in_data, in_data_len, ep11tok_target) ; if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV token_specific_sha_final(DIGEST_CONTEXT *c, CK_BYTE *out_data, CK_ULONG *out_data_len) { CK_RV rc; rc = m_DigestFinal(c->context, c->context_len, out_data, out_data_len, ep11tok_target) ; if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_derive_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE hBaseKey, CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len) { CK_RV rc; CK_BYTE *keyblob; size_t keyblobsize; CK_BYTE newblob[MAX_BLOBSIZE]; size_t newblobsize = sizeof(newblob); char csum[MAX_BLOBSIZE]; CK_ULONG cslen = sizeof(csum); CK_ATTRIBUTE *opaque_attr = NULL; OBJECT *key_obj = NULL; CK_ULONG ktype; CK_ULONG class; CK_ATTRIBUTE_PTR new_attrs = NULL; CK_ULONG new_attrs_len = 0; memset(newblob, 0, sizeof(newblob)); rc = h_opaque_2_blob(hBaseKey, &keyblob, &keyblobsize, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s failedL hBaseKey=0x%lx\n", __func__, hBaseKey); return rc; } /* Get the keytype to use when creating the key object */ rc = ep11_get_keytype(attrs, attrs_len, mech, &ktype, &class); if (rc != CKR_OK) { TRACE_ERROR("%s get_subclass failed with rc=0x%lx\n", __func__, rc); goto error; } rc = check_key_attributes(ktype, class, attrs, attrs_len, &new_attrs, &new_attrs_len); if (rc != CKR_OK) { TRACE_ERROR("%s Check key attributes for derived key failed with rc=0x%lx\n", __func__, rc); return rc; } rc = m_DeriveKey (mech, new_attrs, new_attrs_len, keyblob, keyblobsize, NULL, 0, ep11_pin_blob, ep11_pin_blob_len, newblob, &newblobsize, csum, &cslen, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s hBaseKey=0x%lx rc=0x%lx handle=0x%lx blobsize=0x%zx\n", __func__, hBaseKey, rc, *handle, newblobsize); return rc; } TRACE_INFO("%s hBaseKey=0x%lx rc=0x%lx handle=0x%lx blobsize=0x%zx\n", __func__, hBaseKey, rc, *handle, newblobsize); /* Start creating the key object */ rc = object_mgr_create_skel(session, new_attrs, new_attrs_len, MODE_DERIVE, class, ktype, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s object_mgr_create_skel failed with rc=0x%lx\n", __func__, rc); goto error; } rc = build_attribute(CKA_IBM_OPAQUE, newblob, newblobsize, &opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(key_obj->template, opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } /* key should be fully constructed. * Assign an object handle and store key */ rc = object_mgr_create_final(session, key_obj, handle); if (rc != CKR_OK) { TRACE_ERROR("%s object_mgr_create_final with rc=0x%lx\n", __func__, rc); goto error; } return rc; error: if (key_obj) object_free(key_obj); *handle = 0; if (new_attrs) free_attribute_array(new_attrs, new_attrs_len); return rc; } #define CKA_IBM_STRUCT_PARAMS (CKA_VENDOR_DEFINED +0x10009) static CK_RV dh_generate_keypair(CK_MECHANISM_PTR pMechanism, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_SESSION_HANDLE h) { CK_RV rc; CK_BYTE publblob[MAX_BLOBSIZE]; size_t publblobsize = sizeof(publblob); CK_BYTE privblob[MAX_BLOBSIZE]; size_t privblobsize = sizeof(privblob); CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *opaque_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *attr = NULL; CK_ATTRIBUTE *pPublicKeyTemplate_new = NULL; size_t p_len=0, g_len=0; int i, new_public_attr; CK_ULONG data_len; CK_ULONG field_len; CK_BYTE *data; CK_BYTE *y_start; CK_ULONG bit_str_len; /* ep11 accepts CKA_PRIME and CKA_BASE parameters/attributes * only in this format */ struct { size_t pg_bytes; /* total size: 2*bytecount(P) */ unsigned char *pg; } dh_pgs; memset(&dh_pgs, 0, sizeof(dh_pgs)); memset(publblob, 0, sizeof(publblob)); memset(privblob, 0, sizeof(privblob)); /* card does not want CKA_PRIME/CKA_BASE in template but in dh_pgs */ pPublicKeyTemplate_new = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) * ulPublicKeyAttributeCount); if (!pPublicKeyTemplate_new) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } memset(pPublicKeyTemplate_new, 0, sizeof(CK_ATTRIBUTE) * ulPublicKeyAttributeCount); for (i = 0, new_public_attr = 0; i < ulPublicKeyAttributeCount; i++) { /* filter out CKA_PRIME/CKA_BASE, * but remember where they can be found */ switch(pPublicKeyTemplate[i].type) { case CKA_PRIME: prime_attr = &(pPublicKeyTemplate[i]); p_len = pPublicKeyTemplate[i].ulValueLen; break; case CKA_BASE: base_attr = &(pPublicKeyTemplate[i]); g_len = pPublicKeyTemplate[i].ulValueLen; break; default: /* copy all other attributes */ memcpy(&pPublicKeyTemplate_new[new_public_attr], &(pPublicKeyTemplate[i]), sizeof(CK_ATTRIBUTE)); new_public_attr++; } } if (prime_attr == NULL || base_attr == NULL) { TRACE_ERROR("%s Incomplete template prime_attr=%p base_attr=%p\n", __func__, prime_attr, base_attr); rc = CKR_TEMPLATE_INCOMPLETE; goto dh_generate_keypair_end; } /* copy CKA_PRIME/CKA_BASE to private template */ rc = build_attribute(CKA_PRIME, prime_attr->pValue, prime_attr->ulValueLen, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } rc = template_update_attribute(priv_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } rc = build_attribute(CKA_BASE, base_attr->pValue, base_attr->ulValueLen, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } rc = template_update_attribute(priv_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } /* copy CKA_PRIME/CKA_BASE values */ dh_pgs.pg = malloc(p_len*2); if (!dh_pgs.pg) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } memset(dh_pgs.pg, 0, p_len*2); memcpy(dh_pgs.pg, prime_attr->pValue, p_len); /* copy CKA_PRIME value */ /* copy CKA_BASE value, it must have leading zeros * if it is shorter than CKA_PRIME */ memcpy(dh_pgs.pg + p_len + (p_len - g_len), base_attr->pValue, g_len); dh_pgs.pg_bytes = p_len * 2; #ifdef DEBUG TRACE_DEBUG("%s P:\n", __func__); TRACE_DEBUG_DUMP(&dh_pgs.pg[0], p_len); TRACE_DEBUG("%s G:\n", __func__); TRACE_DEBUG_DUMP(&dh_pgs.pg[p_len], p_len); #endif /* add special attribute, do not add it to ock's pPublicKeyTemplate */ CK_ATTRIBUTE pgs[] = {{CKA_IBM_STRUCT_PARAMS, (CK_VOID_PTR) dh_pgs.pg, dh_pgs.pg_bytes}}; memcpy(&(pPublicKeyTemplate_new[new_public_attr]), &(pgs[0]), sizeof(CK_ATTRIBUTE)); rc = m_GenerateKeyPair(pMechanism, pPublicKeyTemplate_new, new_public_attr+1, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, ep11_pin_blob, ep11_pin_blob_len, privblob, &privblobsize, publblob, &publblobsize, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s m_GenerateKeyPair failed rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } TRACE_INFO("%s rc=0x%lx plen=%zd publblobsize=0x%zx privblobsize=0x%zx\n", __func__, rc, p_len, publblobsize, privblobsize); /* store the blobs */ rc = build_attribute(CKA_IBM_OPAQUE, publblob, publblobsize, &opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } rc = template_update_attribute(publ_tmpl, opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } rc = build_attribute(CKA_IBM_OPAQUE, privblob, privblobsize, &opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } rc = template_update_attribute(priv_tmpl, opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } #ifdef DEBUG TRACE_DEBUG("%s DH SPKI\n", __func__ ); TRACE_DEBUG_DUMP(publblob, publblobsize); #endif /* CKA_VALUE of the public key must hold 'y' */ rc = ep11_spki_key(publblob, &y_start, &bit_str_len); if (rc != CKR_OK) { TRACE_ERROR("%s ber_decode SKPI failed rc=0x%lx\n", __func__, rc); rc = CKR_GENERAL_ERROR; goto dh_generate_keypair_end; } /* DHPublicKey ::= INTEGER -- public key, y = g^x mod p */ rc = ber_decode_INTEGER(y_start, &data, &data_len, &field_len); if (rc != CKR_OK) { TRACE_ERROR("%s ber_decode_INTEGER failed rc=0x%lx\n", __func__, rc); rc = CKR_GENERAL_ERROR; goto dh_generate_keypair_end; } TRACE_INFO("%s DH SPKI decode INTEGER rc=0x%lx y_start=0x%x" " field_len=%lu data_len=%lu data=0x%hhx\n", __func__, rc, y_start[1], field_len, data_len, data[0]); /* remove leading zero, a leading zero is needed * (according to standard) if left most bit of first byte is 1, * in order to indicate a positive number. * ock, like many others, interpret 'y' always as positive number, * a leading zero is not expected by ock. */ if (data[0] == 0) { data_len = data_len - 1; data = data + 1; TRACE_INFO("%s DH SPKI removed leading zero rc=0x%lx" " y_start=0x%x field_len=%lu data_len=%lu data=0x%hhx\n", __func__, rc, y_start[1], field_len, data_len, data[0]); } rc = build_attribute(CKA_VALUE, data, data_len, &value_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dh_generate_keypair_end; } rc = template_update_attribute(publ_tmpl, value_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); } dh_generate_keypair_end: free(pPublicKeyTemplate_new); if (dh_pgs.pg != NULL) free(dh_pgs.pg); return rc; } static CK_RV dsa_generate_keypair(CK_MECHANISM_PTR pMechanism, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_SESSION_HANDLE h) { CK_RV rc; CK_BYTE publblob[MAX_BLOBSIZE]; size_t publblobsize = sizeof(publblob); CK_BYTE privblob[MAX_BLOBSIZE]; size_t privblobsize = sizeof(privblob); CK_ATTRIBUTE *prime_attr = NULL; CK_ATTRIBUTE *sub_prime_attr = NULL; CK_ATTRIBUTE *base_attr = NULL; CK_ATTRIBUTE *opaque_attr = NULL; CK_ATTRIBUTE *value_attr = NULL; CK_ATTRIBUTE *attr = NULL; size_t p_len=0, q_len=0, g_len=0; int i, new_public_attr; CK_ATTRIBUTE *pPublicKeyTemplate_new = NULL; CK_BYTE *key; CK_BYTE *data; CK_ULONG data_len, field_len, bit_str_len; CK_ATTRIBUTE_PTR dsa_pPublicKeyTemplate = NULL; CK_ULONG dsa_ulPublicKeyAttributeCount = 0; CK_ATTRIBUTE_PTR dsa_pPrivateKeyTemplate = NULL; CK_ULONG dsa_ulPrivateKeyAttributeCount = 0; /* ep11 accepts CKA_PRIME,CKA_SUBPRIME,CKA_BASE only in this format */ struct { size_t pqg_bytes; /* total size: 3*bytecount(P) */ unsigned char *pqg; } dsa_pqgs; memset(&dsa_pqgs, 0, sizeof(dsa_pqgs)); memset(publblob, 0, sizeof(publblob)); memset(privblob, 0, sizeof(privblob)); /* card does not want CKA_PRIME/CKA_BASE/CKA_SUBPRIME * in template but in dsa_pqgs */ pPublicKeyTemplate_new = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) * ulPublicKeyAttributeCount); if (!pPublicKeyTemplate_new) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } memset(pPublicKeyTemplate_new, 0, sizeof(CK_ATTRIBUTE) * ulPublicKeyAttributeCount); for (i = 0, new_public_attr = 0; i < ulPublicKeyAttributeCount; i++) { switch(pPublicKeyTemplate[i].type) { case CKA_PRIME: prime_attr = &(pPublicKeyTemplate[i]); p_len = pPublicKeyTemplate[i].ulValueLen; break; case CKA_SUBPRIME: sub_prime_attr = &(pPublicKeyTemplate[i]); q_len = pPublicKeyTemplate[i].ulValueLen; break; case CKA_BASE: base_attr = &(pPublicKeyTemplate[i]); g_len = pPublicKeyTemplate[i].ulValueLen; break; default: /* copy all other attributes */ memcpy(&pPublicKeyTemplate_new[new_public_attr], &(pPublicKeyTemplate[i]), sizeof(CK_ATTRIBUTE)); new_public_attr++; } } if (prime_attr == NULL || sub_prime_attr == NULL || base_attr == NULL) return CKR_TEMPLATE_INCOMPLETE; /* copy CKA_PRIME/CKA_BASE/CKA_SUBPRIME to private template */ rc = build_attribute(CKA_PRIME, prime_attr->pValue, prime_attr->ulValueLen, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = template_update_attribute( priv_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = build_attribute(CKA_BASE, base_attr->pValue, base_attr->ulValueLen, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = template_update_attribute(priv_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = build_attribute(CKA_PRIME, sub_prime_attr->pValue, sub_prime_attr->ulValueLen, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = template_update_attribute(priv_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } /* if CKA_SUBPRIME,CKA_BASE are smaller than CKA_PRIME * then they are extented by leading zeros till they have * the size of CKA_PRIME */ dsa_pqgs.pqg = malloc(p_len*3); if (!dsa_pqgs.pqg) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } memset(dsa_pqgs.pqg, 0, p_len*3); memcpy(dsa_pqgs.pqg, prime_attr->pValue, p_len); memcpy(dsa_pqgs.pqg + p_len + (p_len - q_len), sub_prime_attr->pValue, q_len); memcpy(dsa_pqgs.pqg + 2*p_len + (p_len - g_len), base_attr->pValue, g_len); dsa_pqgs.pqg_bytes = p_len * 3; #ifdef DEBUG TRACE_DEBUG("%s P:\n", __func__); TRACE_DEBUG_DUMP(&dsa_pqgs.pqg[0], p_len); TRACE_DEBUG("%s Q:\n", __func__); TRACE_DEBUG_DUMP(&dsa_pqgs.pqg[p_len], p_len); TRACE_DEBUG("%s G:\n", __func__); TRACE_DEBUG_DUMP(&dsa_pqgs.pqg[2*p_len], p_len); #endif CK_ATTRIBUTE pqgs[] = {{CKA_IBM_STRUCT_PARAMS, (CK_VOID_PTR)dsa_pqgs.pqg, dsa_pqgs.pqg_bytes}}; /* add special attribute, do not add it to ock's pPublicKeyTemplate */ memcpy(&(pPublicKeyTemplate_new[new_public_attr]), &(pqgs[0]), sizeof(CK_ATTRIBUTE)); rc = check_key_attributes(CKK_DSA, CKO_PUBLIC_KEY, pPublicKeyTemplate_new, new_public_attr+1, &dsa_pPublicKeyTemplate, &dsa_ulPublicKeyAttributeCount); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check public key attributes failed with rc=0x%lx\n", __func__, rc); return rc; } rc = check_key_attributes(CKK_DSA, CKO_PRIVATE_KEY, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &dsa_pPrivateKeyTemplate, &dsa_ulPrivateKeyAttributeCount); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check private key attributes failed with rc=0x%lx\n", __func__, rc); return rc; } rc = m_GenerateKeyPair(pMechanism, dsa_pPublicKeyTemplate, dsa_ulPublicKeyAttributeCount, dsa_pPrivateKeyTemplate, dsa_ulPrivateKeyAttributeCount, ep11_pin_blob, ep11_pin_blob_len, privblob, &privblobsize, publblob, &publblobsize, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s m_GenerateKeyPair failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } TRACE_INFO("%s rc=0x%lx p_len=%zd publblobsize=0x%zx privblobsize=0x%zx npattr=0x%x\n", __func__, rc, p_len, publblobsize, privblobsize, new_public_attr+1); rc = build_attribute(CKA_IBM_OPAQUE, publblob, publblobsize, &opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = template_update_attribute(publ_tmpl, opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = build_attribute(CKA_IBM_OPAQUE, privblob, privblobsize, &opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = template_update_attribute(priv_tmpl, opaque_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } /* set CKA_VALUE of the public key, first get key from SPKI */ rc = ep11_spki_key(publblob, &key, &bit_str_len); if (rc != CKR_OK) { TRACE_ERROR("%s reading DSA SPKI failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } /* key must be an integer */ rc = ber_decode_INTEGER(key, &data, &data_len, &field_len); if (rc != CKR_OK) { TRACE_ERROR("%s reading DSA public key failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } #ifdef DEBUG TRACE_DEBUG("%s dsa_generate_keypair public key:\n", __func__); TRACE_DEBUG_DUMP(data, data_len); #endif rc = build_attribute(CKA_VALUE, data, data_len, &value_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto dsa_generate_keypair_end; } rc = template_update_attribute(publ_tmpl, value_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); } dsa_generate_keypair_end: free(pPublicKeyTemplate_new); if(dsa_pqgs.pqg != NULL) free(dsa_pqgs.pqg); if (dsa_pPublicKeyTemplate) free_attribute_array(dsa_pPublicKeyTemplate, dsa_ulPublicKeyAttributeCount); if (dsa_pPrivateKeyTemplate) free_attribute_array(dsa_pPrivateKeyTemplate, dsa_ulPrivateKeyAttributeCount); return rc; } static CK_RV rsa_ec_generate_keypair(CK_MECHANISM_PTR pMechanism, TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_SESSION_HANDLE h) { CK_RV rc; CK_ATTRIBUTE *attr = NULL; CK_ATTRIBUTE *n_attr = NULL; CK_BYTE privkey_blob[MAX_BLOBSIZE]; size_t privkey_blob_len = sizeof(privkey_blob); unsigned char spki[MAX_BLOBSIZE]; size_t spki_len = sizeof(spki); CK_BYTE publblob[MAX_BLOBSIZE]; size_t publblobsize = sizeof(publblob); CK_BYTE privblob[MAX_BLOBSIZE]; size_t privblobsize = sizeof(privblob); int i; CK_ULONG bit_str_len; CK_BYTE *key; CK_BYTE *data; CK_ULONG data_len; CK_ULONG field_len; CK_ATTRIBUTE_PTR new_pPublicKeyTemplate = NULL; CK_ULONG new_ulPublicKeyAttributeCount = 0; CK_ATTRIBUTE_PTR new_pPrivateKeyTemplate = NULL; CK_ULONG new_ulPrivateKeyAttributeCount = 0; CK_ULONG ktype; if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN) ktype = CKK_EC; else if ((pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN) || (pMechanism->mechanism == CKM_RSA_X9_31_KEY_PAIR_GEN)) ktype = CKK_RSA; else { TRACE_ERROR("%s Neither RSA nor EC mech type provided for RSA/EC_key_pair_gen\n", __func__); return CKR_MECHANISM_INVALID; } rc = check_key_attributes(ktype, CKO_PUBLIC_KEY, pPublicKeyTemplate, ulPublicKeyAttributeCount, &new_pPublicKeyTemplate, &new_ulPublicKeyAttributeCount); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check public key attributes failed with rc=0x%lx\n", __func__, rc); return rc; } rc = check_key_attributes(ktype, CKO_PRIVATE_KEY, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &new_pPrivateKeyTemplate, &new_ulPrivateKeyAttributeCount); if (rc != CKR_OK) { TRACE_ERROR("%s RSA/EC check private key attributes failed with rc=0x%lx\n", __func__, rc); goto error; } /* debug */ for (i = 0; i < new_ulPrivateKeyAttributeCount; i++) { TRACE_INFO("%s gen priv attr type=0x%lx valuelen=0x%lx attrcnt=0x%lx\n", __func__, new_pPrivateKeyTemplate[i].type, new_pPrivateKeyTemplate[i].ulValueLen, new_ulPrivateKeyAttributeCount); } rc = m_GenerateKeyPair(pMechanism, new_pPublicKeyTemplate, new_ulPublicKeyAttributeCount, new_pPrivateKeyTemplate, new_ulPrivateKeyAttributeCount, ep11_pin_blob, ep11_pin_blob_len, privkey_blob, &privkey_blob_len, spki, &spki_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s m_GenerateKeyPair rc=0x%lx spki_len=0x%zx " "privkey_blob_len=0x%zx mech='%s'\n", __func__, rc, spki_len, privkey_blob_len, ep11_get_ckm(pMechanism->mechanism)); goto error; } TRACE_INFO("%s m_GenerateKeyPair rc=0x%lx spki_len=0x%zx " "privkey_blob_len=0x%zx mech='%s'\n", __func__, rc, spki_len, privkey_blob_len, ep11_get_ckm(pMechanism->mechanism)); if (spki_len > MAX_BLOBSIZE || privkey_blob_len > MAX_BLOBSIZE) { TRACE_ERROR("%s blobsize error\n", __func__); rc = CKR_KEY_INDIGESTIBLE; goto error; } memset(publblob, 0, sizeof(publblob)); memset(privblob, 0, sizeof(privblob)); memcpy(publblob, spki, spki_len); publblobsize = spki_len; memcpy(privblob, privkey_blob, privkey_blob_len); privblobsize = privkey_blob_len; rc = build_attribute(CKA_IBM_OPAQUE, publblob, publblobsize, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(publ_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = build_attribute(CKA_IBM_OPAQUE, privblob, privblobsize, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(priv_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN) { /* scan the SPKI for CKA_EC_POINT */ #ifdef DEBUG TRACE_DEBUG("%s ec_generate_keypair spki:\n", __func__); TRACE_DEBUG_DUMP(spki, spki_len); #endif rc = ep11_spki_key(spki, &key, &bit_str_len); if (rc != CKR_OK) { TRACE_ERROR("%s read key from SPKI failed with rc=0x%lx\n", __func__, rc); goto error; } /* 'key' is already EC point, * SEC 1: Elliptic Curve Cryptography: * The elliptic curve public key (a value of type ECPoint * that is an OCTET STRING) is mapped to a subjectPublicKey * (a value encoded as type BIT STRING) as follows: The most * significant bit of the value of the OCTET STRING becomes * the most significant bit of the value of the BIT STRING * and so on with consecutive bits until the least significant * bit of the OCTET STRING becomes the least significant bit * of the BIT STRING. */ TRACE_INFO("%s ecpoint length 0x%lx\n", __func__, bit_str_len); data_len = bit_str_len; data = key; #ifdef DEBUG TRACE_DEBUG("%s ec_generate_keypair ecpoint:\n", __func__); TRACE_DEBUG_DUMP(data, data_len); #endif /* build and add CKA_EC_POINT */ rc = build_attribute(CKA_EC_POINT, data, data_len, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(publ_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } /* copy CKA_EC_PARAMS/CKA_ECDSA_PARAMS to private template */ if (template_attribute_find(publ_tmpl, CKA_EC_PARAMS, &attr)) { rc = build_attribute(attr->type, attr->pValue, attr->ulValueLen, &n_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(priv_tmpl, n_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } } if (template_attribute_find(publ_tmpl, CKA_ECDSA_PARAMS, &attr)) { rc = build_attribute(attr->type, attr->pValue, attr->ulValueLen, &n_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(priv_tmpl, n_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } } } else { /* scan the SPKI for modulus and public exponent and * set the public key attributes, a user would use the * already built SPKI (in CKA_IBM_OPAQUE of the public key). */ CK_BYTE *modulus, *publ_exp; rc = ep11_spki_key(spki, &key, &bit_str_len); if (rc != CKR_OK) { TRACE_ERROR("%s read key from SPKI failed with rc=0x%lx\n", __func__, rc); goto error; } /* key must be a sequence holding two integers, * modulus and public exponent */ rc = ber_decode_SEQUENCE(key, &data, &data_len, &field_len); if (rc != CKR_OK) { TRACE_ERROR("%s read sequence failed with rc=0x%lx\n", __func__, rc); goto error; } modulus = key + field_len - data_len; rc = ber_decode_INTEGER(modulus, &data, &data_len, &field_len); if (rc != CKR_OK) { TRACE_ERROR("%s read modulus failed with rc=0x%lx\n", __func__, rc); goto error; } #ifdef DEBUG TRACE_DEBUG("%s rsa_generate_keypair modulus:\n", __func__); TRACE_DEBUG_DUMP(data, data_len); #endif /* build and add CKA_MODULUS */ rc = build_attribute(CKA_MODULUS, data, data_len, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(publ_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } /* read public exponent */ publ_exp = modulus + field_len; rc = ber_decode_INTEGER(publ_exp, &data, &data_len, &field_len); if (rc != CKR_OK) { TRACE_ERROR("%s read public exponent failed with rc=0x%lx\n", __func__, rc); goto error; } #ifdef DEBUG TRACE_DEBUG("%s rsa_generate_keypair public exponent:\n", __func__); TRACE_DEBUG_DUMP(data, data_len); #endif /* build and add CKA_PUBLIC_EXPONENT */ rc = build_attribute(CKA_PUBLIC_EXPONENT, data, data_len, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(publ_tmpl, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } } error: if (new_pPrivateKeyTemplate) free_attribute_array(new_pPrivateKeyTemplate, new_ulPrivateKeyAttributeCount); if (new_pPublicKeyTemplate) free_attribute_array(new_pPublicKeyTemplate, new_ulPublicKeyAttributeCount); return rc; } /* generic function to generate RSA,DH,EC and DSA key pairs */ CK_RV ep11tok_generate_key_pair(SESSION * sess, 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) { CK_RV rc; OBJECT *public_key_obj = NULL; OBJECT *private_key_obj = NULL; CK_ULONG priv_ktype, publ_ktype; CK_ULONG class; CK_ATTRIBUTE *attr = NULL; CK_ATTRIBUTE *n_attr = NULL; /* Get the keytype to use when creating the key object */ rc = ep11_get_keytype(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, pMechanism, &priv_ktype, &class); if (rc != CKR_OK) { TRACE_ERROR("%s get_keytype failed with rc=0x%lx\n", __func__, rc); goto error; } rc = ep11_get_keytype(pPublicKeyTemplate, ulPublicKeyAttributeCount, pMechanism, &publ_ktype, &class); if (rc != CKR_OK) { TRACE_ERROR("%s get_keytype failed with rc=0x%lx\n", __func__, rc); goto error; } /* Now build the skeleton key. */ rc = object_mgr_create_skel(sess, pPublicKeyTemplate, ulPublicKeyAttributeCount, MODE_KEYGEN, CKO_PUBLIC_KEY, publ_ktype, &public_key_obj); if (rc != CKR_OK) { TRACE_DEVEL("%s Object mgr create skeleton failed\n", __func__); goto error; } rc = object_mgr_create_skel(sess, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, MODE_KEYGEN, CKO_PRIVATE_KEY, priv_ktype, &private_key_obj); if (rc != CKR_OK) { TRACE_DEVEL("%s Object mgr create skeleton failed\n", __func__); goto error; } switch(pMechanism->mechanism) { case CKM_DH_PKCS_KEY_PAIR_GEN: rc = dh_generate_keypair(pMechanism, public_key_obj->template, private_key_obj->template, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, sess->handle); break; case CKM_EC_KEY_PAIR_GEN: /* takes same parameters as RSA */ case CKM_RSA_PKCS_KEY_PAIR_GEN: case CKM_RSA_X9_31_KEY_PAIR_GEN: rc = rsa_ec_generate_keypair(pMechanism, public_key_obj->template, private_key_obj->template, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, sess->handle); break; case CKM_DSA_PARAMETER_GEN: case CKM_DSA_KEY_PAIR_GEN: rc = dsa_generate_keypair(pMechanism, public_key_obj->template, private_key_obj->template, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, sess->handle); break; default: TRACE_ERROR("%s invalid mech %s\n", __func__, ep11_get_ckm(pMechanism->mechanism)); rc = CKR_MECHANISM_INVALID; goto error; } if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx hpubkey=0x%lx hprivkey=0x%lx" " pub_name='%s' priv_name='%s' pub_obj=%p priv_obj=%p\n", __func__, rc, *phPublicKey, *phPrivateKey, public_key_obj->name, private_key_obj->name, public_key_obj, private_key_obj); goto error; } else { TRACE_INFO("%s rc=0x%lx hpubkey=0x%lx hprivkey=0x%lx" " pub_name='%s' priv_name='%s' pub_obj=%p priv_obj=%p\n", __func__, rc, *phPublicKey, *phPrivateKey, public_key_obj->name, private_key_obj->name, public_key_obj, private_key_obj); } /* Copy CKA_MODULUS and CKA_PUBLIC_EXPONENT attributes from * public key object to private key object to fulfill PKCS#11 * private key template requirements */ if (template_attribute_find(public_key_obj->template, CKA_MODULUS, &attr)) { rc = build_attribute(attr->type, attr->pValue, attr->ulValueLen, &n_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(private_key_obj->template, n_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with " "rc=0x%lx\n", __func__, rc); goto error; } } if (template_attribute_find(public_key_obj->template, CKA_PUBLIC_EXPONENT, &attr)) { rc = build_attribute(attr->type, attr->pValue, attr->ulValueLen, &n_attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(private_key_obj->template, n_attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with " "rc=0x%lx\n", __func__, rc); goto error; } } /* Keys should be fully constructed, * assign object handles and store keys. */ rc = object_mgr_create_final(sess, public_key_obj, phPublicKey); if (rc != CKR_OK) { TRACE_DEVEL("%s Object mgr create final failed\n", __func__); goto error; } rc = object_mgr_create_final(sess, private_key_obj, phPrivateKey); if (rc != CKR_OK) { TRACE_DEVEL("%s Object mgr create final failed\n", __func__); object_mgr_destroy_object(sess, *phPublicKey); public_key_obj = NULL; goto error; } return rc; error: if (public_key_obj) object_free(public_key_obj); if (private_key_obj) object_free(private_key_obj); *phPublicKey = 0; *phPrivateKey = 0; return rc; } /* Returns a blob for a key (handle or key obj). * The blob is created if none was build yet. */ static CK_RV h_opaque_2_blob(CK_OBJECT_HANDLE handle, CK_BYTE **blob, size_t *blobsize, OBJECT **kobj) { OBJECT *key_obj; CK_ATTRIBUTE *attr = NULL; CK_RV rc; /* find the key obj by the key handle */ rc = object_mgr_find_in_map1(handle, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s key 0x%lx not mapped\n", __func__, handle); return rc; } /* blob already exists */ if (template_attribute_find(key_obj->template, CKA_IBM_OPAQUE, &attr) && (attr->ulValueLen > 0)) { *blob = attr->pValue; *blobsize = (size_t) attr->ulValueLen; *kobj = key_obj; TRACE_INFO("%s blob found blobsize=0x%zx\n", __func__, *blobsize); return CKR_OK; } else { /* should not happen, imported key types not supported * should cause a failing token_specific_object_add */ TRACE_ERROR("%s no blob\n", __func__); return CKR_FUNCTION_FAILED; } } CK_RV ep11tok_sign_init(SESSION *session, CK_MECHANISM *mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key) { CK_RV rc; size_t keyblobsize = 0; CK_BYTE *keyblob; OBJECT *key_obj = NULL; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; size_t ep11_sign_state_l = MAX_SIGN_STATE_BYTES; CK_BYTE *ep11_sign_state = malloc(ep11_sign_state_l); if (!ep11_sign_state) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } rc = h_opaque_2_blob(key, &keyblob, &keyblobsize, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s no blob rc=0x%lx\n", __func__, rc); return rc; } rc = m_SignInit(ep11_sign_state, &ep11_sign_state_l, mech, keyblob, keyblobsize, ep11tok_target) ; if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx blobsize=0x%zx key=0x%lx mech=0x%lx\n", __func__, rc, keyblobsize, key, mech->mechanism); free(ep11_sign_state); } else { /* SIGN_VERIFY_CONTEX holds all needed for continuing, * also by another adapter (stateless requests) */ ctx->key = key; ctx->multi = FALSE; ctx->active = TRUE; ctx->context = ep11_sign_state; ctx->context_len = ep11_sign_state_l; TRACE_INFO("%s rc=0x%lx blobsize=0x%zx key=0x%lx mech=0x%lx\n", __func__, rc, keyblobsize, key, mech->mechanism); } return rc; } CK_RV ep11tok_sign(SESSION *session, CK_BBOOL length_only, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG *sig_len) { CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; rc = m_Sign(ctx->context, ctx->context_len, in_data, in_data_len, signature, sig_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_sign_update(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len) { CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; if (!in_data || !in_data_len) return CKR_OK; rc = m_SignUpdate(ctx->context, ctx->context_len, in_data, in_data_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_sign_final(SESSION *session, CK_BBOOL length_only, CK_BYTE *signature, CK_ULONG *sig_len) { CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx; rc = m_SignFinal(ctx->context, ctx->context_len, signature, sig_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_verify_init(SESSION *session, CK_MECHANISM *mech, CK_BBOOL recover_mode, CK_OBJECT_HANDLE key) { CK_RV rc; CK_BYTE *spki; size_t spki_len = 0; OBJECT *key_obj = NULL; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; size_t ep11_sign_state_l = MAX_SIGN_STATE_BYTES; CK_BYTE *ep11_sign_state = malloc(ep11_sign_state_l); if (!ep11_sign_state) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } rc = h_opaque_2_blob(key, &spki, &spki_len, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s no blob rc=0x%lx\n", __func__, rc); return rc; } rc = m_VerifyInit(ep11_sign_state, &ep11_sign_state_l, mech, spki, spki_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx spki_len=0x%zx key=0x%lx " "ep11_sign_state_l=0x%zx mech=0x%lx\n", __func__, rc, spki_len, key, ep11_sign_state_l, mech->mechanism); } else { ctx->key = key; ctx->multi = FALSE; ctx->active = TRUE; ctx->context = ep11_sign_state; ctx->context_len = ep11_sign_state_l; TRACE_INFO("%s rc=0x%lx spki_len=0x%zx key=0x%lx " "ep11_sign_state_l=0x%zx mech=0x%lx\n", __func__, rc, spki_len, key, ep11_sign_state_l, mech->mechanism); } return rc; } CK_RV ep11tok_verify(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *signature, CK_ULONG sig_len) { CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; rc = m_Verify(ctx->context, ctx->context_len, in_data, in_data_len, signature, sig_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_verify_update(SESSION *session, CK_BYTE *in_data, CK_ULONG in_data_len) { CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; if (!in_data || !in_data_len) return CKR_OK; rc = m_VerifyUpdate(ctx->context, ctx->context_len, in_data, in_data_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_verify_final(SESSION *session, CK_BYTE *signature, CK_ULONG sig_len) { CK_RV rc; SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx; rc = m_VerifyFinal(ctx->context, ctx->context_len, signature, sig_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_decrypt_final(SESSION *session, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->decr_ctx; rc = m_DecryptFinal(ctx->context, ctx->context_len, output_part, p_output_part_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_decrypt(SESSION *session, CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len) { CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->decr_ctx; rc = m_Decrypt(ctx->context, ctx->context_len, input_data, input_data_len, output_data, p_output_data_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_decrypt_update(SESSION *session, CK_BYTE_PTR input_part, CK_ULONG input_part_len, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->decr_ctx; if (!input_part || !input_part_len) { *p_output_part_len = 0; return CKR_OK; /* nothing to update, keep context */ } rc = m_DecryptUpdate(ctx->context, ctx->context_len, input_part, input_part_len, output_part, p_output_part_len, ep11tok_target) ; if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_encrypt_final(SESSION *session, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->encr_ctx; rc = m_EncryptFinal(ctx->context, ctx->context_len, output_part, p_output_part_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_encrypt(SESSION *session, CK_BYTE_PTR input_data, CK_ULONG input_data_len, CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len) { CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->encr_ctx; rc = m_Encrypt(ctx->context, ctx->context_len, input_data, input_data_len, output_data, p_output_data_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_encrypt_update(SESSION *session, CK_BYTE_PTR input_part, CK_ULONG input_part_len, CK_BYTE_PTR output_part, CK_ULONG_PTR p_output_part_len) { CK_RV rc = CKR_OK; ENCR_DECR_CONTEXT *ctx = &session->encr_ctx; if (!input_part || !input_part_len) { *p_output_part_len = 0; return CKR_OK; /* nothing to update, keep context */ } rc = m_EncryptUpdate(ctx->context, ctx->context_len, input_part, input_part_len, output_part, p_output_part_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } static CK_RV ep11_ende_crypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key, int op) { CK_RV rc = CKR_OK; CK_BYTE *blob; size_t blob_len = 0; OBJECT *key_obj = NULL; size_t ep11_state_l = MAX_CRYPT_STATE_BYTES; CK_BYTE *ep11_state = malloc(ep11_state_l); /* freed by encr/decr_mgr.c */ if (!ep11_state) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } rc = h_opaque_2_blob(key, &blob, &blob_len, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s no blob rc=0x%lx\n", __func__, rc); return rc; } if (op == DECRYPT) { ENCR_DECR_CONTEXT *ctx = &session->decr_ctx; rc = m_DecryptInit(ep11_state, &ep11_state_l, mech, blob, blob_len, ep11tok_target); ctx->key = key; ctx->active = TRUE; ctx->context = ep11_state; ctx->context_len = ep11_state_l; if (rc != CKR_OK) { TRACE_ERROR("%s m_DecryptInit rc=0x%lx blob_len=0x%zx " "mech=0x%lx\n", __func__, rc, blob_len, mech->mechanism); } else { TRACE_INFO("%s m_DecryptInit rc=0x%lx blob_len=0x%zx " "mech=0x%lx\n", __func__, rc, blob_len, mech->mechanism); } } else { ENCR_DECR_CONTEXT *ctx = &session->encr_ctx; rc = m_EncryptInit (ep11_state, &ep11_state_l, mech, blob, blob_len, ep11tok_target); ctx->key = key; ctx->active = TRUE; ctx->context = ep11_state; ctx->context_len = ep11_state_l; if (rc != CKR_OK) { TRACE_ERROR("%s m_EncryptInit rc=0x%lx blob_len=0x%zx " "mech=0x%lx\n", __func__, rc, blob_len, mech->mechanism); } else { TRACE_INFO("%s m_EncryptInit rc=0x%lx blob_len=0x%zx " "mech=0x%lx\n", __func__, rc, blob_len, mech->mechanism); } } return rc; } CK_RV ep11tok_encrypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key) { CK_RV rc; TRACE_INFO("%s key=0x%lx\n", __func__, key); rc = ep11_ende_crypt_init(session, mech, key, ENCRYPT); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_decrypt_init(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key) { CK_RV rc; TRACE_INFO("%s key=0x%lx mech=0x%lx\n", __func__, key, mech->mechanism); rc = ep11_ende_crypt_init(session, mech, key, DECRYPT); if (rc != CKR_OK) { TRACE_ERROR("%s rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx\n", __func__, rc); } return rc; } CK_RV ep11tok_wrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR p_wrapped_key_len) { CK_RV rc; CK_BYTE *wrapping_blob; size_t wrapping_blob_len; CK_BYTE *wrap_target_blob; size_t wrap_target_blob_len; int size_querry = 0; OBJECT *key_obj = NULL; CK_ATTRIBUTE *attr; /* ep11 weakness: * it does not set *p_wrapped_key_len if wrapped_key == NULL * (that is with a size query) */ if (wrapped_key == NULL) { size_querry = 1; *p_wrapped_key_len = MAX_BLOBSIZE; wrapped_key = malloc(MAX_BLOBSIZE); if (!wrapped_key) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } } /* the key that encrypts */ rc = h_opaque_2_blob(wrapping_key, &wrapping_blob, &wrapping_blob_len, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s h_opaque_2_blob(wrapping_key) failed with rc=0x%lx\n", __func__, rc); if (size_querry) free(wrapped_key); return rc; } /* the key to be wrapped */ rc = h_opaque_2_blob(key, &wrap_target_blob, &wrap_target_blob_len, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s h_opaque_2_blob(key) failed with rc=0x%lx\n", __func__, rc); if (size_querry) free(wrapped_key); return rc; } /* check if wrap mechanism is allowed for the key to be wrapped. * AES_ECB and AES_CBC is only allowed to wrap secret keys. */ if (!template_attribute_find(key_obj->template, CKA_CLASS, &attr)) { TRACE_ERROR("%s No CKA_CLASS attribute found in key template\n", __func__); return CKR_TEMPLATE_INCOMPLETE; } if ((*(CK_OBJECT_CLASS *)attr->pValue != CKO_SECRET_KEY) && ((mech->mechanism == CKM_AES_ECB) || (mech->mechanism == CKM_AES_CBC))) { TRACE_ERROR("%s Wrap mechanism does not match to target key type\n", __func__); return CKR_KEY_NOT_WRAPPABLE; } /* debug */ TRACE_INFO("%s start wrapKey: mech=0x%lx wr_key=0x%lx\n", __func__, mech->mechanism, wrapping_key); /* the key to be wrapped is extracted from its blob by the card * and a standard BER encoding is build which is encryted by * the wrapping key (wrapping_blob). * The wrapped key can be processed by any PKCS11 implementation. */ rc = m_WrapKey(wrap_target_blob, wrap_target_blob_len, wrapping_blob, wrapping_blob_len, NULL, ~0, mech, wrapped_key, p_wrapped_key_len, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s m_WrapKey failed with rc=0x%lx\n", __func__, rc); } else { TRACE_INFO("%s rc=0x%lx wr_key=%p wr_key_len=0x%lx\n", __func__, rc, wrapped_key, *p_wrapped_key_len); } if (size_querry) free(wrapped_key); return rc; } CK_RV ep11tok_unwrap_key(SESSION *session, CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE_PTR p_key) { CK_RV rc; CK_BYTE *wrapping_blob; size_t wrapping_blob_len; char csum[MAX_BLOBSIZE]; CK_ULONG cslen = sizeof(csum); OBJECT *key_obj = NULL; CK_BYTE keyblob[MAX_BLOBSIZE]; size_t keyblobsize = sizeof(keyblob); CK_ATTRIBUTE *attr = NULL; int i = 0; CK_ULONG ktype; CK_ULONG class; CK_ULONG len; CK_ATTRIBUTE_PTR new_attrs = NULL; CK_ULONG new_attrs_len = 0; OBJECT *kobj = NULL; /* get wrapping key blob */ rc = h_opaque_2_blob(wrapping_key, &wrapping_blob, &wrapping_blob_len, &kobj); if (rc != CKR_OK) { TRACE_ERROR("%s h_opaque_2_blob(wrapping_key) failed with rc=0x%lx\n", __func__, rc); return rc; } TRACE_DEVEL("%s start unwrapKey: mech=0x%lx attrs_len=0x%lx wr_key=0x%lx\n", __func__, mech->mechanism, attrs_len, wrapping_key); for (i = 0; i < attrs_len; i++) { TRACE_DEVEL(" attribute attrs.type=0x%lx\n", attrs[i].type); } memset(keyblob, 0, sizeof(keyblob)); /*get key type of unwrapped key*/ CK_ATTRIBUTE_PTR cla_attr = get_attribute_by_type(attrs, attrs_len, CKA_CLASS); CK_ATTRIBUTE_PTR keytype_attr = get_attribute_by_type(attrs, attrs_len, CKA_KEY_TYPE); if (!cla_attr || !keytype_attr) { TRACE_ERROR("%s CKA_CLASS or CKA_KEY_CLASS attributes not found\n", __func__); return CKR_FUNCTION_FAILED; } switch (*(CK_KEY_TYPE *)cla_attr->pValue) { case CKO_SECRET_KEY: rc = check_key_attributes(*(CK_KEY_TYPE *)keytype_attr->pValue, CKO_SECRET_KEY, attrs, attrs_len, &new_attrs, &new_attrs_len); break; case CKO_PUBLIC_KEY: rc = check_key_attributes(*(CK_KEY_TYPE *)keytype_attr->pValue, CKO_PUBLIC_KEY, attrs, attrs_len, &new_attrs, &new_attrs_len); break; case CKO_PRIVATE_KEY: rc = check_key_attributes(*(CK_KEY_TYPE *)keytype_attr->pValue, CKO_PRIVATE_KEY, attrs, attrs_len, &new_attrs, &new_attrs_len); break; default: TRACE_ERROR("%s Missing CKA_CLASS type of wrapped key\n", __func__); return CKR_TEMPLATE_INCOMPLETE; } if (rc != CKR_OK) { TRACE_ERROR("%s check key attributes failed: rc=0x%lx\n", __func__, rc); goto error; } /* check if unwrap mechanism is allowed for the key to be unwrapped. * AES_ECB and AES_CBC only allowed to unwrap secret keys. */ if ( (*(CK_OBJECT_CLASS *)cla_attr->pValue != CKO_SECRET_KEY) && ((mech->mechanism == CKM_AES_ECB) || (mech->mechanism == CKM_AES_CBC))) return CKR_ARGUMENTS_BAD; /* we need a blob for the new key created by unwrapping, * the wrapped key comes in BER */ rc = m_UnwrapKey(wrapped_key, wrapped_key_len, wrapping_blob, wrapping_blob_len, NULL, ~0, ep11_pin_blob, ep11_pin_blob_len, mech, new_attrs, new_attrs_len, keyblob, &keyblobsize, csum, &cslen, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s m_UnwrapKey rc=0x%lx blobsize=0x%zx mech=0x%lx\n", __func__, rc, keyblobsize, mech->mechanism); goto error; } TRACE_INFO("%s m_UnwrapKey rc=0x%lx blobsize=0x%zx mech=0x%lx\n", __func__, rc, keyblobsize, mech->mechanism); /* card provides length in csum bytes 4 - 7, big endian */ len = csum[6] + 256*csum[5] + 256*256*csum[4] + 256*256*256*csum[3]; len = len/8; /* comes in bits */ TRACE_INFO("%s m_UnwrapKey length 0x%hhx 0x%hhx 0x%hhx 0x%hhx 0x%lx\n", __func__, csum[3], csum[4], csum[5], csum[6], len); /* Get the keytype to use when creating the key object */ rc = ep11_get_keytype(new_attrs, new_attrs_len, mech, &ktype, &class); if (rc != CKR_OK) { TRACE_ERROR("%s get_subclass failed with rc=0x%lx\n", __func__, rc); goto error; } /* Start creating the key object */ rc = object_mgr_create_skel(session, new_attrs, new_attrs_len, MODE_UNWRAP, class, ktype, &key_obj); if (rc != CKR_OK) { TRACE_ERROR("%s object_mgr_create_skel failed with rc=0x%lx\n", __func__, rc); goto error; } rc = build_attribute(CKA_IBM_OPAQUE, keyblob, keyblobsize, &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(key_obj->template, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = build_attribute(CKA_VALUE_LEN, (CK_BYTE *) &len, sizeof(CK_ULONG), &attr); if (rc != CKR_OK) { TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } rc = template_update_attribute(key_obj->template, attr); if (rc != CKR_OK) { TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n", __func__, rc); goto error; } /* key should be fully constructed. * Assign an object handle and store key. */ rc = object_mgr_create_final(session, key_obj, p_key); if (rc != CKR_OK) { TRACE_ERROR("%s object_mgr_create_final with rc=0x%lx\n", __func__, rc); goto error; } goto done; error: if (key_obj) object_free(key_obj); *p_key = 0; done: if (new_attrs) free_attribute_array(new_attrs, new_attrs_len); return rc; } /* mechanisms ep11 reports but should be hidden because e.g. the EP11 card operates in a FIPS mode that forbides the mechanism, add here other mechanisms if required */ CK_MECHANISM_TYPE ep11_banned_mech_list[] = { #ifdef DEFENSIVE_MECHLIST CKM_DES_KEY_GEN, CKM_DES_ECB, CKM_DES_CBC, CKM_DES_CBC_PAD, CKM_GENERIC_SECRET_KEY_GEN, CKM_SHA224, CKM_SHA224_HMAC, CKM_SHA224_RSA_PKCS, CKM_SHA224_RSA_PKCS_PSS, CKM_SHA256_RSA_PKCS_PSS, CKM_SHA384_RSA_PKCS_PSS, CKM_SHA512_RSA_PKCS_PSS, CKM_SHA224_KEY_DERIVATION, CKM_SHA384_KEY_DERIVATION, CKM_SHA512_KEY_DERIVATION, /* Vendor specific */ 0x80020006, 0x80020007, 0x8001000C, 0x80020004, 0x8001000D, 0x80040001, 0x80010007, #endif }; CK_ULONG banned_mech_list_len = (sizeof(ep11_banned_mech_list) / sizeof(CK_MECHANISM_TYPE)); /* filtering out some mechanisms we do not want to provide * makes it complicated */ CK_RV ep11tok_get_mechanism_list(CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { CK_RV rc = 0; CK_ULONG counter = 0; CK_MECHANISM_TYPE_PTR mlist = NULL; int i, j, banned; /* size querry */ if (pMechanismList == NULL) { rc = m_GetMechanismList(0, pMechanismList, pulCount, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #1\n", __func__, rc); return rc; } /* adjust the size according to the ban list, * for this we need to know what the card provides */ counter = *pulCount; mlist = (CK_MECHANISM_TYPE *)malloc(sizeof(CK_MECHANISM_TYPE) * counter); if (!mlist) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } rc = m_GetMechanismList(0, mlist, &counter, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #2\n", __func__, rc); free(mlist); return rc; } for (i = 0; i < counter; i++) { banned = 0; for (j = 0; j < banned_mech_list_len; j++) { if (mlist[i] == ep11_banned_mech_list[j]) { banned = 1; TRACE_INFO("%s banned mech '%s'\n", __func__, ep11_get_ckm(ep11_banned_mech_list[j])); } } if (banned == 1) { /* banned mech found, * decrement reported list size */ *pulCount = *pulCount - 1; } } } else { /* 2. call, content request */ /* find out size ep11 will report, cannot use the size * that comes as parameter, this is a 'reduced size', * ep11 would complain about insufficient list size */ rc = m_GetMechanismList(0, mlist, &counter, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #3\n", __func__, rc); return rc; } mlist = (CK_MECHANISM_TYPE *)malloc(sizeof(CK_MECHANISM_TYPE) * counter); if (!mlist) { TRACE_ERROR("%s Memory allocation failed\n", __func__); return CKR_HOST_MEMORY; } /* all the card has */ rc = m_GetMechanismList(0, mlist, &counter, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #4\n", __func__, rc); free(mlist); return rc; } for (i = 0; i < counter; i++) TRACE_INFO("%s raw mech list entry '%s'\n", __func__, ep11_get_ckm(mlist[i])); /* copy only mechanisms not banned */ *pulCount = 0; for (i = 0; i < counter; i++) { banned = 0; for (j = 0; j < banned_mech_list_len; j++) { if (mlist[i] == ep11_banned_mech_list[j]) { banned = 1; } } if (banned == 0) { pMechanismList[*pulCount] = mlist[i]; *pulCount = *pulCount + 1; } else { ; } /* do not copy banned mech */ } } if (mlist) free(mlist); return rc; } CK_RV ep11tok_get_mechanism_info(CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_RV rc; int i; rc = m_GetMechanismInfo(0, type, pInfo, ep11tok_target); if (rc != CKR_OK) { TRACE_ERROR("%s m_GetMechanismInfo(0x%lx) failed with rc=0x%lx\n", __func__, type, rc); return rc; } /* The card operates always in a FISP mode that requires stronger * key sizes, but, in theory, can also operate with weaker key sizes. * Customers are not interested in theory but in what mechanism * they can use (mechanisms that are not rejected by the card). */ for (i = 0; i < banned_mech_list_len; i++) { if (type == ep11_banned_mech_list[i]) return CKR_MECHANISM_INVALID; } #ifdef DEFENSIVE_MECHLIST if (rc == CKR_OK) { switch (type) { case CKM_RSA_PKCS: case CKM_RSA_PKCS_KEY_PAIR_GEN: case CKM_RSA_X9_31_KEY_PAIR_GEN: case CKM_RSA_PKCS_PSS: case CKM_SHA1_RSA_X9_31: case CKM_SHA1_RSA_PKCS: case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA224_RSA_PKCS: case CKM_SHA224_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS: case CKM_SHA512_RSA_PKCS_PSS: case CKM_RSA_X_509: case CKM_RSA_X9_31: /* EP11 card always in a FIPS mode rejecting * lower key sizes */ pInfo->ulMinKeySize = 1024; break; case CKM_SHA256_HMAC: case CKM_SHA224_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_DES3_ECB: case CKM_DES3_CBC: case CKM_DES3_CBC_PAD: case CKM_SHA_1_HMAC: /* EP11 card always in a FIPS mode rejecting * lower key sizes < 80 bits. */ if (pInfo->ulMinKeySize == 8) pInfo->ulMinKeySize = 16; break; default: ; /* do not touch */ } } #endif /* DEFENSIVE_MECHLIST */ if (rc != CKR_OK) TRACE_ERROR("%s rc=0x%lx unsupported '%s'\n", __func__, rc, ep11_get_ckm(type)); return rc; } /* used for reading in the adapter config file, * converts a 'token' to a number, returns 0 with success */ static inline short check_n(char *nptr, int j, int *apqn_i) { char *endptr; long int num = strtol(nptr, &endptr, 10); if (*endptr != '\0') { TRACE_ERROR("%s invalid number '%s' (%d)\n", __func__, nptr, j); return -1; } if (num < 0 || num > 255) { TRACE_ERROR("%s invalid number '%s' %d(%d)\n", __func__, nptr, (int)num, j); return -1; } else if (*apqn_i < 0 || *apqn_i >= MAX_APQN*2) { TRACE_ERROR("%s invalid amount of numbers %d(%d)\n", __func__, (int)num, j); return -1; } else { /* insert number into target variable */ ep11_targets.apqns[*apqn_i] = (short)num; /* how many APQNs numbers so far */ *apqn_i = *apqn_i + 1; return 0; } } static int read_adapter_config_file(const char* conf_name) { FILE *ap_fp = NULL; /* file pointer adapter config file */ int ap_file_size = 0; /* size adapter config file */ char *token, *str; char filebuf[EP11_CFG_FILE_SIZE]; char line[1024]; int i, j; int blackmode = 0; int whitemode = 0; int anymode = 0; int apqn_i = 0; /* how many APQN numbers */ char *conf_dir = getenv("OCK_EP11_TOKEN_DIR"); char fname[PATH_MAX]; int rc = 0; if (ep11_initialized) { return 0; } memset(fname, 0, PATH_MAX); /* via envrionment variable it is possible to overwrite the * directory where the ep11 token config file is searched. */ if (conf_dir) { if (conf_name && strlen(conf_name) > 0) { /* extract filename part from conf_name */ for (i=strlen(conf_name)-1; i >= 0 && conf_name[i] != '/'; i--); snprintf(fname, sizeof(fname), "%s/%s", conf_dir, conf_name+i+1); fname[sizeof(fname)-1] = '\0'; ap_fp = fopen(fname, "r"); if (!ap_fp) TRACE_DEVEL("%s fopen('%s') failed with errno %d\n", __func__, fname, errno); } if (!ap_fp) { snprintf(fname, sizeof(fname), "%s/%s", conf_dir, EP11_DEFAULT_CFG_FILE); fname[sizeof(fname)-1] = '\0'; ap_fp = fopen(fname, "r"); if (!ap_fp) TRACE_DEVEL("%s fopen('%s') failed with errno %d\n", __func__, fname, errno); } } else { if (conf_name && strlen(conf_name) > 0) { strncpy(fname, conf_name, sizeof(fname)); fname[sizeof(fname)-1] = '\0'; ap_fp = fopen(fname, "r"); if (!ap_fp) { TRACE_DEVEL("%s fopen('%s') failed with errno %d\n", __func__, fname, errno); snprintf(fname, sizeof(fname), "%s/%s", OCK_CONFDIR, conf_name); fname[sizeof(fname)-1] = '\0'; ap_fp = fopen(fname, "r"); if (!ap_fp) TRACE_DEVEL("%s fopen('%s') failed with errno %d\n", __func__, fname, errno); } } else { snprintf(fname, sizeof(fname), "%s/%s", OCK_CONFDIR, EP11_DEFAULT_CFG_FILE); fname[sizeof(fname)-1] = '\0'; ap_fp = fopen(fname, "r"); if (!ap_fp) TRACE_DEVEL("%s fopen('%s') failed with errno %d\n", __func__, fname, errno); } } /* now we should really have an open ep11 token config file */ if (!ap_fp) { TRACE_ERROR("%s no valid EP 11 config file found\n", __func__); return APQN_FILE_INV_2; } TRACE_INFO("%s EP 11 token config file is '%s'\n", __func__, fname); /* read config file line by line, * ignore empty and # and copy rest into file buf */ memset(filebuf, 0, EP11_CFG_FILE_SIZE); while (fgets((char *)line, sizeof(line), ap_fp)) { char *p; int len; /* skip over leading spaces */ for (p=line; *p == ' ' || *p == '\t'; p++) ; /* if line is empty or starts with # skip line */ len = strlen(p); if (*p != '#' && *p != '\n' && len > 0) { /* store line in buffer */ if (ap_file_size + len < EP11_CFG_FILE_SIZE) { memcpy(filebuf+ap_file_size, p, len); ap_file_size += len; } else { TRACE_ERROR("%s EP 11 config file filename too large\n", __func__); return APQN_FILE_INV_FILE_SIZE; } } } ep11_targets.length = 0; /* parse the file buf * please note, we still accept the LOGLEVEL entry * for compatibility reasons but just ignore it. */ for (i=0, j=0, str=filebuf; rc == 0; str=NULL) { /* strtok tokenizes the string, * delimiters are newline and whitespace. */ token = strtok(str, "\n\t "); if (i == 0) { /* expecting APQN_WHITELIST or APQN_BLACKLIST * or APQN_ANY or LOGLEVEL or eof. */ if (token == NULL) break; if (strncmp(token, "APQN_WHITELIST", 14) == 0) { whitemode = 1; i = 1; } else if (strncmp(token, "APQN_BLACKLIST", 14) == 0) { blackmode = 1; i = 1; } else if (strncmp(token, "APQN_ANY", 8) == 0) { anymode = 1; i = 0; } else if (strncmp(token, "LOGLEVEL", 8) == 0) i = 3; else { /* syntax error */ TRACE_ERROR("%s Expected APQN_WHITELIST or" " APQN_BLACKLIST or APQN_ANY or LOGLEVEL" " keyword, found '%s' in configfile\n", __func__, token); rc = APQN_FILE_SYNTAX_ERROR_0; break; } } else if (i == 1) { /* expecting END or first number of a number * pair (number range 0...255) */ if (strncmp(token, "END", 3) == 0) i = 0; else { if (check_n(token, j, &apqn_i) < 0) { rc = APQN_FILE_SYNTAX_ERROR_1; break; } i = 2; } } else if (i == 2) { /* expecting second number of a number pair * (number range 0...255) */ if (strncmp(token, "END", 3) == 0) { TRACE_ERROR("%s Expected 2nd number, found '%s' in configfile\n", __func__, token); rc = APQN_FILE_SYNTAX_ERROR_2; break; } if (check_n(token, j, &apqn_i) < 0) { rc = APQN_FILE_SYNTAX_ERROR_3; break; } ep11_targets.length++; if (ep11_targets.length > MAX_APQN) { TRACE_ERROR("%s Too many APQNs in configfile (max %d)\n", __func__, (int) MAX_APQN); rc = APQN_FILE_SYNTAX_ERROR_4; break; } i = 1; j++; } else if (i == 3) { /* expecting log level value * (a number in the range 0...9) */ char *endptr; int loglevel = strtol(token, &endptr, 10); if (*endptr != '\0' || loglevel < 0 || loglevel > 9) { TRACE_ERROR("%s Invalid loglevel value '%s' in configfile\n", __func__, token); rc = APQN_FILE_SYNTAX_ERROR_5; break; } TRACE_WARNING("%s LOGLEVEL setting is not supported any more !\n", __func__); TRACE_WARNING("%s Use opencryptoki logging/tracing facilities instead.\n", __func__); i = 0; } } /* do some checks: */ if (rc == 0) { if ( !(whitemode || blackmode || anymode)) { TRACE_ERROR("%s At least one APQN mode needs to be present in configfile:" " APQN_WHITEMODE or APQN_BLACKMODE or APQN_ANY\n", __func__); rc = APQN_FILE_NO_APQN_MODE; } else if (whitemode || blackmode) { /* at least one APQN needs to be defined */ if (ep11_targets.length < 1) { TRACE_ERROR("%s At least one APQN needs to be defined in the configfile\n", __func__); rc = APQN_FILE_NO_APQN_GIVEN; } } } /* log the white- or blacklist of APQNs */ if (rc == 0 && (whitemode || blackmode)) { TRACE_INFO("%s %s with %d APQNs defined:\n", __func__, blackmode ? "blacklist" : "whitelist", ep11_targets.length); for (i=0; i < ep11_targets.length; i++) { TRACE_INFO(" APQN %d: %d %d\n", i, ep11_targets.apqns[2*i], ep11_targets.apqns[2*i+1]); } } if (blackmode == 1) ep11_targets.length *= -1; ep11_initialized = TRUE; return rc; } opencryptoki+dfsg/usr/lib/pkcs11/ep11_stdll/ep11tok.conf0000644000175000017500000000060612630407154022065 0ustar xnoxxnox# # EP11 token configuration # # In order to use the EP11 Token you need to specify a list of # adapter/domain pairs installed and configured on your system. # # There are 2 ways to specify the crypto adapters: # 1) explicitly list of ap-qid/domain-id pairs # # APQN_WHITELIST # 08 13 # 10 13 # END # # 2) any available crypto adapters # # APQN_ANY # APQN_ANY opencryptoki+dfsg/usr/lib/pkcs11/ep11_stdll/tok_struct.h0000644000175000017500000004431112630407154022305 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2002 */ /*************************************************************************** Change Log ========== 4/25/03 Kapil Sood (kapil@corrent.com) Added DH key pair generation and DH shared key derivation functions. ****************************************************************************/ // SAB FIXME need to figure out a better way... // // to get the variant dependency out #ifndef __TOK_STRUCT_H #define __TOK_STRUCT_H #include #include "tok_spec_struct.h" #ifndef SW_CONFIG_PATH #ifndef CONFIG_PATH #warning CONFIG_PATH not set, using default (/usr/local/var/lib/opencryptoki) #define CONFIG_PATH "/usr/local/var/lib/opencryptoki" #endif // #ifndef CONFIG_PATH #define SW_CONFIG_PATH CONFIG_PATH "/ep11tok" #endif // #ifndef SW_CONFIG_PATH token_spec_t token_specific = { SW_CONFIG_PATH, "ep11tok", 24, // keysize // Token data info: { FALSE, // Don't use per guest data store TRUE, // Use master key CKM_DES3_CBC, // Data store encryption "12345678", // Default initialization vector for pins "10293847", // Default initialization vector for objects }, NULL, // t_creatlock NULL, // t_attach_shm NULL, // init NULL, // init_token_data NULL, // load_token_data NULL, // save_token_data &token_specific_rng, NULL, // final NULL, // init_token NULL, // token_specific_login, NULL, // token_specific_logout, NULL, // init_pin, NULL, // set_pin // DES NULL, // des_key_gen, NULL, // des_ecb, NULL, // des_cbc, // Triple DES NULL, // tdes_ecb, NULL, // tdes_cbc, NULL, // des3_ofb NULL, // des3_cfb NULL, // des3_mac // RSA NULL, // rsa_decrypt NULL, // rsa_encrypt NULL, // rsa_sign NULL, // rsa_verify NULL, // rsa_verify_recover NULL, // rsa_x509_decrypt NULL, // rsa_x509_encrypt NULL, // rsa_x509_sign NULL, // rsa_x509_verify NULL, // rsa_x509_verify_recover NULL, // rsa_oaep_decrypt NULL, // rsa_oaep_encrypt NULL, // rsa_pss_sign NULL, // rsa_pss_verify NULL, // rsa_generate_keypair // Elliptic Curve NULL, // ec_sign, NULL, // ec_verify NULL, // ec_generate_keypair // DH NULL, // dh_pkcs_derive, NULL, // dh_pkcs_key_pair_gen // SHA &token_specific_sha_init, &token_specific_sha, &token_specific_sha_update, &token_specific_sha_final, // HMAC NULL, // hmac_sign_init NULL, // hmac_sign NULL, // hmac_sign_update NULL, // hmac_sign_final NULL, // hmac_verify_init NULL, // hmac_verify NULL, // hmac_verify_update NULL, // hmac_verify_final NULL, // generic_secret_key_gen // AES NULL, // aes_key_gen, NULL, // aes_ecb, NULL, // aes_cbc, NULL, // aes_ctr NULL, // aes_gcm_init NULL, // aes_gcm NULL, // aes_gcm_update NULL, // aes_gcm_final NULL, // aes_ofb NULL, // aes_cfb NULL, // aes_mac // DSA NULL, // dsa_generate_keypair, NULL, // dsa_sign NULL, // dsa_verify NULL, // get_mechanism_list NULL, // get mechanism_info &token_specific_object_add }; #endif opencryptoki+dfsg/usr/lib/pkcs11/ep11_stdll/Makefile.am0000644000175000017500000000512012630407154021762 0ustar xnoxxnox# Makefile.am for EP11 token for openCryptoki # nobase_lib_LTLIBRARIES = opencryptoki/stdll/libpkcs11_ep11.la opencryptoki_stdll_libpkcs11_ep11_la_LDFLAGS = -shared -Wl,-Bsymbolic \ -lc -lpthread -lcrypto -lrt -llber # Not all versions of automake observe libname_CFLAGS opencryptoki_stdll_libpkcs11_ep11_la_CFLAGS = -DDEV -D_THREAD_SAFE \ -DSHALLOW=0 -DEPSWTOK=1 -DLITE=0 \ -DNOCDMF -DNOMD2 -DNORIPE \ -fPIC -O0 -DDEFENSIVE_MECHLIST \ -I/usr/include -I. \ -I../../../include/pkcs11/stdll \ -I../../../include/pkcs11 \ -I../common -DSTDLL_NAME=\"ep11tok\" opencryptoki_stdll_libpkcs11_ep11_la_SOURCES = ../common/asn1.c \ ../common/btree.c \ ../common/cert.c \ ../common/hwf_obj.c \ ../common/dp_obj.c \ ../common/data_obj.c \ ../common/dig_mgr.c \ ../common/globals.c \ ../common/loadsave.c \ ../common/mech_ec.c \ ../common/mech_md5.c \ ../common/mech_md2.c \ ../common/mech_rng.c \ ../common/mech_sha.c \ new_host.c \ ../common/obj_mgr.c \ ../common/object.c \ ../common/sess_mgr.c \ ../common/key.c \ ../common/template.c \ ../common/p11util.c \ ../common/utility.c \ ../common/trace.c \ ../common/shared_memory.c \ ../common/attributes.c \ ../common/sw_crypt.c \ ep11_specific.c noinst_HEADERS = ep11.h install-data-hook: cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ ln -sf libpkcs11_ep11.so PKCS11_EP11.so $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/opencryptoki/ep11tok/TOK_OBJ $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/ep11tok/TOK_OBJ $(CHGRP) pkcs11 $(DESTDIR)$(localstatedir)/lib/opencryptoki/ep11tok $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/ep11tok/TOK_OBJ $(CHMOD) 0770 $(DESTDIR)$(localstatedir)/lib/opencryptoki/ep11tok $(MKDIR_P) $(DESTDIR)$(lockdir)/ep11tok $(CHGRP) pkcs11 $(DESTDIR)$(lockdir)/ep11tok $(CHMOD) 0770 $(DESTDIR)$(lockdir)/ep11tok uninstall-hook: if test -d $(DESTDIR)$(libdir)/opencryptoki/stdll; then \ cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \ rm -f PKCS11_EP11.so; fi install-data-local : test -f $(DESTDIR)$(sysconfdir)/opencryptoki || $(MKDIR_P) $(DESTDIR)$(sysconfdir)/opencryptoki || true test -f $(DESTDIR)$(sysconfdir)/opencryptoki/ep11tok.conf || $(INSTALL) -m 644 $(srcdir)/ep11tok.conf $(DESTDIR)$(sysconfdir)/opencryptoki/ep11tok.conf || true opencryptoki+dfsg/usr/lib/pkcs11/ep11_stdll/new_host.c0000644000175000017500000027113212630407154021730 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2015 */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "pkcs11types.h" #include "stdll.h" #include "defs.h" #include "host_defs.h" #include "h_extern.h" #include "tok_spec_struct.h" #include "pkcs32.h" #include "trace.h" #include "ep11_specific.h" #include "../api/apiproto.h" /* Declared in obj_mgr.c */ extern pthread_rwlock_t obj_list_rw_mutex; void SC_SetFunctionList(void); CK_ULONG usage_count = 0; /* track DLL usage */ void Fork_Initializer(void) { /* Initialize spinlock. */ XProcLock_Init(); /* Force logout. This cleans out the private session and list * and cleans out the private object map */ session_mgr_logout_all(); /* Clean out the public object map * First parm is no longer used.. */ object_mgr_purge_map((SESSION *)0xFFFF, PUBLIC); object_mgr_purge_map((SESSION *)0xFFFF, PRIVATE); /* This should clear the entire session list out */ session_mgr_close_all_sessions(); /* Clean out the global login state variable * When implemented... Although logout_all should clear this up. */ bt_destroy(&priv_token_obj_btree, object_free); bt_destroy(&publ_token_obj_btree, object_free); /* Need to do something to prevent the shared memory from * having the objects loaded again.... The most likely place * is in the obj_mgr file where the object is added to shared * memory (object_mgr_add_to_shm) a query should be done to * the appropriate object list.... */ } /* verify that the mech specified is in the * mech list for this token... */ CK_RV valid_mech(CK_MECHANISM_PTR m, CK_FLAGS f) { CK_RV rc; CK_MECHANISM_INFO info; if (m) { memset(&info, 0, sizeof(info)); rc = ep11tok_get_mechanism_info(m->mechanism, &info); if (rc != CKR_OK || !(info.flags & (f))) return CKR_MECHANISM_INVALID; } return CKR_OK; } /* In an STDLL this is called once for each card in the system * therefore the initialized only flags certain one time things. */ CK_RV ST_Initialize(void **FunctionList, CK_SLOT_ID SlotNumber, char *conf_name, struct trace_handle_t t) { CK_RV rc = CKR_OK; if ((rc = check_user_and_group()) != CKR_OK) return rc; /* assume that the upper API prevents multiple calls of initialize * since that only happens on C_Initialize and that is the * resonsibility of the upper layer.. */ initialized = FALSE; /* So the rest of the code works correctly */ /* If we're not already initialized, grab the mutex and do the * initialization. Check to see if another thread did so while we * were waiting... * * One of the things we do during initialization is create the mutex * for PKCS#11 operations; until we do so, we have to use the native * mutex... */ if (pthread_mutex_lock(&native_mutex)) { rc = CKR_FUNCTION_FAILED; TRACE_ERROR("Failed to lock mutex.\n"); } /* SAB need to call Fork_Initializer here * instead of at the end of the loop... * it may also need to call destroy of the following 3 mutexes.. * it may not matter... */ Fork_Initializer(); /* set trace info */ set_trace(t); MY_CreateMutex(&pkcs_mutex); MY_CreateMutex(&obj_list_mutex); if (pthread_rwlock_init(&obj_list_rw_mutex, NULL)) { TRACE_ERROR("Mutex lock failed.\n"); } MY_CreateMutex(&sess_list_mutex); MY_CreateMutex(&login_mutex); /* Create lockfile */ if (CreateXProcLock() != CKR_OK) { TRACE_ERROR("Process lock failed.\n"); goto done; } init_data_store((char *)PK_DIR); /* Handle global initialization issues first if we have not * been initialized. */ if (initialized == FALSE) { rc = attach_shm(SlotNumber, &global_shm); if (rc != CKR_OK) { TRACE_ERROR("Could not attach to shared memory.\n"); goto done; } nv_token_data = &global_shm->nv_token_data; initialized = TRUE; SC_SetFunctionList(); rc = ep11tok_init(SlotNumber, conf_name); if (rc != 0) { *FunctionList = NULL; TRACE_DEVEL("Token Specific Init failed.\n"); goto done; } } rc = load_token_data(SlotNumber); if (rc != CKR_OK) { *FunctionList = NULL; TRACE_DEVEL("Failed to load token data.\n"); goto done; } /* no need to return error here, we load the token data we can * and syslog the rest */ load_public_token_objects(); XProcLock(); global_shm->publ_loaded = TRUE; XProcUnLock(); init_slotInfo(); usage_count++; (*FunctionList) = &function_list; done: if (pthread_mutex_unlock(&native_mutex)) { TRACE_ERROR("Failed to unlock mutex.\n"); rc = CKR_FUNCTION_FAILED; } return rc; } /* What does this really have to do in this new token... probably * need to close the adapters that are opened, and clear the other * stuff */ CK_RV SC_Finalize(CK_SLOT_ID sid) { CK_RV rc, rc_mutex; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } rc = MY_LockMutex(&pkcs_mutex); if (rc != CKR_OK) { TRACE_ERROR("Mutex lock failed.\n"); return rc; } /* If somebody else has taken care of things, leave... */ if (initialized == FALSE) { MY_UnlockMutex(&pkcs_mutex); TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } usage_count--; if (usage_count == 0) { initialized = FALSE; } session_mgr_close_all_sessions(); object_mgr_purge_token_objects(); detach_shm(); /* close spin lock file */ CloseXProcLock(); rc = ep11tok_final(); if (rc != CKR_OK) { TRACE_ERROR("Token specific final call failed.\n"); goto done; } done: rc_mutex = MY_UnlockMutex(&pkcs_mutex); if (rc_mutex != CKR_OK) { TRACE_ERROR("Mutex unlock failed.\n"); return rc_mutex; } return rc; } CK_RV SC_GetTokenInfo(CK_SLOT_ID sid, CK_TOKEN_INFO_PTR pInfo) { CK_RV rc = CKR_OK; time_t now; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto done; } copy_token_contents_sensibly(pInfo, nv_token_data); /* Set the time */ now = time ((time_t *)NULL); strftime((char *)pInfo->utcTime, 16, "%X", localtime(&now)); done: TRACE_INFO("C_GetTokenInfo: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } /* * Get the mechanism type list for the current token. */ CK_RV SC_GetMechanismList(CK_SLOT_ID sid, CK_MECHANISM_TYPE_PTR pMechList, CK_ULONG_PTR count) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto out; } if (count == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto out; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto out; } rc = ep11tok_get_mechanism_list(pMechList, count); if (rc == CKR_OK) { /* To accomodate certain special cases, we may need to * make adjustments to the token's mechanism list. */ mechanism_list_transformations(pMechList, count); } out: TRACE_INFO("C_GetMechanismList: rc = 0x%08lx, # mechanisms: %lu\n", rc, *count); return rc; } /* * Get the mechanism info for the current type and token. */ CK_RV SC_GetMechanismInfo(CK_SLOT_ID sid, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto out; } if (pInfo == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto out; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto out; } rc = ep11tok_get_mechanism_info(type, pInfo); out: TRACE_INFO("C_GetMechanismInfo: rc = 0x%08lx, mech type = 0x%08lx\n", rc, type); return rc; } /* * This routine should only be called if no other processes are * attached to the token. we need to somehow check that this is the * only process Meta API should prevent this since it knows session * states in the shared memory. */ CK_RV SC_InitToken(CK_SLOT_ID sid, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) { CK_RV rc = CKR_OK; CK_BYTE hash_sha[SHA1_HASH_SIZE]; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPin || !pLabel) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (nv_token_data->token_info.flags & CKF_SO_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } rc = compute_sha1(pPin, ulPinLen, hash_sha); if (memcmp(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* Before we reconstruct all the data, we should delete the * token objects from the filesystem. */ object_mgr_destroy_token_objects(); delete_token_data(); init_token_data(sid); init_slotInfo(); memcpy(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE); nv_token_data->token_info.flags |= CKF_TOKEN_INITIALIZED; memcpy(nv_token_data->token_info.label, pLabel, 32); rc = save_token_data(sid); if (rc != CKR_OK) { TRACE_DEVEL("Failed to save token data.\n"); goto done; } done: TRACE_INFO("C_InitToken: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_InitPIN(ST_SESSION_HANDLE *sSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { SESSION *sess = NULL; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_BYTE hash_md5[MD5_HASH_SIZE]; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPin) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_locked(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } if (sess->session_info.state != CKS_RW_SO_FUNCTIONS) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } if ((ulPinLen < MIN_PIN_LEN) || (ulPinLen > MAX_PIN_LEN)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LEN_RANGE)); rc = CKR_PIN_LEN_RANGE; goto done; } /* compute the SHA and MD5 hashes of the user pin */ rc = compute_sha1(pPin, ulPinLen, hash_sha); rc |= compute_md5( pPin, ulPinLen, hash_md5 ); if (rc != CKR_OK) { TRACE_ERROR("Failed to compute sha or md5 for user pin.\n"); goto done; } rc = XProcLock(); if (rc != CKR_OK) { TRACE_ERROR("Failed to get process lock.\n"); goto done; } memcpy(nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE); nv_token_data->token_info.flags |= CKF_USER_PIN_INITIALIZED; nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); nv_token_data->token_info.flags &= ~(CKF_USER_PIN_LOCKED); XProcUnLock(); memcpy(user_pin_md5, hash_md5, MD5_HASH_SIZE); rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) { TRACE_DEVEL("Failed to save token data.\n"); goto done; } rc = save_masterkey_user(); if (rc != CKR_OK) TRACE_DEVEL("Failed to save user's masterkey.\n"); done: TRACE_INFO("C_InitPin: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_SetPIN(ST_SESSION_HANDLE *sSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { SESSION *sess = NULL; CK_BYTE old_hash_sha[SHA1_HASH_SIZE]; CK_BYTE new_hash_sha[SHA1_HASH_SIZE]; CK_BYTE hash_md5[MD5_HASH_SIZE]; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_locked(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } /* Check if token has a specific handler for this, otherwise fall back * to default behaviour. */ if ((ulNewLen < MIN_PIN_LEN) || (ulNewLen > MAX_PIN_LEN)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LEN_RANGE)); rc = CKR_PIN_LEN_RANGE; goto done; } rc = compute_sha1(pOldPin, ulOldLen, old_hash_sha); if (rc != CKR_OK) { TRACE_ERROR("Failed to compute sha for old pin.\n"); goto done; } /* From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of * the user that is currently logged in, or the CKU_USER PIN * if the session is not logged in." A non R/W session fails * with CKR_SESSION_READ_ONLY. */ if ((sess->session_info.state == CKS_RW_USER_FUNCTIONS) || (sess->session_info.state == CKS_RW_PUBLIC_SESSION)) { if (memcmp(nv_token_data->user_pin_sha, old_hash_sha, SHA1_HASH_SIZE) != 0) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } rc = compute_sha1(pNewPin, ulNewLen, new_hash_sha); rc |= compute_md5(pNewPin, ulNewLen, hash_md5); if (rc != CKR_OK) { TRACE_ERROR("Failed to compute hash for new pin.\n"); goto done; } /* The old PIN matches, now make sure its different * than the new and is not the default. */ if ((memcmp(old_hash_sha, new_hash_sha, SHA1_HASH_SIZE) == 0) || (memcmp(new_hash_sha, default_user_pin_sha, SHA1_HASH_SIZE) == 0)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID)); rc = CKR_PIN_INVALID; goto done; } rc = XProcLock(); if (rc != CKR_OK) { TRACE_DEVEL("Failed to get process lock.\n"); goto done; } memcpy(nv_token_data->user_pin_sha, new_hash_sha, SHA1_HASH_SIZE); memcpy(user_pin_md5, hash_md5, MD5_HASH_SIZE); nv_token_data->token_info.flags &= ~(CKF_USER_PIN_TO_BE_CHANGED); XProcUnLock(); rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) { TRACE_DEVEL("Failed to save token data.\n"); goto done; } rc = save_masterkey_user(); } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { if (memcmp(nv_token_data->so_pin_sha, old_hash_sha, SHA1_HASH_SIZE) != 0) { rc = CKR_PIN_INCORRECT; TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); goto done; } rc = compute_sha1(pNewPin, ulNewLen, new_hash_sha); rc |= compute_md5(pNewPin, ulNewLen, hash_md5); if (rc != CKR_OK) { TRACE_ERROR("Failed to compute hash for new pin.\n"); goto done; } /* The old PIN matches, now make sure its different * than the new and is not the default. */ if ((memcmp(old_hash_sha, new_hash_sha, SHA1_HASH_SIZE) == 0) || (memcmp(new_hash_sha, default_so_pin_sha, SHA1_HASH_SIZE) == 0)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_INVALID)); rc = CKR_PIN_INVALID; goto done; } rc = XProcLock(); if (rc != CKR_OK) { TRACE_DEVEL("Failed to get process lock.\n"); goto done; } memcpy(nv_token_data->so_pin_sha, new_hash_sha, SHA1_HASH_SIZE); memcpy(so_pin_md5, hash_md5, MD5_HASH_SIZE); nv_token_data->token_info.flags &= ~(CKF_SO_PIN_TO_BE_CHANGED); XProcUnLock(); rc = save_token_data(sess->session_info.slotID); if (rc != CKR_OK) { TRACE_DEVEL("Failed to save token data.\n"); goto done; } rc = save_masterkey_so(); if (rc != CKR_OK) TRACE_DEVEL("Failed to save SO's masterkey.\n"); } else { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY)); rc = CKR_SESSION_READ_ONLY; } done: TRACE_INFO("C_SetPin: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_OpenSession(CK_SLOT_ID sid, CK_FLAGS flags, CK_SESSION_HANDLE_PTR phSession) { CK_BBOOL locked = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (phSession == NULL) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (sid > MAX_SLOT_ID) { TRACE_ERROR("%s\n", ock_err(ERR_SLOT_ID_INVALID)); rc = CKR_SLOT_ID_INVALID; goto done; } flags |= CKF_SERIAL_SESSION; if ((flags & CKF_RW_SESSION) == 0) { if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_WRITE_SO_EXISTS)); rc = CKR_SESSION_READ_WRITE_SO_EXISTS; goto done; } } /* Get the mutex because we may modify the pid_list */ rc = MY_LockMutex(&pkcs_mutex); if (rc != CKR_OK) { TRACE_ERROR("Failed to get mutex lock.\n"); goto done; } locked = TRUE; MY_UnlockMutex(&pkcs_mutex); locked = FALSE; rc = session_mgr_new(flags, sid, phSession); if (rc != CKR_OK) { TRACE_DEVEL("session_mgr_new() failed\n"); goto done; } done: if (locked) MY_UnlockMutex(&pkcs_mutex); TRACE_INFO("C_OpenSession: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_CloseSession(ST_SESSION_HANDLE *sSession) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } rc = session_mgr_close_session(sSession->sessionh); done: TRACE_INFO("C_CloseSession: rc = 0x%08lx sess = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_CloseAllSessions(CK_SLOT_ID sid) { CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } rc = session_mgr_close_all_sessions(); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_close_all_sessions() failed.\n"); done: TRACE_INFO("C_CloseAllSessions: rc = 0x%08lx slot = %lu\n", rc, sid); return rc; } CK_RV SC_GetSessionInfo(ST_SESSION_HANDLE *sSession, CK_SESSION_INFO_PTR pInfo) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pInfo) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } memcpy(pInfo, &sess->session_info, sizeof(CK_SESSION_INFO)); done: TRACE_INFO("C_GetSessionInfo: session = %lu\n", sSession->sessionh); return rc; } CK_RV SC_GetOperationState(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulOperationStateLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } if (!pOperationState) length_only = TRUE; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = session_mgr_get_op_state(sess, length_only, pOperationState, pulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_get_op_state() failed.\n"); done: TRACE_INFO("C_GetOperationState: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_SetOperationState(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pOperationState || (ulOperationStateLen == 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey, pOperationState, ulOperationStateLen); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_set_op_state() failed.\n"); done: TRACE_INFO("C_SetOperationState: rc = 0x%08lx, session = %lu\n", rc, sSession->sessionh); return rc; } CK_RV SC_Login(ST_SESSION_HANDLE *sSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { SESSION *sess = NULL; CK_FLAGS_32 *flags = NULL; CK_BYTE hash_sha[SHA1_HASH_SIZE]; CK_RV rc = CKR_OK; /* In v2.11, logins should be exclusive, since token * specific flags may need to be set for a bad login. - KEY */ rc = MY_LockMutex(&login_mutex); if (rc != CKR_OK) { TRACE_ERROR("Failed to get mutex lock.\n"); return CKR_FUNCTION_FAILED; } if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } flags = &nv_token_data->token_info.flags; if (!pPin || ulPinLen > MAX_PIN_LEN) { set_login_flags(userType, flags); TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* PKCS #11 v2.01 requires that all sessions have the same login status: * --> all sessions are public, all are SO or all are USER */ if (userType == CKU_USER) { if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_ANOTHER_ALREADY_LOGGED_IN)); rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } if (session_mgr_user_session_exists()) { TRACE_ERROR("%s\n",ock_err(ERR_USER_ALREADY_LOGGED_IN)); rc = CKR_USER_ALREADY_LOGGED_IN; } } else if (userType == CKU_SO) { if (session_mgr_user_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_ANOTHER_ALREADY_LOGGED_IN)); rc = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; } if (session_mgr_so_session_exists()) { TRACE_ERROR("%s\n",ock_err(ERR_USER_ALREADY_LOGGED_IN)); rc = CKR_USER_ALREADY_LOGGED_IN; } if (session_mgr_readonly_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY_EXISTS)); rc = CKR_SESSION_READ_ONLY_EXISTS; } } else { rc = CKR_USER_TYPE_INVALID; TRACE_ERROR("%s\n", ock_err(ERR_USER_TYPE_INVALID)); } if (rc != CKR_OK) goto done; if (userType == CKU_USER) { if (*flags & CKF_USER_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } if (memcmp(nv_token_data->user_pin_sha, "00000000000000000000", SHA1_HASH_SIZE) == 0) { TRACE_ERROR("%s\n", ock_err(ERR_USER_PIN_NOT_INITIALIZED)); rc = CKR_USER_PIN_NOT_INITIALIZED; goto done; } rc = compute_sha1(pPin, ulPinLen, hash_sha); if (memcmp(nv_token_data->user_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { set_login_flags(userType, flags); TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* Successful login, clear flags */ *flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_COUNT_LOW); compute_md5( pPin, ulPinLen, user_pin_md5 ); memset( so_pin_md5, 0x0, MD5_HASH_SIZE ); rc = load_masterkey_user(); if (rc != CKR_OK){ TRACE_DEVEL("Failed to load user's masterkey.\n"); goto done; } /* no need to return error here, we load the token data * we can and syslog the rest */ load_private_token_objects(); XProcLock(); global_shm->priv_loaded = TRUE; XProcUnLock(); } else { if (*flags & CKF_SO_PIN_LOCKED) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_LOCKED)); rc = CKR_PIN_LOCKED; goto done; } rc = compute_sha1(pPin, ulPinLen, hash_sha); if (memcmp(nv_token_data->so_pin_sha, hash_sha, SHA1_HASH_SIZE) != 0) { set_login_flags(userType, flags); TRACE_ERROR("%s\n", ock_err(ERR_PIN_INCORRECT)); rc = CKR_PIN_INCORRECT; goto done; } /* Successful login, clear flags */ *flags &= ~(CKF_SO_PIN_LOCKED | CKF_SO_PIN_FINAL_TRY | CKF_SO_PIN_COUNT_LOW); compute_md5(pPin, ulPinLen, so_pin_md5); memset(user_pin_md5, 0x0, MD5_HASH_SIZE); rc = load_masterkey_so(); if (rc != CKR_OK) TRACE_DEVEL("Failed to load SO's masterkey.\n"); } done: if (rc == CKR_OK) { rc = session_mgr_login_all(userType); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_login_all failed.\n"); } TRACE_INFO("C_Login: rc = 0x%08lx\n", rc); save_token_data(sess->session_info.slotID); MY_UnlockMutex(&login_mutex); return rc; } CK_RV SC_Logout(ST_SESSION_HANDLE *sSession) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } /* all sessions have the same state so we just have to check one */ if (session_mgr_public_session_exists()) { TRACE_ERROR("%s\n", ock_err(ERR_USER_NOT_LOGGED_IN)); rc = CKR_USER_NOT_LOGGED_IN; goto done; } rc = session_mgr_logout_all(); if (rc != CKR_OK) TRACE_DEVEL("session_mgr_logout_all failed.\n"); memset(user_pin_md5, 0x0, MD5_HASH_SIZE); memset(so_pin_md5, 0x0, MD5_HASH_SIZE); object_mgr_purge_private_token_objects(); done: TRACE_INFO("C_Logout: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_CreateObject(ST_SESSION_HANDLE *sSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags)) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_add(sess, pTemplate, ulCount, phObject); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_add() failed.\n"); done: TRACE_INFO("C_CreateObject: rc = 0x%08lx\n", rc); #ifdef DEBUG int i; for (i = 0; i < ulCount; i++) { if (pTemplate[i].type == CKA_CLASS) { TRACE_DEBUG("Object Type: 0x%02lx\n", *((CK_ULONG *) pTemplate[i].pValue)); } } if (rc == CKR_OK) TRACE_DEBUG("Handle: %lu\n", *phObject); #endif return rc; } CK_RV SC_CopyObject(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_copy(sess, pTemplate, ulCount, hObject, phNewObject); if (rc != CKR_OK) TRACE_DEVEL("object_mgr_copy() failed\n"); done: TRACE_INFO("C_CopyObject:rc = 0x%08lx,old handle = %lu, " "new handle = %lu\n", rc, hObject, *phNewObject); return rc; } CK_RV SC_DestroyObject(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = object_mgr_destroy_object(sess, hObject); if (rc != CKR_OK) TRACE_DEVEL("*_destroy_object() failed\n"); done: TRACE_INFO("C_DestroyObject: rc = 0x%08lx, handle = %lu\n", rc, hObject); return rc; } CK_RV SC_GetObjectSize(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_get_object_size(hObject, pulSize); if (rc != CKR_OK) TRACE_ERROR("object_mgr_get_object_size() failed.\n"); done: TRACE_INFO("C_GetObjectSize: rc = 0x%08lx, handle = %lu\n", rc, hObject); return rc; } CK_RV SC_GetAttributeValue(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_get_attribute_values(sess, hObject, pTemplate, ulCount); if (rc != CKR_OK) TRACE_DEVEL("obj_mgr_get_attribute_value() failed.\n"); done: TRACE_INFO("C_GetAttributeValue: rc = 0x%08lx, handle = %lu\n", rc, hObject); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; CK_BYTE *ptr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_SetAttributeValue(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = object_mgr_set_attribute_values(sess, hObject, pTemplate, ulCount); if (rc != CKR_OK) TRACE_DEVEL("obj_mgr_set_attribute_values() failed.\n"); done: TRACE_INFO("C_SetAttributeValue: rc = 0x%08lx, handle = %lu\n", rc, hObject); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_FindObjectsInit(ST_SESSION_HANDLE *sSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->find_active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = object_mgr_find_init(sess, pTemplate, ulCount); done: TRACE_INFO("C_FindObjectsInit: rc = 0x%08lx\n", rc); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_FindObjects(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { SESSION *sess = NULL; CK_ULONG count = 0; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!phObject || !pulObjectCount) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->find_active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!sess->find_list) { TRACE_DEVEL("sess->find_list is NULL.\n"); rc = CKR_FUNCTION_FAILED; goto done; } count = MIN(ulMaxObjectCount, (sess->find_count - sess->find_idx)); memcpy(phObject, sess->find_list + sess->find_idx, count * sizeof(CK_OBJECT_HANDLE)); *pulObjectCount = count; sess->find_idx += count; rc = CKR_OK; done: TRACE_INFO("C_FindObjects: rc = 0x%08lx, returned %lu objects\n", rc, count); return rc; } CK_RV SC_FindObjectsFinal(ST_SESSION_HANDLE *sSession) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->find_active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (sess->find_list) free(sess->find_list); sess->find_list = NULL; sess->find_len = 0; sess->find_idx = 0; sess->find_active = FALSE; rc = CKR_OK; done: TRACE_INFO("C_FindObjectsFinal: rc = 0x%08lx\n", rc); return rc; } CK_RV SC_EncryptInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_ENCRYPT); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->encr_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = ep11tok_encrypt_init(sess, pMechanism, hKey); done: TRACE_INFO("C_EncryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Encrypt(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pulEncryptedDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pEncryptedData) length_only = TRUE; rc = ep11tok_encrypt(sess, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_encrypt() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_EncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if ((!pPart && ulPartLen != 0) || !pulEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = ep11tok_encrypt_update(sess, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_encrypt_update() failed.\n"); done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen); return rc; } CK_RV SC_EncryptFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulLastEncryptedPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->encr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pLastEncryptedPart) length_only = TRUE; rc = ep11tok_encrypt_final(sess, pLastEncryptedPart, pulLastEncryptedPartLen); if (rc != CKR_OK) TRACE_ERROR("ep11tok_encrypt_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) encr_mgr_cleanup( &sess->encr_ctx ); TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle); return rc; } CK_RV SC_DecryptInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DECRYPT); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->decr_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = ep11tok_decrypt_init(sess, pMechanism, hKey); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_decrypt_init() failed.\n"); done: TRACE_INFO("C_DecryptInit: rc = 0x%08lx, sess = %ld, mech = 0x%lx\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Decrypt(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pEncryptedData || !pulDataLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pData) length_only = TRUE; rc = ep11tok_decrypt(sess, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_decrypt() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulEncryptedDataLen); return rc; } CK_RV SC_DecryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if ((!pEncryptedPart && ulEncryptedPartLen != 0) || !pulPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = ep11tok_decrypt_update(sess, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_decrypt_update() failed.\n"); done: if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, ulEncryptedPartLen); return rc; } CK_RV SC_DecryptFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulLastPartLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->decr_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pLastPart) length_only = TRUE; rc = ep11tok_decrypt_final(sess, pLastPart, pulLastPartLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_decrypt_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) decr_mgr_cleanup( &sess->decr_ctx ); TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG)sess->handle, *pulLastPartLen); return rc; } CK_RV SC_DigestInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DIGEST); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->digest_ctx.active == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto done; } rc = digest_mgr_init(sess, &sess->digest_ctx, pMechanism); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_init() failed.\n"); done: TRACE_INFO("C_DigestInit: rc = 0x%08lx, sess = %ld, mech = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Digest(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } /* Netscape has been known to pass a null pData to DigestUpdate * but never for Digest. It doesn't really make sense to allow it here */ if (!pData || !pulDigestLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pDigest) length_only = TRUE; rc = digest_mgr_digest(sess, length_only, &sess->digest_ctx, pData, ulDataLen, pDigest, pulDigestLen); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest() failed.\n"); done: TRACE_INFO("C_Digest: rc = 0x%08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_DigestUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } /* If there is data to hash, do so. */ if (ulPartLen) { rc = digest_mgr_digest_update(sess, &sess->digest_ctx, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest_update() failed.\n"); } done: TRACE_INFO("C_DigestUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_DigestKey(ST_SESSION_HANDLE *sSession, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = digest_mgr_digest_key(sess, &sess->digest_ctx, hKey); if (rc != CKR_OK) TRACE_DEVEL("digest_mgr_digest_key() failed.\n"); done: TRACE_INFO("C_DigestKey: rc = %08lx, sess = %ld, key = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, hKey); return rc; } CK_RV SC_DigestFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulDigestLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->digest_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pDigest) length_only = TRUE; rc = digest_mgr_digest_final(sess, length_only, &sess->digest_ctx, pDigest, pulDigestLen); if (rc != CKR_OK) TRACE_ERROR("digest_mgr_digest_final() failed.\n"); done: TRACE_INFO("C_DigestFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_SignInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism ) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = valid_mech(pMechanism, CKF_SIGN); if (rc != CKR_OK) goto done; if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->sign_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); goto done; } rc = ep11tok_sign_init(sess, pMechanism, FALSE, hKey); if (rc != CKR_OK) TRACE_DEVEL("*_sign_init() failed.\n"); done: TRACE_INFO("C_SignInit: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Sign(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pSignature) length_only = TRUE; rc = ep11tok_sign(sess, length_only, pData, ulDataLen, pSignature, pulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_sign() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_Sign: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_SignUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } rc = ep11tok_sign_update(sess, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_sign_update() failed.\n"); done: if (rc != CKR_OK) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_SignFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { SESSION *sess = NULL; CK_BBOOL length_only = FALSE; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pulSignatureLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->sign_ctx.active == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); rc = CKR_OPERATION_NOT_INITIALIZED; goto done; } if (!pSignature) length_only = TRUE; rc = ep11tok_sign_final(sess, length_only, pSignature, pulSignatureLen); if (rc != CKR_OK) TRACE_ERROR("ep11tok_sign_final() failed.\n"); done: if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) sign_mgr_cleanup(&sess->sign_ctx); TRACE_INFO("C_SignFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_SignRecoverInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_SignRecover(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_VerifyInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism ) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_VERIFY); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } if (sess->verify_ctx.active == TRUE) { rc = CKR_OPERATION_ACTIVE; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); goto done; } rc = ep11tok_verify_init(sess, pMechanism, FALSE, hKey); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_verify_init() failed.\n"); done: TRACE_INFO("C_VerifyInit: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); return rc; } CK_RV SC_Verify(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pData || !pSignature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = ep11tok_verify(sess, pData, ulDataLen, pSignature, ulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_verify() failed.\n"); done: verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_Verify: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulDataLen); return rc; } CK_RV SC_VerifyUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pPart && ulPartLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = ep11tok_verify_update(sess, pPart, ulPartLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_verify_update() failed.\n"); done: if (rc != CKR_OK) verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyUpdate: rc = %08lx, sess = %ld, datalen = %lu\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, ulPartLen); return rc; } CK_RV SC_VerifyFinal(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pSignature) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (sess->verify_ctx.active == FALSE) { rc = CKR_OPERATION_NOT_INITIALIZED; TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); goto done; } rc = ep11tok_verify_final(sess, pSignature, ulSignatureLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_verify_final() failed.\n"); done: verify_mgr_cleanup(&sess->verify_ctx); TRACE_INFO("C_VerifyFinal: rc = %08lx, sess = %ld\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle); return rc; } CK_RV SC_VerifyRecoverInit(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_VerifyRecover(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_DigestEncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_DecryptDigestUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_SignEncryptUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_DecryptVerifyUpdate(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED)); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV SC_GenerateKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !phKey || (pTemplate == NULL && ulCount != 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_GENERATE); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = ep11tok_generate_key(sess, pMechanism, pTemplate, ulCount, phKey); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_generate_key() failed.\n"); done: TRACE_INFO("C_GenerateKey: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, pMechanism->mechanism); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx,Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) { TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } } #endif return rc; } CK_RV SC_GenerateKeyPair(ST_SESSION_HANDLE *sSession, 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) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !phPublicKey || !phPrivateKey || (!pPublicKeyTemplate && (ulPublicKeyAttributeCount != 0)) || (!pPrivateKeyTemplate && (ulPrivateKeyAttributeCount != 0))) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_GENERATE_KEY_PAIR); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = ep11tok_generate_key_pair(sess, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_generate_key_pair() failed.\n"); done: TRACE_INFO("C_GenerateKeyPair: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL) ? -1 : ((CK_LONG) sess->handle), pMechanism->mechanism); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; int i; if (rc == CKR_OK) { TRACE_DEBUG("Public handle: %lu, Private handle: %lu\n", *phPublicKey, *phPrivateKey); } TRACE_DEBUG("Public Template:\n"); attr = pPublicKeyTemplate; for (i = 0; i < ulPublicKeyAttributeCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } TRACE_DEBUG("Private Template:\n"); attr = pPublicKeyTemplate; for (i = 0; i < ulPublicKeyAttributeCount; i++, attr++) { CK_BYTE *ptr = (CK_BYTE *) attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_WrapKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !pulWrappedKeyLen) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_WRAP); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = ep11tok_wrap_key(sess, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_wrap_key() failed.\n"); done: TRACE_INFO("C_WrapKey: rc = %08lx, sess = %ld, encrypting key = %lu, " "wrapped key = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, hWrappingKey, hKey); return rc; } CK_RV SC_UnwrapKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !pWrappedKey || (!pTemplate && ulCount != 0) || !phKey) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_UNWRAP); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = ep11tok_unwrap_key(sess, pMechanism, pTemplate, ulCount, pWrappedKey, ulWrappedKeyLen, hUnwrappingKey, phKey); if (rc != CKR_OK) TRACE_DEVEL("ep11tok_unwrap_key() failed.\n"); done: TRACE_INFO("C_UnwrapKey: rc = %08lx, sess = %ld, decrypting key = %lu," "unwrapped key = %lu\n", rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, hUnwrappingKey, *phKey); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; CK_BYTE *ptr = NULL; int i; attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != ((CK_ULONG) -1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif return rc; } CK_RV SC_DeriveKey(ST_SESSION_HANDLE *sSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pMechanism || !phKey || (!pTemplate && ulCount != 0)) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } rc = valid_mech(pMechanism, CKF_DERIVE); if (rc != CKR_OK) goto done; sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } if (pin_expired(&sess->session_info, nv_token_data->token_info.flags) == TRUE) { TRACE_ERROR("%s\n", ock_err(ERR_PIN_EXPIRED)); rc = CKR_PIN_EXPIRED; goto done; } rc = ep11tok_derive_key(sess, pMechanism, hBaseKey, phKey, pTemplate, ulCount); if (rc != CKR_OK) TRACE_DEVEL("epl11tok_derive_key() failed.\n"); done: TRACE_INFO("C_DeriveKey: rc = %08lx, sess = %ld, mech = %lx\n", rc, (sess == NULL)?-1:(CK_LONG)sess->handle, pMechanism->mechanism); #ifdef DEBUG CK_ATTRIBUTE *attr = NULL; CK_BYTE *ptr = NULL; int i; if (rc == CKR_OK) { switch (pMechanism->mechanism) { case CKM_SSL3_KEY_AND_MAC_DERIVE: { CK_SSL3_KEY_MAT_PARAMS *pReq; CK_SSL3_KEY_MAT_OUT *pPtr; pReq = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; pPtr = pReq->pReturnedKeyMaterial; TRACE_DEBUG("Client MAC key: %lu, Server MAC key: %lu, " "Client Key: %lu, Server Key: %lu\n", pPtr->hClientMacSecret, pPtr->hServerMacSecret, pPtr->hClientKey, pPtr->hServerKey); } break; case CKM_DH_PKCS_DERIVE: { TRACE_DEBUG("DH Shared Secret:\n"); } break ; default: TRACE_DEBUG("Derived key: %lu\n", *phKey); } } attr = pTemplate; for (i = 0; i < ulCount; i++, attr++) { ptr = (CK_BYTE *)attr->pValue; TRACE_DEBUG("%d: Attribute type: 0x%08lx, Value Length: %lu\n", i, attr->type, attr->ulValueLen); if (attr->ulValueLen != (CK_ULONG)(-1) && (ptr != NULL)) TRACE_DEBUG("First 4 bytes: %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3]); } #endif /* DEBUG */ return rc; } CK_RV SC_SeedRandom(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_RANDOM_SEED_NOT_SUPPORTED)); return CKR_RANDOM_SEED_NOT_SUPPORTED; } CK_RV SC_GenerateRandom(ST_SESSION_HANDLE *sSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) { SESSION *sess = NULL; CK_RV rc = CKR_OK; if (initialized == FALSE) { TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); rc = CKR_CRYPTOKI_NOT_INITIALIZED; goto done; } if (!pRandomData && ulRandomLen != 0) { TRACE_ERROR("%s\n", ock_err(ERR_ARGUMENTS_BAD)); rc = CKR_ARGUMENTS_BAD; goto done; } sess = session_mgr_find(sSession->sessionh); if (!sess) { TRACE_ERROR("%s\n", ock_err(ERR_SESSION_HANDLE_INVALID)); rc = CKR_SESSION_HANDLE_INVALID; goto done; } rc = rng_generate(pRandomData, ulRandomLen); if (rc != CKR_OK) TRACE_DEVEL("rng_generate() failed.\n"); done: TRACE_INFO("C_GenerateRandom:rc = %08lx, %lu bytes\n", rc, ulRandomLen); return rc; } CK_RV SC_GetFunctionStatus(ST_SESSION_HANDLE *sSession) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL)); return CKR_FUNCTION_NOT_PARALLEL; } CK_RV SC_CancelFunction(ST_SESSION_HANDLE *sSession) { if (initialized == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_CRYPTOKI_NOT_INITIALIZED)); return CKR_CRYPTOKI_NOT_INITIALIZED; } TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_PARALLEL)); return CKR_FUNCTION_NOT_PARALLEL; } void SC_SetFunctionList(void) { function_list.ST_Initialize = (void *)ST_Initialize; function_list.ST_GetTokenInfo = SC_GetTokenInfo; function_list.ST_GetMechanismList = SC_GetMechanismList; function_list.ST_GetMechanismInfo = SC_GetMechanismInfo; function_list.ST_InitToken = SC_InitToken; function_list.ST_InitPIN = SC_InitPIN; function_list.ST_SetPIN = SC_SetPIN; function_list.ST_OpenSession = SC_OpenSession; function_list.ST_CloseSession = SC_CloseSession; function_list.ST_GetSessionInfo = SC_GetSessionInfo; function_list.ST_GetOperationState = SC_GetOperationState; function_list.ST_SetOperationState = SC_SetOperationState; function_list.ST_Login = SC_Login; function_list.ST_Logout = SC_Logout; function_list.ST_CreateObject = SC_CreateObject; function_list.ST_CopyObject = SC_CopyObject; function_list.ST_DestroyObject = SC_DestroyObject; function_list.ST_GetObjectSize = SC_GetObjectSize; function_list.ST_GetAttributeValue = SC_GetAttributeValue; function_list.ST_SetAttributeValue = SC_SetAttributeValue; function_list.ST_FindObjectsInit = SC_FindObjectsInit; function_list.ST_FindObjects = SC_FindObjects; function_list.ST_FindObjectsFinal = SC_FindObjectsFinal; function_list.ST_EncryptInit = SC_EncryptInit; function_list.ST_Encrypt = SC_Encrypt; function_list.ST_EncryptUpdate = SC_EncryptUpdate; function_list.ST_EncryptFinal = SC_EncryptFinal; function_list.ST_DecryptInit = SC_DecryptInit; function_list.ST_Decrypt = SC_Decrypt; function_list.ST_DecryptUpdate = SC_DecryptUpdate; function_list.ST_DecryptFinal = SC_DecryptFinal; function_list.ST_DigestInit = SC_DigestInit; function_list.ST_Digest = SC_Digest; function_list.ST_DigestUpdate = SC_DigestUpdate; function_list.ST_DigestKey = SC_DigestKey; function_list.ST_DigestFinal = SC_DigestFinal; function_list.ST_SignInit = SC_SignInit; function_list.ST_Sign = SC_Sign; function_list.ST_SignUpdate = SC_SignUpdate; function_list.ST_SignFinal = SC_SignFinal; function_list.ST_SignRecoverInit = SC_SignRecoverInit; function_list.ST_SignRecover = SC_SignRecover; function_list.ST_VerifyInit = SC_VerifyInit; function_list.ST_Verify = SC_Verify; function_list.ST_VerifyUpdate = SC_VerifyUpdate; function_list.ST_VerifyFinal = SC_VerifyFinal; function_list.ST_VerifyRecoverInit = SC_VerifyRecoverInit; function_list.ST_VerifyRecover = SC_VerifyRecover; function_list.ST_DigestEncryptUpdate = NULL; // SC_DigestEncryptUpdate; function_list.ST_DecryptDigestUpdate = NULL; // SC_DecryptDigestUpdate; function_list.ST_SignEncryptUpdate = NULL; //SC_SignEncryptUpdate; function_list.ST_DecryptVerifyUpdate = NULL; // SC_DecryptVerifyUpdate; function_list.ST_GenerateKey = SC_GenerateKey; function_list.ST_GenerateKeyPair = SC_GenerateKeyPair; function_list.ST_WrapKey = SC_WrapKey; function_list.ST_UnwrapKey = SC_UnwrapKey; function_list.ST_DeriveKey = SC_DeriveKey; function_list.ST_SeedRandom = SC_SeedRandom ; function_list.ST_GenerateRandom = SC_GenerateRandom; function_list.ST_GetFunctionStatus = NULL; // SC_GetFunctionStatus; function_list.ST_CancelFunction = NULL; // SC_CancelFunction; } opencryptoki+dfsg/usr/Makefile.am0000644000175000017500000000041112630407153016137 0ustar xnoxxnoxif ENABLE_DAEMON DAEMONDIRS = include sbin endif SUBDIRS = lib $(DAEMONDIRS) install-data-hook: $(MKDIR_P) $(DESTDIR)$(lockdir) $(DESTDIR)$(logdir) $(CHGRP) pkcs11 $(DESTDIR)$(lockdir) $(DESTDIR)$(logdir) $(CHMOD) 0770 $(DESTDIR)$(lockdir) $(DESTDIR)$(logdir) opencryptoki+dfsg/usr/include/0000755000175000017500000000000012630407153015532 5ustar xnoxxnoxopencryptoki+dfsg/usr/include/Makefile.am0000644000175000017500000000002112630407153017557 0ustar xnoxxnoxSUBDIRS = pkcs11 opencryptoki+dfsg/usr/include/pkcs11/0000755000175000017500000000000012630407154016635 5ustar xnoxxnoxopencryptoki+dfsg/usr/include/pkcs11/local_types.h0000755000175000017500000004016712630407154021337 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/local_types.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef __LOCAL_TYPES #define __LOCAL_TYPES typedef unsigned char uint8; typedef unsigned short uint16; // typedef short int16; typedef unsigned int uint32; // typedef int int32; #define BT_FLAG_FREE 1 /* Binary tree node * - 20 bytes on 32bit platform * - 40 bytes on 64bit platform */ struct btnode { struct btnode *left; struct btnode *right; struct btnode *parent; unsigned long flags; void *value; }; /* Binary tree root */ struct btree { struct btnode *free_list; struct btnode *top; unsigned long size; unsigned long free_nodes; }; struct btnode *bt_get_node(struct btree *t, unsigned long node_num); void *bt_get_node_value(struct btree *t, unsigned long node_num); inline int bt_is_empty(struct btree *t); void bt_for_each_node(struct btree *t, void (*)(void *, unsigned long, void *), void *); unsigned long bt_nodes_in_use(struct btree *t); unsigned long bt_node_add(struct btree *t, void *value); struct btnode *bt_node_free(struct btree *t, unsigned long node_num, void (*delete_func)(void *)); void bt_destroy(struct btree *t, void (*func)(void *)); #endif opencryptoki+dfsg/usr/include/pkcs11/pkcs11types.h0000755000175000017500000023163012630407154021205 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/pkcs11types.h,v 1.5 2007/12/05 22:52:01 mhalcrow Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ //---------------------------------------------------------------------------- // // File: PKCS11Types.h // // //---------------------------------------------------------------------------- #ifndef _PKCS11TYPES_H_ #define _PKCS11TYPES_H_ #ifdef __cplusplus extern "C" { #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE (!FALSE) #endif // AIX Addition for 64Bit work. // All types are 32bit types, therefore the longs have to be // typedefed to be 32bit values. typedef unsigned int uint_32; typedef int int_32; #define CK_PTR * #define CK_CALLBACK_FUNCTION(returnType, name) \ returnType (* name) #ifndef NULL_PTR #define NULL_PTR ((void *) NULL) #endif /* NULL_PTR */ /* 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 { CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ CK_CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; /* must be zero */ /* libraryDescription and libraryVersion are new for v2.0 */ CK_CHAR 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 { CK_CHAR slotDescription[64]; /* blank padded */ CK_CHAR 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 { CK_CHAR label[32]; /* blank padded */ CK_CHAR manufacturerID[32]; /* blank padded */ CK_CHAR 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 is new for v2.11. If it is true, the * token has been initialized using C_InitializeToken or an * equivalent mechanism outside the scope of this standard. * Calling C_InitializeToken when this flag is set will cause * the token to be reinitialized. */ #define CKF_TOKEN_INITIALIZED 0x00000400 /* CKF_SECONDARY_AUTHENTICATION is new for v2.11. If it is * true, the token supports secondary authentication for private * key objects. According to the 2.11 spec pg. 45, this flag * is deprecated and this flags should never be true. */ #define CKF_SECONDARY_AUTHENTICATION 0x00000800 /* CKF_USER_PIN_COUNT_LOW is new in v2.11. This flag is true * is an incorrect user PIN has been entered at least once * since the last successful authentication. */ #define CKF_USER_PIN_COUNT_LOW 0x00010000 /* CKF_USER_PIN_FINAL_TRY is new in v2.11. This flag is true if * supplying an incorrect user PIN will cause it to become * locked. */ #define CKF_USER_PIN_FINAL_TRY 0x00020000 /* CKF_USER_PIN_LOCKED is new in v2.11. This is true if 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 is new in v2.11. This flag is * true if the user PIN value is the default value set by * token initialization of manufacturing, or the PIN has * been expired by the card. */ #define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 /* CKF_SO_PIN_COUNT_LOW is new in v2.11. This flag is true if * and 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 is new in v2.11. This flag is true if * supplying an incorrect SO PIN will cause it to become * locked. */ #define CKF_SO_PIN_FINAL_TRY 0x00200000 /* CKF_SO_PIN_LOCKED is new in v2.11. This flag is true if * the SO PIN has been locked. User login to the token is not * possible. */ #define CKF_SO_PIN_LOCKED 0x00400000 /* CKF_SO_PIN_TO_BE_CHANGED is new in v2.11. This flag is true * if the SO PIN calue is the default value set by token init- * ialization of manufacturing, or the PIN has been expired by * the card. */ #define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 #if 0 /* IBM extended Token Info Flags - defined by Michael Hamann */ /* These Flags are not part of PKCS#11 Version 2.01 */ /* This will be used to track the state of login retries */ #define CKF_USER_PIN_COUNT_LOW 0x00010000 #define CKF_USER_PIN_FINAL_TRY 0x00020000 #define CKF_USER_PIN_LOCKED 0x00040000 #define CKF_USER_PIN_MANUFACT_VALUE 0x00080000 #define CKF_SO_PIN_COUNT_LOW 0x00100000 #define CKF_SO_PIN_FINAL_TRY 0x00200000 #define CKF_SO_PIN_LOCKED 0x00400000 #define CKF_SO_PIN_MANUFACT_VALUE 0x00800000 #endif /* other IBM extended Token info Flags 05/29/99 */ #define CKF_SO_PIN_DERIVED 0x01000000 // Sec Officer pin on card is derived from card id #define CKF_SO_CARD 0x02000000 // Security Officer Card /* End of IBM extented Token Info Flags */ 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 /* 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: */ #define CKO_DATA 0x00000000 #define CKO_CERTIFICATE 0x00000001 #define CKO_PUBLIC_KEY 0x00000002 #define CKO_PRIVATE_KEY 0x00000003 #define CKO_SECRET_KEY 0x00000004 /* CKO_HW_FEATURE and CKO_DOMAIN_PARAMETERS are new for v2.11 */ #define CKO_HW_FEATURE 0x00000005 #define CKO_DOMAIN_PARAMETERS 0x00000006 #define CKO_VENDOR_DEFINED 0x80000000 typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; /* CK_HW_FEATURE_TYPE is a value that identifies a hardware * feature type of a device. This is new for v2.11. */ typedef CK_ULONG CK_HW_FEATURE_TYPE; /* The following hardware feature types are defined: */ #define CKH_MONOTONIC_COUNTER 0x00000001 #define CKH_CLOCK 0x00000002 #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 /* CAST128=CAST5 */ #define CKK_RC5 0x00000019 #define CKK_IDEA 0x0000001A #define CKK_SKIPJACK 0x0000001B #define CKK_BATON 0x0000001C #define CKK_JUNIPER 0x0000001D #define CKK_CDMF 0x0000001E /* CKK_AES is new for v2.11 */ #define CKK_AES 0x0000001F #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: */ #define CKC_X_509 0x00000000 /* CKC_X_509_ATTR_CERT is new for v2.11 */ #define CKC_X_509_ATTR_CERT 0x00000001 #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 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.11 */ #define CKA_OBJECT_ID 0x00000012 #define CKA_CERTIFICATE_TYPE 0x00000080 #define CKA_ISSUER 0x00000081 #define CKA_SERIAL_NUMBER 0x00000082 /* CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES and CKA_TRUSTED * are new for v2.11 */ #define CKA_AC_ISSUER 0x00000083 #define CKA_OWNER 0x00000084 #define CKA_ATTR_TYPES 0x00000085 #define CKA_TRUSTED 0x00000086 #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_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 /* The following are new for v2.11 */ #define CKA_SECONDARY_AUTH 0x00000200 #define CKA_AUTH_PIN_FLAGS 0x00000201 #define CKA_HW_FEATURE_TYPE 0x00000300 #define CKA_RESET_ON_INIT 0x00000301 #define CKA_HAS_RESET 0x00000302 #define CKA_VENDOR_DEFINED 0x80000000 /* For use in storing objects that have an encrypted or otherwise * opaque attribute. Support has been added to use this attribute * in key objects only. */ #define CKA_IBM_OPAQUE CKA_VENDOR_DEFINED + 1 /* 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 /* The following are new for v2.11: */ #define CKM_RIPEMD128_RSA_PKCS 0x00000007 #define CKM_RIPEMD160_RSA_PKCS 0x00000008 #define CKM_RSA_PKCS_OAEP 0x00000009 #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 /* The following 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 #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 #define CKM_DES_OFB64 0x00000150 #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 /* The following are new for v2.11 */ #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 #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 /* The following 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 #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 #define CKM_SHA256_KEY_DERIVATION 0x00000393 #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.11 */ #define CKM_PKCS5_PBKD2 0x000003B0 #define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 #define CKM_KEY_WRAP_LYNKS 0x00000400 #define CKM_KEY_WRAP_SET_OAEP 0x00000401 /* 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 /* The following 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 /* The following 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 #define CKM_AES_CTR 0x00001086 #define CKM_AES_GCM 0x00001087 #define CKM_DSA_PARAMETER_GEN 0x00002000 #define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 #define CKM_X9_42_DH_PARAMETER_GEN 0x00002002 #define CKM_AES_OFB 0x00002104 #define CKM_AES_CFB64 0x00002105 #define CKM_AES_CFB8 0x00002106 #define CKM_AES_CFB128 0x00002107 #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 */ /* 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 /* The following are new for v2.11 */ #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 2.01 */ 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 /* CKR_DOMAIN_PARAMS_INVALID is new for v2.11 */ #define CKR_DOMAIN_PARAMS_INVALID 0x00000130 #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 #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_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 */ // SAB the mutex ones had pf infront previously.. // The spec says otherwise. 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_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_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ typedef struct CK_AES_CTR_PARAMS { CK_ULONG ulCounterBits; CK_BYTE cb[16]; } CK_AES_CTR_PARAMS; typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR; typedef struct CK_GCM_PARAMS { CK_BYTE_PTR pIv; CK_ULONG ulIvLen; CK_BYTE_PTR pAAD; CK_ULONG ulAADLen; CK_ULONG ulTagBits; } CK_GCM_PARAMS; typedef CK_GCM_PARAMS CK_PTR CK_GCM_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_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_CHAR_PTR pInitVector; CK_CHAR_PTR pPassword; CK_ULONG ulPasswordLen; CK_CHAR_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; 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; /* RSA mechanism OAEP encoding */ typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; /* PKCS#1 RSA OAEP Encoding Parameter Sources */ #define CKZ_DATA_SPECIFIED 0x00000001 /* PKCS#1 Mask Generation Functions */ #define CKG_MGF1_SHA1 0x00000001 #define CKG_MGF1_SHA256 0x00000002 #define CKG_MGF1_SHA384 0x00000003 #define CKG_MGF1_SHA512 0x00000004 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; 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_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; typedef CK_RV (CK_PTR CK_C_Initialize) (CK_VOID_PTR pReserved); typedef CK_RV (CK_PTR CK_C_Finalize) (CK_VOID_PTR pReserved); typedef CK_RV (CK_PTR CK_C_Terminate) (void); typedef CK_RV (CK_PTR CK_C_GetInfo) (CK_INFO_PTR pInfo); typedef CK_RV (CK_PTR CK_C_GetFunctionList) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); typedef CK_RV (CK_PTR CK_C_GetSlotList) (CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pusCount); typedef CK_RV (CK_PTR CK_C_GetSlotInfo) (CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); typedef CK_RV (CK_PTR CK_C_GetTokenInfo) (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); typedef CK_RV (CK_PTR CK_C_GetMechanismList) (CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pusCount); typedef CK_RV (CK_PTR CK_C_GetMechanismInfo) (CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); typedef CK_RV (CK_PTR CK_C_InitToken) (CK_SLOT_ID slotID, CK_CHAR_PTR pPin, CK_ULONG usPinLen, CK_CHAR_PTR pLabel); typedef CK_RV (CK_PTR CK_C_InitPIN) (CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG usPinLen); typedef CK_RV (CK_PTR CK_C_SetPIN) (CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, CK_ULONG usOldLen, CK_CHAR_PTR pNewPin, CK_ULONG usNewLen); typedef CK_RV (CK_PTR CK_C_OpenSession) (CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_RV (*Notify) (CK_SESSION_HANDLE hSession, CK_NOTIFICATION event, CK_VOID_PTR pApplication), CK_SESSION_HANDLE_PTR phSession); typedef CK_RV (CK_PTR CK_C_CloseSession) (CK_SESSION_HANDLE hSession); typedef CK_RV (CK_PTR CK_C_CloseAllSessions) (CK_SLOT_ID slotID); typedef CK_RV (CK_PTR CK_C_GetSessionInfo) (CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo); typedef CK_RV (CK_PTR CK_C_GetOperationState) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen); typedef CK_RV (CK_PTR CK_C_SetOperationState) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey); typedef CK_RV (CK_PTR CK_C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG usPinLen); typedef CK_RV (CK_PTR CK_C_Logout)(CK_SESSION_HANDLE hSession); typedef CK_RV (CK_PTR CK_C_CreateObject) (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phObject); typedef CK_RV (CK_PTR CK_C_CopyObject) (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phNewObject); typedef CK_RV (CK_PTR CK_C_DestroyObject) (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject); typedef CK_RV(CK_PTR CK_C_GetObjectSize) (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pusSize); typedef CK_RV(CK_PTR CK_C_GetAttributeValue) (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV(CK_PTR CK_C_SetAttributeValue) (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV (CK_PTR CK_C_FindObjectsInit) (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV (CK_PTR CK_C_FindObjects) (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG usMaxObjectCount, CK_ULONG_PTR pusObjectCount); typedef CK_RV (CK_PTR CK_C_FindObjectsFinal) (CK_SESSION_HANDLE hSession); typedef CK_RV (CK_PTR CK_C_EncryptInit) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR CK_C_Encrypt) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pusEncryptedDataLen); typedef CK_RV (CK_PTR CK_C_EncryptUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pusEncryptedPartLen); typedef CK_RV (CK_PTR CK_C_EncryptFinal) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pusLastEncryptedPartLen); typedef CK_RV (CK_PTR CK_C_DecryptInit) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR CK_C_Decrypt) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG usEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pusDataLen); typedef CK_RV (CK_PTR CK_C_DecryptUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG usEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pusPartLen); typedef CK_RV (CK_PTR CK_C_DecryptFinal) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pusLastPartLen); typedef CK_RV (CK_PTR CK_C_DigestInit) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism); typedef CK_RV (CK_PTR CK_C_Digest) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pusDigestLen); typedef CK_RV (CK_PTR CK_C_DigestUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR CK_C_DigestKey) (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR CK_C_DigestFinal) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pusDigestLen); typedef CK_RV (CK_PTR CK_C_SignInit) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR CK_C_Sign) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR CK_C_SignUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR CK_C_SignFinal) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR CK_C_SignRecoverInit) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR CK_C_SignRecover) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR CK_C_VerifyInit) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR CK_C_Verify) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen); typedef CK_RV (CK_PTR CK_C_VerifyUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR CK_C_VerifyFinal) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen); typedef CK_RV (CK_PTR CK_C_VerifyRecoverInit) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR CK_C_VerifyRecover) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pusDataLen); typedef CK_RV (CK_PTR CK_C_DigestEncryptUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); typedef CK_RV (CK_PTR CK_C_DecryptDigestUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); typedef CK_RV (CK_PTR CK_C_SignEncryptUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); typedef CK_RV (CK_PTR CK_C_DecryptVerifyUpdate) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); typedef CK_RV (CK_PTR CK_C_GenerateKey) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR CK_C_GenerateKeyPair) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG usPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG usPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPrivateKey, CK_OBJECT_HANDLE_PTR phPublicKey); typedef CK_RV (CK_PTR CK_C_WrapKey) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pusWrappedKeyLen); typedef CK_RV (CK_PTR CK_C_UnwrapKey) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG usWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR CK_C_DeriveKey) (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR CK_C_SeedRandom) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG usSeedLen); typedef CK_RV (CK_PTR CK_C_GenerateRandom) (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG usRandomLen); typedef CK_RV (CK_PTR CK_C_GetFunctionStatus) (CK_SESSION_HANDLE hSession); typedef CK_RV (CK_PTR CK_C_CancelFunction) (CK_SESSION_HANDLE hSession); typedef CK_RV (CK_PTR CK_Notify) (CK_SESSION_HANDLE hSession, CK_NOTIFICATION event, CK_VOID_PTR pApplication); typedef CK_RV (CK_PTR CK_C_WaitForSlotEvent) (CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved); struct CK_FUNCTION_LIST { CK_VERSION version; CK_C_Initialize C_Initialize; CK_C_Finalize C_Finalize; CK_C_GetInfo C_GetInfo; CK_C_GetFunctionList C_GetFunctionList; CK_C_GetSlotList C_GetSlotList; CK_C_GetSlotInfo C_GetSlotInfo; CK_C_GetTokenInfo C_GetTokenInfo; CK_C_GetMechanismList C_GetMechanismList; CK_C_GetMechanismInfo C_GetMechanismInfo; CK_C_InitToken C_InitToken; CK_C_InitPIN C_InitPIN; CK_C_SetPIN C_SetPIN; CK_C_OpenSession C_OpenSession; CK_C_CloseSession C_CloseSession; CK_C_CloseAllSessions C_CloseAllSessions; CK_C_GetSessionInfo C_GetSessionInfo; CK_C_GetOperationState C_GetOperationState; CK_C_SetOperationState C_SetOperationState; CK_C_Login C_Login; CK_C_Logout C_Logout; CK_C_CreateObject C_CreateObject; CK_C_CopyObject C_CopyObject; CK_C_DestroyObject C_DestroyObject; CK_C_GetObjectSize C_GetObjectSize; CK_C_GetAttributeValue C_GetAttributeValue; CK_C_SetAttributeValue C_SetAttributeValue; CK_C_FindObjectsInit C_FindObjectsInit; CK_C_FindObjects C_FindObjects; CK_C_FindObjectsFinal C_FindObjectsFinal; CK_C_EncryptInit C_EncryptInit; CK_C_Encrypt C_Encrypt; CK_C_EncryptUpdate C_EncryptUpdate; CK_C_EncryptFinal C_EncryptFinal; CK_C_DecryptInit C_DecryptInit; CK_C_Decrypt C_Decrypt; CK_C_DecryptUpdate C_DecryptUpdate; CK_C_DecryptFinal C_DecryptFinal; CK_C_DigestInit C_DigestInit; CK_C_Digest C_Digest; CK_C_DigestUpdate C_DigestUpdate; CK_C_DigestKey C_DigestKey; CK_C_DigestFinal C_DigestFinal; CK_C_SignInit C_SignInit; CK_C_Sign C_Sign; CK_C_SignUpdate C_SignUpdate; CK_C_SignFinal C_SignFinal; CK_C_SignRecoverInit C_SignRecoverInit; CK_C_SignRecover C_SignRecover; CK_C_VerifyInit C_VerifyInit; CK_C_Verify C_Verify; CK_C_VerifyUpdate C_VerifyUpdate; CK_C_VerifyFinal C_VerifyFinal; CK_C_VerifyRecoverInit C_VerifyRecoverInit; CK_C_VerifyRecover C_VerifyRecover; CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; CK_C_SignEncryptUpdate C_SignEncryptUpdate; CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; CK_C_GenerateKey C_GenerateKey; CK_C_GenerateKeyPair C_GenerateKeyPair; CK_C_WrapKey C_WrapKey; CK_C_UnwrapKey C_UnwrapKey; CK_C_DeriveKey C_DeriveKey; CK_C_SeedRandom C_SeedRandom; CK_C_GenerateRandom C_GenerateRandom; CK_C_GetFunctionStatus C_GetFunctionStatus; CK_C_CancelFunction C_CancelFunction; CK_C_WaitForSlotEvent C_WaitForSlotEvent; }; #ifdef __cplusplus } #endif #endif // _PKCS11TYPES_H_ opencryptoki+dfsg/usr/include/pkcs11/pkcs11log.h0000755000175000017500000004460012630407154020621 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/pkcs11log.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _LOG_H #define _LOG_H 1 #include #include #include #include #include #include #include #include #include #include "pkcs11err.h" #ifndef FALSE #define FALSE 0 #endif /* FALSE */ #ifndef TRUE #define TRUE (!(FALSE)) #endif /* TRUE */ #ifndef MAX_LOGGING_FACILITIES #define MAX_LOGGING_FACILITIES 16 #endif /* MAX_LOGGING_FACILITIES */ #ifndef TRUNCATE_LOGS_ON_START #define TRUNCATE_LOGS_ON_START 0 #endif /* TRUNCATE_LOGS_ON_START */ /* Use an enum here? */ #define DEBUG_NONE (0) #define DEBUG_LEVEL0 (100) /* Less detail */ #define DEBUG_LEVEL1 (DEBUG_LEVEL0 + 100) /* . */ #define DEBUG_LEVEL2 (DEBUG_LEVEL1 + 100) /* v */ #define DEBUG_LEVEL3 (DEBUG_LEVEL2 + 100) /* More detail */ #define DEBUG_LEVEL4 (DEBUG_LEVEL3 + 100) #define DEBUG_LEVEL5 (DEBUG_LEVEL4 + 100) #define DNONE (DEBUG_NONE) #define DL0 (DEBUG_LEVEL0) #define DL1 (DEBUG_LEVEL1) #define DL2 (DEBUG_LEVEL2) #define DL3 (DEBUG_LEVEL3) #define DL4 (DEBUG_LEVEL4) #define DL5 (DEBUG_LEVEL5) #ifndef DbgPrint #define DbgPrint DbgLog #endif /* DbgPrint */ /************** * Structures * **************/ /************************************************************************ * Yes, the structures are somewhat redundant; this is an evolutionary * side-effect. They should probably be combined into a single struct * - SCM ************************************************************************/ typedef u_int32 LogHandle, *pLogHandle; typedef u_int32 BOOL, bool, BOOLEAN, boolean; typedef struct _logging_facility_info { BOOL Initialized; char Descrip[255]; u_int32 LogOption; char *Filename; BOOL UseSyslog; u_int32 LogLevel; struct syslog_data LogData; pid_t pid; } LoggingFacilityInfo, *pLoggingFacilityInfo; typedef struct _LoggingFacility { char *Label; pLogHandle phLog; char *Filename; BOOL UseSyslog; u_int32 LogLevel; } LoggingFacility, *pLoggingFacility; /******************************** * Exported Function Prototypes * ********************************/ void DbgLog ( u_int32 DebugLevel, char *Format, ... ); void ErrLog ( char *Format, ... ); void LogLog ( char *Format, ... ); void WarnLog ( char *Format, ... ); void TraceLog ( char *Format, ... ); void InfoLog ( char *Format, ... ); BOOL PKCS_Log ( LogHandle *phLog, char *Format, va_list ap ); BOOL NewLoggingFacility ( char *ID, pLoggingFacility pStuff ); BOOL CloseLoggingFacility ( LogHandle hLog ); BOOL GetCurrentTimeString ( char *Buffer ); u_int32 SetDebugLevel ( u_int32 Val ); u_int32 GetDebugLevel ( void ); #endif /* _LOG_H */ opencryptoki+dfsg/usr/include/pkcs11/stdll/0000755000175000017500000000000012630407154017757 5ustar xnoxxnoxopencryptoki+dfsg/usr/include/pkcs11/stdll/keys.h0000755000175000017500000003645412630407154021122 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/stdll/keys.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _STDLL_KEYS_H #define _STDLL_KEYS_H #include #include /* This header file will be eliminated when the objects are actually created * by the library rather than being hard coded into it. */ B_KEY_OBJ BSafe_Key_Object; #endif opencryptoki+dfsg/usr/include/pkcs11/stdll/functions.h0000755000175000017500000003776112630407154022161 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/stdll/functions.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _STDLL_PKCS_FUNCTIONS_H #define _STDLL_PKCS_FUNCTIONS_H extern CK_RV SC_GetTokenInfo(); extern CK_RV SC_GetMechanismList(); extern CK_RV SC_GetMechanismInfo(); extern CK_RV SC_OpenSession(); extern CK_RV SC_CloseSession(); extern CK_RV SC_GetSessionInfo(); extern CK_RV SC_Login(); extern CK_RV SC_Logout(); extern CK_RV SC_CreateObject(); extern CK_RV SC_CopyObject(); extern CK_RV SC_DestroyObject(); extern CK_RV SC_GetAttributeValue(); extern CK_RV SC_SetAttributeValue(); extern CK_RV SC_FindObjectsInit(); extern CK_RV SC_FindObjects(); extern CK_RV SC_FindObjectsFinal(); extern CK_RV SC_EncryptInit(); extern CK_RV SC_Encrypt(); extern CK_RV SC_DecryptInit(); extern CK_RV SC_Decrypt(); extern CK_RV SC_SignInit(); extern CK_RV SC_Sign(); extern CK_RV SC_Verify(); extern CK_RV SC_VerifyRecover(); extern CK_RV SC_GenerateKey(); extern CK_RV SC_GenerateKeyPair(); extern CK_RV SC_WrapKey(); extern CK_RV SC_UnwrapKey(); extern CK_RV SC_GenerateRandom(); #endif opencryptoki+dfsg/usr/include/pkcs11/stdll/stdll_gen.h0000755000175000017500000004157012630407154022115 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/stdll/stdll_gen.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _PKCS11_GENERAL_H #define _PKCS11_GENERAL_H #include #include "pkcs11o.h" #include "stdll.h" #define CKS_MAX_SESSIONS 10 #define CKS_NUMBER_OF_MECHANISMS 2 #define CKS_NUMBER_OF_OBJECTS 100 /* Size of Object Array */ #define CKS_NUMBER_OF_SLOTS 1 #define DLL_LBL "Prototype Software Token (BSAFE)" #define DLL_MFG "IBM Austin: RS/6000 Division " #define DLL_MODEL "BSAFE Prototype " #define DLL_SERIAL "mdmcl00-02 03-SEPTEMBER-1999 " #define DBG_LABEL "pkcs11.c: " typedef struct SC_Slot { CK_SLOT_ID MySlotID; CK_TOKEN_INFO MyToken; CK_BBOOL LoggedIn; /* Is this redundant of MyState? */ CK_CHAR_PTR MyDevice; CK_STATE MyState; /* Login Status */ CK_USER_TYPE MyUserType; /* R/O, R/E User */ } SC_Slot_t; SC_Slot_t slots[ CKS_NUMBER_OF_SLOTS ]; CK_ULONG SlotCount; STDLL_FcnList_t MyFunctionList; CK_MECHANISM_TYPE MyMechanisms[ CKS_NUMBER_OF_MECHANISMS ]; typedef struct SC_Session { CK_SESSION_HANDLE SessionList; CK_SESSION_INFO_PTR SessionInfo; } SC_Session_t; SC_Session_t sessions[ CKS_NUMBER_OF_SLOTS ] [ CKS_MAX_SESSIONS ]; SC_OBJECT_HANDLE_PTR ObjectList [ CKS_NUMBER_OF_SLOTS ] [ CKS_MAX_SESSIONS ]; SC_OBJECT_HANDLE_PTR TokenObjectList; /* Find Objects */ typedef struct SC_FindObjects { CK_BBOOL FindObjectReady; CK_ATTRIBUTE_PTR FindObjectAttr; CK_ULONG FindObjectNum; } SC_FindObjects_t; SC_FindObjects_t FindParameters[ CKS_NUMBER_OF_SLOTS ] [ CKS_MAX_SESSIONS ]; /* Loop Control Variable */ /* XXX Global? What about concurrent access? */ int lcv; #endif opencryptoki+dfsg/usr/include/pkcs11/stdll/decrypt.h0000755000175000017500000003663212630407154021617 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/stdll/decrypt.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _STDLL_DECRYPT_H #define _STDLL_DECRYPT_H #include #include "stdll_gen.h" B_ALGORITHM_OBJ DecryptObj [ CKS_NUMBER_OF_SLOTS ] [ CKS_MAX_SESSIONS ]; B_ALGORITHM_OBJ BSafe_Algorithm_Object; B_ALGORITHM_METHOD *RSA_DECRYPT_CHOOSER[] = { &AM_RSA_CRT_DECRYPT, (B_ALGORITHM_METHOD *)NULL_PTR}; #endif opencryptoki+dfsg/usr/include/pkcs11/stdll/encrypt.h0000755000175000017500000003724412630407154021631 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/stdll/encrypt.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _STDLL_ENCRYPT_H #define _STDLL_ENCRYPT_H #include #include "stdll_gen.h" B_ALGORITHM_OBJ EncryptObj [ CKS_NUMBER_OF_SLOTS ] [ CKS_MAX_SESSIONS ]; B_ALGORITHM_OBJ BSafe_Algorithm_Object; B_ALGORITHM_METHOD *RSA_ENCRYPT_CHOOSER[] = { &AM_RSA_ENCRYPT, (B_ALGORITHM_METHOD *)NULL_PTR }; B_ALGORITHM_OBJ BSafe_Random_Object; B_ALGORITHM_METHOD *MD5_RANDOM_CHOOSER[] = { &AM_MD5_RANDOM, (B_ALGORITHM_METHOD *)NULL_PTR }; B_ALGORITHM_METHOD *RSA_SIGN_CHOOSER[] = { &AM_MD5, &AM_RSA_CRT_ENCRYPT, (B_ALGORITHM_METHOD *)NULL_PTR }; #endif opencryptoki+dfsg/usr/include/pkcs11/apiclient.h0000755000175000017500000005256312630407153020773 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/apiclient.h,v 1.2 2005/02/22 20:47:32 mhalcrow Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _APICLIENT_H #define _APICLIENT_H #include "pkcs11types.h" #define VERSION_MAJOR 2 // Version 2 of the PKCS library #define VERSION_MINOR 01 // minor revision .10 of PKCS11 #ifdef __cplusplus extern "C" { #endif CK_RV C_CancelFunction ( CK_SESSION_HANDLE ); CK_RV C_CloseAllSessions ( CK_SLOT_ID ); CK_RV C_CloseSession ( CK_SESSION_HANDLE ); CK_RV C_CopyObject ( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR ); CK_RV C_CreateObject ( CK_SESSION_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR ); CK_RV C_Decrypt ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_DecryptDigestUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_DecryptFinal ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_DecryptInit ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE ); CK_RV C_DecryptUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_DecryptVerifyUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_DeriveKey ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR ); CK_RV C_DestroyObject ( CK_SESSION_HANDLE, CK_OBJECT_HANDLE ); CK_RV C_Digest ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_DigestEncryptUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_DigestFinal ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_DigestInit ( CK_SESSION_HANDLE, CK_MECHANISM_PTR ); CK_RV C_DigestKey ( CK_SESSION_HANDLE, CK_OBJECT_HANDLE ); CK_RV C_DigestUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG ); CK_RV C_Encrypt ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_EncryptFinal ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_EncryptInit ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE ); CK_RV C_EncryptUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_Finalize ( CK_VOID_PTR ); CK_RV C_FindObjects ( CK_SESSION_HANDLE, CK_OBJECT_HANDLE_PTR, CK_ULONG, CK_ULONG_PTR ); CK_RV C_FindObjectsFinal ( CK_SESSION_HANDLE ); CK_RV C_FindObjectsInit ( CK_SESSION_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG ); CK_RV C_GenerateKey ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR ); CK_RV C_GenerateKeyPair ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR ); CK_RV C_GenerateRandom ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG ); CK_RV C_GetAttributeValue ( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG ); CK_RV C_GetFunctionList ( CK_FUNCTION_LIST_PTR_PTR ); CK_RV C_GetFunctionStatus ( CK_SESSION_HANDLE ); CK_RV C_GetInfo ( CK_INFO_PTR ); CK_RV C_GetMechanismInfo ( CK_SLOT_ID, CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR ); CK_RV C_GetMechanismList ( CK_SLOT_ID, CK_MECHANISM_TYPE_PTR, CK_ULONG_PTR ); CK_RV C_GetObjectSize ( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ULONG_PTR ); CK_RV C_GetOperationState ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_GetSessionInfo ( CK_SESSION_HANDLE, CK_SESSION_INFO_PTR ); CK_RV C_GetSlotInfo ( CK_SLOT_ID, CK_SLOT_INFO_PTR ); CK_RV C_GetSlotList ( CK_BBOOL, CK_SLOT_ID_PTR, CK_ULONG_PTR ); CK_RV C_GetTokenInfo ( CK_SLOT_ID, CK_TOKEN_INFO_PTR ); CK_RV C_Initialize ( CK_VOID_PTR ); CK_RV C_InitPIN ( CK_SESSION_HANDLE, CK_CHAR_PTR, CK_ULONG ); CK_RV C_InitToken ( CK_SLOT_ID, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR ); CK_RV C_Login ( CK_SESSION_HANDLE, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG ); CK_RV C_Logout ( CK_SESSION_HANDLE ); CK_RV C_OpenSession ( CK_SLOT_ID, CK_FLAGS, CK_VOID_PTR, CK_NOTIFY, CK_SESSION_HANDLE_PTR ); CK_RV C_SeedRandom ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG ); CK_RV C_SetAttributeValue ( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG ); CK_RV C_SetOperationState ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE ); CK_RV C_SetPIN ( CK_SESSION_HANDLE, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG ); CK_RV C_Sign ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_SignEncryptUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_SignFinal ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_SignInit ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE ); CK_RV C_SignRecover ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_SignRecoverInit ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE ); CK_RV C_SignUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG ); 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 ); CK_RV C_Verify ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG ); CK_RV C_VerifyFinal ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG ); CK_RV C_VerifyInit ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE ); CK_RV C_VerifyRecover ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR ); CK_RV C_VerifyRecoverInit ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE ); CK_RV C_VerifyUpdate ( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG ); CK_RV C_WaitForSlotEvent ( CK_FLAGS, CK_SLOT_ID_PTR, CK_VOID_PTR ); CK_RV C_WrapKey ( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR ); #ifdef __cplusplus } #endif #endif // _APICLIENT_H opencryptoki+dfsg/usr/include/pkcs11/testcert.h0000755000175000017500000005314312630407154020654 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/testcert.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #define TestCert_Label "Self Signed Cert for PKCS#11" char DN[83] = { 48, 81, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 9, 48, 7, 6, 3, 85, 4, 3, 19, 0 }; char Issuer[83] = { 48, 81, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 9, 48, 7, 6, 3, 85, 4, 3, 19, 0 }; char Cert[541] = { 48, 130, 2, 25, 48, 130, 1, 130, 160, 3, 2, 1, 2, 2, 4, 55, 196, 11, 144, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 81, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 9, 48, 7, 6, 3, 85, 4, 3, 19, 0, 48, 30, 23, 13, 57, 57, 48, 56, 50, 52, 49, 53, 50, 56, 49, 54, 90, 23, 13, 48, 50, 48, 52, 49, 54, 49, 53, 50, 56, 49, 54, 90, 48, 81, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 0, 49, 9, 48, 7, 6, 3, 85, 4, 3, 19, 0, 48, 129, 159, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 141, 0, 48, 129, 137, 2, 129, 129, 0, 160, 224, 39, 50, 200, 43, 125, 162, 219, 163, 93, 182, 28, 38, 105, 248, 255, 78, 10, 54, 255, 234, 184, 7, 45, 219, 23, 131, 54, 130, 37, 184, 205, 41, 40, 38, 229, 190, 17, 130, 75, 151, 190, 209, 226, 37, 38, 145, 26, 237, 169, 117, 114, 169, 55, 107, 225, 24, 205, 171, 226, 82, 69, 57, 241, 149, 32, 188, 86, 234, 5, 206, 0, 20, 237, 210, 101, 109, 143, 160, 182, 15, 201, 2, 252, 237, 241, 120, 179, 187, 112, 143, 31, 156, 90, 173, 211, 130, 151, 164, 199, 235, 48, 223, 124, 145, 100, 3, 104, 188, 49, 110, 232, 54, 108, 30, 33, 169, 197, 137, 92, 244, 7, 135, 208, 216, 9, 141, 2, 3, 1, 0, 1, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3, 129, 129, 0, 66, 115, 199, 229, 210, 234, 31, 199, 15, 171, 65, 13, 86, 149, 206, 161, 252, 120, 220, 228, 215, 39, 23, 180, 166, 151, 48, 77, 112, 119, 145, 165, 123, 159, 48, 0, 169, 191, 5, 16, 48, 199, 161, 49, 134, 91, 190, 235, 37, 80, 91, 96, 205, 43, 177, 13, 224, 10, 92, 211, 40, 50, 69, 103, 241, 121, 120, 227, 189, 99, 95, 92, 174, 83, 31, 45, 119, 103, 96, 192, 208, 245, 58, 248, 106, 203, 27, 218, 149, 139, 46, 204, 27, 104, 241, 98, 22, 58, 212, 207, 122, 100, 241, 39, 233, 54, 40, 66, 87, 177, 129, 12, 65, 107, 116, 30, 176, 220, 20, 183, 16, 104, 229, 84, 19, 35, 84, 204 }; char PrivKey[633] = { 48, 130, 2, 117, 2, 1, 0, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 4, 130, 2, 95, 48, 130, 2, 91, 2, 1, 0, 2, 129, 129, 0, 160, 224, 39, 50, 200, 43, 125, 162, 219, 163, 93, 182, 28, 38, 105, 248, 255, 78, 10, 54, 255, 234, 184, 7, 45, 219, 23, 131, 54, 130, 37, 184, 205, 41, 40, 38, 229, 190, 17, 130, 75, 151, 190, 209, 226, 37, 38, 145, 26, 237, 169, 117, 114, 169, 55, 107, 225, 24, 205, 171, 226, 82, 69, 57, 241, 149, 32, 188, 86, 234, 5, 206, 0, 20, 237, 210, 101, 109, 143, 160, 182, 15, 201, 2, 252, 237, 241, 120, 179, 187, 112, 143, 31, 156, 90, 173, 211, 130, 151, 164, 199, 235, 48, 223, 124, 145, 100, 3, 104, 188, 49, 110, 232, 54, 108, 30, 33, 169, 197, 137, 92, 244, 7, 135, 208, 216, 9, 141, 2, 3, 1, 0, 1, 2, 129, 128, 9, 209, 3, 179, 78, 145, 144, 206, 2, 54, 250, 189, 229, 3, 215, 13, 145, 142, 146, 130, 254, 164, 180, 236, 3, 57, 78, 58, 252, 117, 126, 149, 195, 55, 18, 179, 36, 235, 175, 39, 211, 51, 4, 58, 204, 96, 213, 244, 158, 191, 7, 203, 25, 223, 7, 121, 182, 183, 139, 189, 68, 71, 30, 224, 44, 126, 87, 202, 196, 83, 124, 134, 139, 54, 29, 50, 175, 106, 126, 193, 7, 52, 67, 12, 115, 251, 84, 232, 222, 118, 41, 195, 5, 182, 176, 73, 79, 103, 107, 141, 96, 170, 242, 175, 183, 154, 13, 224, 45, 40, 49, 96, 146, 3, 9, 26, 21, 115, 33, 183, 118, 174, 68, 13, 198, 220, 105, 69, 2, 65, 0, 208, 30, 177, 14, 227, 148, 126, 152, 149, 117, 190, 215, 106, 133, 96, 66, 114, 141, 175, 245, 146, 81, 1, 197, 182, 147, 187, 214, 33, 125, 144, 126, 229, 192, 141, 200, 168, 106, 238, 231, 122, 104, 55, 70, 94, 82, 1, 155, 209, 245, 162, 101, 78, 1, 57, 33, 11, 205, 97, 202, 170, 26, 48, 43, 2, 65, 0, 197, 226, 253, 53, 187, 167, 237, 30, 197, 139, 227, 116, 80, 173, 71, 136, 99, 143, 199, 246, 94, 102, 86, 110, 152, 149, 122, 165, 243, 16, 98, 220, 143, 90, 3, 235, 88, 67, 41, 235, 146, 37, 192, 88, 54, 160, 79, 102, 76, 127, 246, 232, 222, 20, 70, 217, 22, 119, 50, 80, 182, 179, 153, 39, 2, 64, 122, 166, 203, 212, 41, 125, 23, 10, 151, 114, 151, 240, 222, 31, 18, 118, 182, 138, 23, 252, 18, 169, 216, 240, 139, 68, 15, 124, 7, 170, 183, 96, 129, 200, 116, 6, 160, 114, 188, 175, 0, 173, 176, 125, 177, 18, 133, 78, 46, 115, 163, 172, 46, 71, 124, 66, 164, 112, 250, 195, 244, 113, 144, 151, 2, 64, 52, 212, 28, 117, 51, 219, 232, 217, 198, 51, 74, 77, 203, 27, 247, 116, 217, 223, 144, 170, 157, 25, 5, 10, 17, 130, 22, 116, 39, 39, 192, 188, 209, 40, 94, 211, 125, 132, 176, 180, 75, 23, 248, 249, 147, 219, 200, 86, 175, 37, 154, 109, 32, 156, 153, 45, 107, 105, 246, 236, 197, 89, 189, 17, 2, 64, 92, 208, 59, 86, 221, 175, 121, 63, 31, 217, 197, 148, 228, 143, 254, 51, 187, 57, 71, 38, 153, 157, 38, 65, 121, 247, 184, 55, 159, 47, 207, 153, 186, 45, 117, 138, 229, 175, 95, 21, 161, 206, 167, 112, 119, 67, 201, 138, 92, 243, 1, 142, 133, 117, 15, 106, 195, 57, 136, 191, 217, 48, 0, 98, }; char PubKey[162] = { 48, 129, 159, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 141, 0, 48, 129, 137, 2, 129, 129, 0, 160, 224, 39, 50, 200, 43, 125, 162, 219, 163, 93, 182, 28, 38, 105, 248, 255, 78, 10, 54, 255, 234, 184, 7, 45, 219, 23, 131, 54, 130, 37, 184, 205, 41, 40, 38, 229, 190, 17, 130, 75, 151, 190, 209, 226, 37, 38, 145, 26, 237, 169, 117, 114, 169, 55, 107, 225, 24, 205, 171, 226, 82, 69, 57, 241, 149, 32, 188, 86, 234, 5, 206, 0, 20, 237, 210, 101, 109, 143, 160, 182, 15, 201, 2, 252, 237, 241, 120, 179, 187, 112, 143, 31, 156, 90, 173, 211, 130, 151, 164, 199, 235, 48, 223, 124, 145, 100, 3, 104, 188, 49, 110, 232, 54, 108, 30, 33, 169, 197, 137, 92, 244, 7, 135, 208, 216, 9, 141, 2, 3, 1, 0, 1 }; opencryptoki+dfsg/usr/include/pkcs11/pkcs11o.h0000755000175000017500000005572712630407154020312 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/pkcs11o.h,v 1.1 2005/01/18 16:09:04 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _PKCS11OBJECTS_H #define _PKCS11OBJECTS_H #include "pkcs11types.h" #define SC_CLASS 0x00 #define SC_TOKEN 0x01 #define SC_PRIVATE 0x02 #define SC_MODIFIABLE 0x03 #define SC_LABEL 0x04 #define SC_KEY_TYPE 0x05 #define SC_KEY_ID 0x06 #define SC_KEY_START 0x07 #define SC_KEY_END 0x08 #define SC_KEY_DERIVE 0x09 #define SC_KEY_LOCAL 0x10 typedef union SC_OBJECT { struct { CK_ATTRIBUTE class; /* Object type */ CK_ATTRIBUTE token; /* True for token object */ CK_ATTRIBUTE bPrivate; /* True for private objects */ CK_ATTRIBUTE bModifiable; /* True if can be modified */ CK_ATTRIBUTE label; /* Description of the object */ CK_ATTRIBUTE application; /* Description of the managing app */ CK_ATTRIBUTE value; /* Value of the object */ } Data; struct { CK_ATTRIBUTE class; /* Object type */ CK_ATTRIBUTE token; /* True for token object */ CK_ATTRIBUTE bPrivate; /* True for private objects */ CK_ATTRIBUTE bModifiable; /* True if can be modified */ CK_ATTRIBUTE label; /* Description of the object */ CK_ATTRIBUTE type; /* Type of Certificate */ CK_ATTRIBUTE subject; /* DER encoded subject name */ CK_ATTRIBUTE id; /* Key identifier for key pair */ CK_ATTRIBUTE issuer; /* DER encoded issuer name */ CK_ATTRIBUTE serial; /* DER encoded serial number */ CK_ATTRIBUTE value; /* BER encoding of the certificate */ } Cert; struct { CK_ATTRIBUTE class; /* Object type */ CK_ATTRIBUTE token; /* True for token object */ CK_ATTRIBUTE bPrivate; /* True for private objects */ CK_ATTRIBUTE bModifiable; /* True if can be modified */ CK_ATTRIBUTE label; /* Description of the object */ CK_ATTRIBUTE type; /* Type of Key */ CK_ATTRIBUTE id; /* Key identifier for the key */ CK_ATTRIBUTE start; /* Start date for the key */ CK_ATTRIBUTE end; /* End date for the key */ CK_ATTRIBUTE derive; /* TRUE: keys can be derived from */ CK_ATTRIBUTE local; /* Generated locally */ CK_ATTRIBUTE subject; /* DER encoded key subject name */ CK_ATTRIBUTE encrypt; /* TRUE: can encrypt */ CK_ATTRIBUTE verify; /* TRUE: sign is an appendix */ CK_ATTRIBUTE v_recover; /* TRUE: verify where data in sign */ CK_ATTRIBUTE wrap; /* TRUE: if can wrap other keys */ CK_ATTRIBUTE modulus; /* Modulus n */ CK_ATTRIBUTE length; /* Length in bits of modulus n */ CK_ATTRIBUTE exponent; /* Public Exponent e */ } PubKey; struct { CK_ATTRIBUTE class; /* Object type */ CK_ATTRIBUTE token; /* True for token object */ CK_ATTRIBUTE bPrivate; /* True for private objects */ CK_ATTRIBUTE bModifiable; /* True if can be modified */ CK_ATTRIBUTE label; /* Description of the object */ CK_ATTRIBUTE type; /* Type of Key */ CK_ATTRIBUTE id; /* Key identifier for the key */ CK_ATTRIBUTE start; /* Start date for the key */ CK_ATTRIBUTE end; /* End date for the key */ CK_ATTRIBUTE derive; /* TRUE: keys can be derived from */ CK_ATTRIBUTE local; /* Generated locally */ CK_ATTRIBUTE subject; /* DER encoded key subject name */ CK_ATTRIBUTE sensitive; /* TRUE: key is sensitive */ CK_ATTRIBUTE decrypt; /* TRUE: can decrypt */ CK_ATTRIBUTE sign; /* TRUE: sign as an appendix */ CK_ATTRIBUTE s_recover; /* TRUE: verify where data in sign */ CK_ATTRIBUTE unwrap; /* TRUE: if can unwrap other keys */ CK_ATTRIBUTE extractable; /* TRUE: can be extracted */ CK_ATTRIBUTE always_sens; /* TRUE: if sensitive always been T */ CK_ATTRIBUTE never_extract;/* TRUE: if extractable never set T */ CK_ATTRIBUTE modulus; /* Modulus n */ CK_ATTRIBUTE pub_exp; /* Public Exponent e */ CK_ATTRIBUTE priv_exp; /* Public Exponent d */ CK_ATTRIBUTE prime1; /* Prime p */ CK_ATTRIBUTE prime2; /* Prime q */ CK_ATTRIBUTE exp1; /* Private Exponent d modulo p-1 */ CK_ATTRIBUTE exp2; /* Private Exponent d modulo q-1 */ CK_ATTRIBUTE coefficient; /* CRT coefficient q^(-1) mod p */ } PrivKey; struct { CK_ATTRIBUTE class; /* Object type */ CK_ATTRIBUTE token; /* True for token object */ CK_ATTRIBUTE bPrivate; /* True for private objects */ CK_ATTRIBUTE bModifiable; /* True if can be modified */ CK_ATTRIBUTE label; /* Description of the object */ CK_ATTRIBUTE type; /* Type of Key */ CK_ATTRIBUTE id; /* Key identifier for the key */ CK_ATTRIBUTE start; /* Start date for the key */ CK_ATTRIBUTE end; /* End date for the key */ CK_ATTRIBUTE derive; /* TRUE: keys can be derived from */ CK_ATTRIBUTE local; /* Generated locally */ CK_ATTRIBUTE sensitive; /* TRUE: key is sensitive */ CK_ATTRIBUTE encrypt; /* TRUE: can encrypt */ CK_ATTRIBUTE decrypt; /* TRUE: can decrypt */ CK_ATTRIBUTE sign; /* TRUE: sign as an appendix */ CK_ATTRIBUTE verify; /* TRUE: sign is an appendix */ CK_ATTRIBUTE wrap; /* TRUE: if can wrap other keys */ CK_ATTRIBUTE unwrap; /* TRUE: if can unwrap other keys */ CK_ATTRIBUTE extractable; /* TRUE: can be extracted */ CK_ATTRIBUTE always_sens; /* TRUE: if sensitive always been T */ CK_ATTRIBUTE never_extract;/* TRUE: if extractable never set T */ CK_ATTRIBUTE value; /* Key value */ CK_ATTRIBUTE len; /* Length in bytes of key */ } SecretKey; CK_ATTRIBUTE generic[28]; // PrivKey is the largest structure with 28 Attributes } SC_OBJECT; typedef SC_OBJECT * SC_OBJECT_PTR; typedef struct SC_SESSION_HANDLE * SC_SESSION_HANDLE_PTR; typedef struct SC_OBJECT_HANDLE * SC_OBJECT_HANDLE_PTR; typedef struct SC_SESSION_HANDLE { CK_SESSION_HANDLE session; SC_SESSION_HANDLE_PTR next; } SC_SESSION_HANDLE; typedef struct SC_OBJECT_HANDLE { CK_OBJECT_HANDLE object; SC_OBJECT_HANDLE_PTR next; } SC_OBJECT_HANDLE; #endif opencryptoki+dfsg/usr/include/pkcs11/pkcs11.h0000644000175000017500000003605012630407154020114 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (c) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef OPENCRYPTOKI_PKCS11_H #define OPENCRYPTOKI_PKCS11_H #include #include #endif opencryptoki+dfsg/usr/include/pkcs11/slotmgr.h0000755000175000017500000005301312630407154020502 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/slotmgr.h,v 1.7 2006/04/17 18:23:06 danielhjones Exp $ */ // /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ // //Slot Manager Daemon Constants... // // #include #include #include #include #include #ifndef _SLOTMGR_H #define _SLOTMGR_H #define TOK_PATH SBIN_PATH "/pkcsslotd" #define OCK_API_LOCK_FILE LOCKDIR_PATH "/LCK..APIlock" #define SOCKET_FILE_PATH "/var/run/pkcsslotd.socket" #define PID_FILE_PATH "/var/run/pkcsslotd.pid" #define OCK_CONFIG OCK_CONFDIR "/opencryptoki.conf" #ifndef CK_BOOL #define CK_BOOL CK_BBOOL #endif /* CK_BOOL */ #ifndef TEST_COND_VARS #define TEST_COND_VARS 0 #endif /* TEST_COND_VARS */ #define NUMBER_SLOTS_MANAGED 6 #define NUMBER_PROCESSES_ALLOWED 1000 // // Per Process Data structure // one entry in the table is grabbed by each process // when it attaches to the shared memory and released // when the C_Finalize is called. typedef struct{ pthread_mutex_t proc_mutex; pthread_cond_t proc_slot_cond; CK_BOOL inuse; // flag indicating if the entry is in use pid_t proc_id; // This could also be used to indicate inuse. however // we will actualy use it to provide a check for a bad // process which did not C_finalize and remove itself // properly. uint32 slotmap; // Bit map of the slots with events App uses this // in the C_WaitForSlotEvent call uint8 blocking; // Flag to use if a thread is blocking on the condition // variable Used by C_Finalize to wake up the uint8 error ; // indication of an error causing the thread sleeping on the // condition variable to wakeup. uint32 slot_session_count[NUMBER_SLOTS_MANAGED]; // Per process session // count for garbage collection clean up of the global // session count. time_t reg_time; // Time application registered } Slot_Mgr_Proc_t; // // Shared Memory Region of Slot information // // Slot info structure which contains the PKCS11 CK_SLOT_INFO // as well as the local information typedef struct{ CK_SLOT_ID slot_number; CK_BOOL present; CK_SLOT_INFO pk_slot; char dll_location[NAME_MAX+1]; // location of slot management DLL char slot_init_fcn[NAME_MAX+1]; // function to call to initialize the token in the slot }Slot_Info_t; #ifdef PKCS64 /* * Constant size types and structures to allow 32-bit daemon to work with * 64-bit libraries. * * Note - ulong long is 8 bytes for both 32-bit and 64-bit applications. * */ typedef signed long long pid_t_64; typedef unsigned long long time_t_64; typedef unsigned long long CK_SLOT_ID_64; typedef unsigned long long CK_FLAGS_64; typedef struct CK_INFO_64 { CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ CK_CHAR manufacturerID[32]; /* blank padded */ CK_CHAR pad1[6]; /* pad for dword alignment */ CK_FLAGS_64 flags; /* must be zero */ /* libraryDescription and libraryVersion are new for v2.0 */ CK_CHAR libraryDescription[32]; /* blank padded */ CK_VERSION libraryVersion; /* version of library */ CK_CHAR pad2[6]; /* pad for dword alignment */ } CK_INFO_64; typedef CK_INFO_64 CK_PTR CK_INFO_PTR_64; typedef struct CK_SLOT_INFO_64 { CK_CHAR slotDescription[64]; /* blank padded */ CK_CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS_64 flags; /* hardwareVersion and firmwareVersion are new for v2.0 */ CK_VERSION hardwareVersion; /* version of hardware */ CK_VERSION firmwareVersion; /* version of firmware */ CK_CHAR pad[4]; /* pad for dword alignment */ } CK_SLOT_INFO_64; typedef struct Slot_Mgr_Proc_t_64 { // pthread_cond_t proc_slot_cond; CK_BOOL inuse; // flag indicating if the entry is in use pid_t proc_id;// This could also be used to indicate inuse. however // we will actualy use it to provide a check for a bad // process which did not C_finalize and remove itself // properly. uint32 slotmap; // Bit map of the slots with events App uses this // in the C_WaitForSlotEvent call uint8 blocking; // Flag to use if a thread is blocking on the condition // variable Used by C_Finalize to wake up the uint8 error ; // indication of an error causing the thread sleeping on the // condition variable to wakeup. uint32 slot_session_count[NUMBER_SLOTS_MANAGED]; // Per process session // count for garbage collection clean up of the global // session count. time_t_64 reg_time; // Time application registered } Slot_Mgr_Proc_t_64; // // Shared Memory Region of Slot information // // Slot info structure which contains the PKCS11 CK_SLOT_INFO // as well as the local information typedef struct { CK_SLOT_ID_64 slot_number; CK_BOOL present; char pad1[7]; // pad for dword alignment CK_SLOT_INFO_64 pk_slot; char dll_location[NAME_MAX+1]; // location of slot's DLL char confname[NAME_MAX+1]; // token specific config file }Slot_Info_t_64; typedef struct { /* Information that the API calls will use. */ uint32 slot_global_sessions[NUMBER_SLOTS_MANAGED]; Slot_Mgr_Proc_t_64 proc_table[NUMBER_PROCESSES_ALLOWED]; } Slot_Mgr_Shr_t; typedef struct { uint8 num_slots; CK_INFO_64 ck_info; Slot_Info_t_64 slot_info[NUMBER_SLOTS_MANAGED]; } Slot_Mgr_Socket_t; #else // PKCS64 typedef struct { /* Information that the API calls will use. */ uint32 slot_global_sessions[NUMBER_SLOTS_MANAGED]; Slot_Mgr_Proc_t proc_table[NUMBER_PROCESSES_ALLOWED]; } Slot_Mgr_Shr_t; typedef struct { uint8 num_slots; CK_INFO ck_info; Slot_Info_t slot_info[NUMBER_SLOTS_MANAGED]; } Slot_Mgr_Socket_t; #endif // PKCS64 // Loging type constants // #define ERROR 1 #define INFO 2 // Call to populate the shared memory #define STR "01234567890123456789012345678901" #define MFG "IBM " #define LIB "Meta PKCS11 LIBRARY " #define MAJOR_V 1 #define MINOR_V 2 #ifndef CRYPTOKI_API_MAJOR_V #define CRYPTOKI_API_MAJOR_V 0x2 #endif #ifndef CRYPTOKI_API_MINOR_V #define CRYPTOKI_API_MINOR_V 0x14 #endif #define LIB_MAJOR_V 1 #define LIB_MINOR_V 4 #define RESTART_SYS_CALLS 1 #endif /* _SLOTMGR_H */ opencryptoki+dfsg/usr/include/pkcs11/Makefile.am0000644000175000017500000000024412630407153020670 0ustar xnoxxnoxopencryptoki_headers = apiclient.h pkcs11types.h pkcs11.h opencryptokiincludedir=$(includedir)/opencryptoki opencryptokiinclude_HEADERS = $(opencryptoki_headers) opencryptoki+dfsg/usr/include/pkcs11/apictl.h0000755000175000017500000004133112630407154020267 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/apictl.h,v 1.2 2005/02/22 20:47:32 mhalcrow Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include #ifndef _APILOCAL_H #define _APILOCAL_H // SAB Add a linked list of STDLL's loaded to // only load and get list once, but let multiple slots us it. typedef struct{ CK_BOOL DLLoaded; // Flag to indicate if the STDDL has been loaded char *dll_name; // Malloced space to copy the name. void *dlop_p; int dll_load_count; // STDLL_FcnList_t *FcnList; // Function list pointer for the STDLL } DLL_Load_t; typedef struct { CK_BOOL DLLoaded; // Flag to indicate if the STDDL has been loaded void *dlop_p; // Pointer to the value returned from the DL open STDLL_FcnList_t *FcnList; // Function list pointer for the STDLL DLL_Load_t *dll_information; void (*pSTfini)(); // Addition of Final function. CK_RV (*pSTcloseall)(); // Addition of close all for leeds code } API_Slot_t; // Per process API structure. // Allocate one per process on the C_Initialize. This will be // a global type for the API and will be used through out. // typedef struct { pid_t Pid; pthread_mutex_t ProcMutex; // Mutex for the process level should this be necessary key_t shm_tok; struct btree sess_btree; pthread_mutex_t SessListMutex; /*used to lock around btree accesses */ void *SharedMemP; Slot_Mgr_Socket_t SocketDataP; uint16 MgrProcIndex; // Index into shared memory for This process ctl block API_Slot_t SltList[NUMBER_SLOTS_MANAGED]; DLL_Load_t DLLs[NUMBER_SLOTS_MANAGED]; // worst case we have a separate DLL per slot } API_Proc_Struct_t; #endif opencryptoki+dfsg/usr/include/pkcs11/pkcs32.h0000755000175000017500000005046712630407154020132 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/pkcs32.h,v 1.2 2005/02/22 20:47:35 mhalcrow Exp $ */ //---------------------------------------------------------------------------- /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ // // File: PKCS11Types.h // // //---------------------------------------------------------------------------- #ifndef _PKCS1132_H_ #define _PKCS1132_H_ #ifdef __cplusplus extern "C" { #endif /* These are the new definitions need for the structures in * leeds_stdll largs.h (and elsewhere) */ typedef unsigned int CK_ULONG_32; typedef int CK_LONG_32; typedef unsigned int * CK_ULONG_PTR_32; typedef CK_ULONG_32 CK_MECHANISM_TYPE_32; typedef CK_ULONG_32 CK_SESSION_HANDLE_32; typedef CK_ULONG_32 CK_SLOT_ID_32; typedef CK_ULONG_32 CK_FLAGS_32; typedef CK_ULONG_32 CK_USER_TYPE_32; typedef CK_ULONG_32 CK_OBJECT_HANDLE_32; typedef CK_OBJECT_HANDLE_32 * CK_OBJECT_HANDLE__PTR_32; typedef CK_ULONG_32 CK_ATTRIBUTE_TYPE_32; typedef CK_ULONG_32 CK_STATE_32; typedef CK_ULONG_32 CK_OBJECT_CLASS_32; typedef CK_BYTE CK_PTR CK_BYTE_PTR_32; typedef CK_CHAR CK_PTR CK_CHAR_PTR_32; typedef CK_ULONG_32 CK_MAC_GENERAL_PARAMS_32; typedef CK_MAC_GENERAL_PARAMS_32 CK_PTR CK_MAC_GENERAL_PARAMS_PTR_32; // SSL 3 Mechanism pointers for the Leeds card. typedef struct CK_SSL3_RANDOM_DATA_32 { CK_BYTE_PTR_32 pClientRandom; CK_ULONG_32 ulClientRandomLen; CK_BYTE_PTR_32 pServerRandom; CK_ULONG_32 ulServerRandomLen; } CK_SSL3_RANDOM_DATA_32; typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS_32 { CK_SSL3_RANDOM_DATA_32 RandomInfo; CK_VERSION_PTR pVersion; } CK_SSL3_MASTER_KEY_DERIVE_PARAMS_32; typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS_32 CK_PTR \ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR_32; typedef struct CK_SSL3_KEY_MAT_OUT_32 { CK_OBJECT_HANDLE_32 hClientMacSecret; CK_OBJECT_HANDLE_32 hServerMacSecret; CK_OBJECT_HANDLE_32 hClientKey; CK_OBJECT_HANDLE_32 hServerKey; CK_BYTE_PTR_32 pIVClient; CK_BYTE_PTR_32 pIVServer; } CK_SSL3_KEY_MAT_OUT_32; typedef CK_SSL3_KEY_MAT_OUT_32 CK_PTR CK_SSL3_KEY_MAT_OUT_PTR_32; typedef struct CK_SSL3_KEY_MAT_PARAMS_32 { CK_ULONG_32 ulMacSizeInBits; CK_ULONG_32 ulKeySizeInBits; CK_ULONG_32 ulIVSizeInBits; CK_BBOOL bIsExport; CK_SSL3_RANDOM_DATA_32 RandomInfo; CK_SSL3_KEY_MAT_OUT_PTR_32 pReturnedKeyMaterial; } CK_SSL3_KEY_MAT_PARAMS_32; typedef CK_SSL3_KEY_MAT_PARAMS_32 CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR_32; typedef struct CK_KEY_DERIVATION_STRING_DATA_32 { CK_BYTE_PTR_32 pData; CK_ULONG_32 ulLen; } CK_KEY_DERIVATION_STRING_DATA_32; typedef CK_KEY_DERIVATION_STRING_DATA_32 CK_PTR \ CK_KEY_DERIVATION_STRING_DATA_PTR_32; typedef struct CK_TOKEN_INFO_32 { CK_CHAR label[32]; /* blank padded */ CK_CHAR manufacturerID[32]; /* blank padded */ CK_CHAR model[16]; /* blank padded */ CK_CHAR serialNumber[16]; /* blank padded */ CK_FLAGS_32 flags; /* see below */ // SAB FIXME needs to be 32 bit /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been * changed from CK_USHORT to CK_ULONG for v2.0 */ CK_ULONG_32 ulMaxSessionCount; /* max open sessions */ CK_ULONG_32 ulSessionCount; /* sess. now open */ CK_ULONG_32 ulMaxRwSessionCount; /* max R/W sessions */ CK_ULONG_32 ulRwSessionCount; /* R/W sess. now open */ CK_ULONG_32 ulMaxPinLen; /* in bytes */ CK_ULONG_32 ulMinPinLen; /* in bytes */ CK_ULONG_32 ulTotalPublicMemory; /* in bytes */ CK_ULONG_32 ulFreePublicMemory; /* in bytes */ CK_ULONG_32 ulTotalPrivateMemory; /* in bytes */ CK_ULONG_32 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_32; typedef struct CK_SESSION_INFO_32 { CK_SLOT_ID_32 slotID; CK_STATE_32 state; CK_FLAGS_32 flags; /* see below */ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for * v2.0 */ CK_ULONG_32 ulDeviceError; /* device-dependent error code */ } CK_SESSION_INFO_32; typedef struct CK_MECHANISM_INFO_32 { CK_ULONG_32 ulMinKeySize; CK_ULONG_32 ulMaxKeySize; CK_FLAGS_32 flags; } CK_MECHANISM_INFO_32; /* CK_MECHANISM_32 is a structure that specifies a particular * mechanism */ typedef struct CK_MECHANISM_32 { CK_MECHANISM_TYPE_32 mechanism; CK_VOID_PTR pParameter; /* ulParameterLen was changed from CK_USHORT to CK_ULONG for * v2.0 */ CK_ULONG_32 ulParameterLen; /* in bytes */ } CK_MECHANISM_32; /* CK_ATTRIBUTE is a structure that includes the type, length * and value of an attribute */ typedef struct CK_ATTRIBUTE_32 { CK_ATTRIBUTE_TYPE_32 type; CK_ULONG_32 pValue; // SAB XXX XXX Was CK_VOID_PTR which is 64Bit /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ CK_ULONG_32 ulValueLen; /* in bytes */ } CK_ATTRIBUTE_32; #pragma pack() #ifdef __cplusplus } #endif #endif // _PKCS1132_HS_H_ opencryptoki+dfsg/usr/include/pkcs11/stdll.h0000755000175000017500000007370212630407154020144 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/stdll.h,v 1.2 2005/02/22 20:47:40 mhalcrow Exp $ */ // /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ // // API Local control blocks within the PKCS11 Meta API // // // #include #include #include #include #ifndef _STDLL_H #define _STDLL_H typedef struct { CK_SLOT_ID slotID; CK_SESSION_HANDLE sessionh; } ST_SESSION_T ; typedef ST_SESSION_T ST_SESSION_HANDLE; /* 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 CK_RV (CK_PTR ST_C_Initialize) (void **ppFunctionList, CK_SLOT_ID slotID, CK_CHAR_PTR pConfName); typedef CK_RV (CK_PTR ST_C_Finalize) (CK_VOID_PTR pReserved); typedef CK_RV (CK_PTR ST_C_Terminate) (void); typedef CK_RV (CK_PTR ST_C_GetInfo) (CK_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_GetFunctionList) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); typedef CK_RV (CK_PTR ST_C_GetSlotList) (CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pusCount); typedef CK_RV (CK_PTR ST_C_GetSlotInfo) (CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_GetTokenInfo) (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_GetMechanismList) (CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pusCount); typedef CK_RV (CK_PTR ST_C_GetMechanismInfo) (CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_InitToken) (CK_SLOT_ID slotID, CK_CHAR_PTR pPin, CK_ULONG usPinLen, CK_CHAR_PTR pLabel); typedef CK_RV (CK_PTR ST_C_InitPIN) (ST_SESSION_T *hSession, CK_CHAR_PTR pPin, CK_ULONG usPinLen); typedef CK_RV (CK_PTR ST_C_SetPIN) (ST_SESSION_T *hSession, CK_CHAR_PTR pOldPin, CK_ULONG usOldLen, CK_CHAR_PTR pNewPin, CK_ULONG usNewLen); // typedef CK_RV (CK_PTR ST_C_OpenSession) // (CK_SLOT_ID slotID, CK_FLAGS flags, // CK_VOID_PTR pApplication, // CK_RV (*Notify) (CK_SESSION_HANDLE hSession, // CK_NOTIFICATION event, CK_VOID_PTR pApplication), // CK_SESSION_HANDLE_PTR phSession); typedef CK_RV (CK_PTR ST_C_OpenSession) (CK_SLOT_ID slotID, CK_FLAGS flags, CK_SESSION_HANDLE_PTR phSession); typedef CK_RV (CK_PTR ST_C_CloseSession) (ST_SESSION_T *hSession); typedef CK_RV (CK_PTR ST_C_CloseAllSessions) (CK_SLOT_ID slotID); typedef CK_RV (CK_PTR ST_C_GetSessionInfo) (ST_SESSION_T *hSession, CK_SESSION_INFO_PTR pInfo); typedef CK_RV (CK_PTR ST_C_GetOperationState) (ST_SESSION_T *hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen); typedef CK_RV (CK_PTR ST_C_SetOperationState) (ST_SESSION_T *hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey); typedef CK_RV (CK_PTR ST_C_Login)(ST_SESSION_T *hSession, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG usPinLen); typedef CK_RV (CK_PTR ST_C_Logout)(ST_SESSION_T *hSession); typedef CK_RV (CK_PTR ST_C_CreateObject) (ST_SESSION_T *hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phObject); typedef CK_RV (CK_PTR ST_C_CopyObject) (ST_SESSION_T *hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phNewObject); typedef CK_RV (CK_PTR ST_C_DestroyObject) (ST_SESSION_T *hSession, CK_OBJECT_HANDLE hObject); typedef CK_RV(CK_PTR ST_C_GetObjectSize) (ST_SESSION_T *hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pusSize); typedef CK_RV(CK_PTR ST_C_GetAttributeValue) (ST_SESSION_T *hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV(CK_PTR ST_C_SetAttributeValue) (ST_SESSION_T *hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV (CK_PTR ST_C_FindObjectsInit) (ST_SESSION_T *hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); typedef CK_RV (CK_PTR ST_C_FindObjects) (ST_SESSION_T *hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG usMaxObjectCount, CK_ULONG_PTR pusObjectCount); typedef CK_RV (CK_PTR ST_C_FindObjectsFinal) (ST_SESSION_T *hSession); typedef CK_RV (CK_PTR ST_C_EncryptInit) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_Encrypt) (ST_SESSION_T *hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pusEncryptedDataLen); typedef CK_RV (CK_PTR ST_C_EncryptUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pusEncryptedPartLen); typedef CK_RV (CK_PTR ST_C_EncryptFinal) (ST_SESSION_T *hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pusLastEncryptedPartLen); typedef CK_RV (CK_PTR ST_C_DecryptInit) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_Decrypt) (ST_SESSION_T *hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG usEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pusDataLen); typedef CK_RV (CK_PTR ST_C_DecryptUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG usEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pusPartLen); typedef CK_RV (CK_PTR ST_C_DecryptFinal) (ST_SESSION_T *hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pusLastPartLen); typedef CK_RV (CK_PTR ST_C_DigestInit) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism); typedef CK_RV (CK_PTR ST_C_Digest) (ST_SESSION_T *hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pusDigestLen); typedef CK_RV (CK_PTR ST_C_DigestUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR ST_C_DigestKey) (ST_SESSION_T *hSession, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_DigestFinal) (ST_SESSION_T *hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pusDigestLen); typedef CK_RV (CK_PTR ST_C_SignInit) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_Sign) (ST_SESSION_T *hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR ST_C_SignUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR ST_C_SignFinal) (ST_SESSION_T *hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR ST_C_SignRecoverInit) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_SignRecover) (ST_SESSION_T *hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen); typedef CK_RV (CK_PTR ST_C_VerifyInit) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_Verify) (ST_SESSION_T *hSession, CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen); typedef CK_RV (CK_PTR ST_C_VerifyUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pPart, CK_ULONG usPartLen); typedef CK_RV (CK_PTR ST_C_VerifyFinal) (ST_SESSION_T *hSession, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen); typedef CK_RV (CK_PTR ST_C_VerifyRecoverInit) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); typedef CK_RV (CK_PTR ST_C_VerifyRecover) (ST_SESSION_T *hSession, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pusDataLen); typedef CK_RV (CK_PTR ST_C_DigestEncryptUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); typedef CK_RV (CK_PTR ST_C_DecryptDigestUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); typedef CK_RV (CK_PTR ST_C_SignEncryptUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); typedef CK_RV (CK_PTR ST_C_DecryptVerifyUpdate) (ST_SESSION_T *hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); typedef CK_RV (CK_PTR ST_C_GenerateKey) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR ST_C_GenerateKeyPair) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG usPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG usPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPrivateKey, CK_OBJECT_HANDLE_PTR phPublicKey); typedef CK_RV (CK_PTR ST_C_WrapKey) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pusWrappedKeyLen); typedef CK_RV (CK_PTR ST_C_UnwrapKey) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG usWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR ST_C_DeriveKey) (ST_SESSION_T *hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount, CK_OBJECT_HANDLE_PTR phKey); typedef CK_RV (CK_PTR ST_C_SeedRandom) (ST_SESSION_T *hSession, CK_BYTE_PTR pSeed, CK_ULONG usSeedLen); typedef CK_RV (CK_PTR ST_C_GenerateRandom) (ST_SESSION_T *hSession, CK_BYTE_PTR pRandomData, CK_ULONG usRandomLen); typedef CK_RV (CK_PTR ST_C_GetFunctionStatus) (ST_SESSION_T *hSession); typedef CK_RV (CK_PTR ST_C_CancelFunction) (ST_SESSION_T *hSession); typedef CK_RV (CK_PTR ST_Notify) (ST_SESSION_T *hSession, CK_NOTIFICATION event, CK_VOID_PTR pApplication); typedef CK_RV (CK_PTR ST_C_WaitForSlotEvent) (CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved); struct ST_FCN_LIST{ // Need initialization function But it is different than // the C_Initialize ST_C_Initialize ST_Initialize; ST_C_GetTokenInfo ST_GetTokenInfo; ST_C_GetMechanismList ST_GetMechanismList; ST_C_GetMechanismInfo ST_GetMechanismInfo; ST_C_InitToken ST_InitToken; ST_C_InitPIN ST_InitPIN; ST_C_SetPIN ST_SetPIN; ST_C_OpenSession ST_OpenSession; ST_C_CloseSession ST_CloseSession; ST_C_GetSessionInfo ST_GetSessionInfo; ST_C_GetOperationState ST_GetOperationState; // Not used by Netscape ST_C_SetOperationState ST_SetOperationState; // Not used by Netscape ST_C_Login ST_Login; ST_C_Logout ST_Logout; ST_C_CreateObject ST_CreateObject; ST_C_CopyObject ST_CopyObject; ST_C_DestroyObject ST_DestroyObject; ST_C_GetObjectSize ST_GetObjectSize; ST_C_GetAttributeValue ST_GetAttributeValue; ST_C_SetAttributeValue ST_SetAttributeValue; ST_C_FindObjectsInit ST_FindObjectsInit; ST_C_FindObjects ST_FindObjects; ST_C_FindObjectsFinal ST_FindObjectsFinal; ST_C_EncryptInit ST_EncryptInit; ST_C_Encrypt ST_Encrypt; ST_C_EncryptUpdate ST_EncryptUpdate; // Not used by Netscape ST_C_EncryptFinal ST_EncryptFinal; // Not used by Netscape ST_C_DecryptInit ST_DecryptInit; ST_C_Decrypt ST_Decrypt; ST_C_DecryptUpdate ST_DecryptUpdate; // Not used by Netscape ST_C_DecryptFinal ST_DecryptFinal; // Not used by Netscape ST_C_DigestInit ST_DigestInit; ST_C_Digest ST_Digest; ST_C_DigestUpdate ST_DigestUpdate; ST_C_DigestKey ST_DigestKey; ST_C_DigestFinal ST_DigestFinal; ST_C_SignInit ST_SignInit; ST_C_Sign ST_Sign; ST_C_SignUpdate ST_SignUpdate; ST_C_SignFinal ST_SignFinal; ST_C_SignRecoverInit ST_SignRecoverInit; ST_C_SignRecover ST_SignRecover; ST_C_VerifyInit ST_VerifyInit; ST_C_Verify ST_Verify; ST_C_VerifyUpdate ST_VerifyUpdate; ST_C_VerifyFinal ST_VerifyFinal; ST_C_VerifyRecoverInit ST_VerifyRecoverInit; ST_C_VerifyRecover ST_VerifyRecover; ST_C_DigestEncryptUpdate ST_DigestEncryptUpdate; ST_C_DecryptDigestUpdate ST_DecryptDigestUpdate; ST_C_SignEncryptUpdate ST_SignEncryptUpdate; ST_C_DecryptVerifyUpdate ST_DecryptVerifyUpdate; ST_C_GenerateKey ST_GenerateKey; ST_C_GenerateKeyPair ST_GenerateKeyPair; ST_C_WrapKey ST_WrapKey; // Netscape optionsl will use En/Decrypt ST_C_UnwrapKey ST_UnwrapKey; ST_C_DeriveKey ST_DeriveKey; ST_C_SeedRandom ST_SeedRandom; ST_C_GenerateRandom ST_GenerateRandom; // Question if these have to be implemented for Netscape support ST_C_GetFunctionStatus ST_GetFunctionStatus; ST_C_CancelFunction ST_CancelFunction; }; typedef struct ST_FCN_LIST STDLL_FcnList_t; #endif opencryptoki+dfsg/usr/include/pkcs11/pkcs11err.h0000755000175000017500000004372112630407154020633 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/include/pkcs11/pkcs11err.h,v 1.2 2006/04/05 20:07:44 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _SLOTD_ERR_H #define _SLOTD_ERR_H #ifdef DEV #ifndef ASSERT #define ASSERT(_expr) _ASSERT((_expr),(__FILE__),(__LINE__)) #define _ASSERT(_expr, _fname, _line) \ if (!(_expr)) { \ ErrLog("****** ****** ***** ***** ***** ***** ***** ***** ***** ****** ******"); \ ErrLog("****** ASSERTION FAILED '%s'; %s, line %d", (#_expr), (_fname), (_line)); \ ErrLog("****** ****** ***** ***** ***** ***** ***** ***** ***** ****** ******"); \ ErrLog("Exiting."); \ abort(); \ } #endif /* ASSERT */ #ifndef ASSERT_FUNC #define ASSERT_FUNC(_expr, _func) _ASSERT_FUNC((_expr), (_func), (__FILE__), (__LINE__)) #define _ASSERT_FUNC(_expr, _func, _fname, _line) \ if (!(_expr)) { \ ErrLog("****** ****** ***** ***** ***** ***** ***** ***** ***** ****** ******"); \ ErrLog("****** ASSERTION FAILED '%s'; %s, line %d", (#_expr), (_fname), (_line)); \ ErrLog("Additional information from '%s':\n", (#_func)); \ { _func; } \ ErrLog("End of additional information from '%s'\n", (#_func) ); \ ErrLog("****** ****** ***** ***** ***** ***** ***** ***** ***** ****** ******"); \ ErrLog("Exiting."); \ abort(); \ } #endif /* ASSERT_FUNC */ #else #ifndef ASSERT #define ASSERT(_expr) {} #endif /* ASSERT */ #ifndef ASSERT_FUNC #define ASSERT_FUNC(_expr, _func_to_call) {} #endif /* ASSERT_FUNC */ #endif /* DEV */ #define SEV_EXPECTED 0x01 #define SEV_ALLOWED 0x02 #define SEV_ERROR 0x03 #define SEV_FATAL 0x04 typedef struct _ConstInfo { unsigned const int Code; unsigned const char Name[128]; /* UCHAR Descrip[256]; */ } ConstInfo, *pConstInfo; #define CONSTINFO(_X) { (_X), (#_X) } const unsigned char *ConstName ( pConstInfo pInfoArray, unsigned int InfoArraySize, unsigned int ConstValue ); #ifdef _DAE_H const unsigned char *DAEConst ( unsigned int Val ); #endif /* _DAE_H */ #ifdef _H_ERRNO const unsigned char *SysConst ( unsigned int Val ); #define SysError( _x ) SysConst((_x)) #endif /* _H_ERRNO */ #ifdef _H_SIGNAL const unsigned char *SignalConst ( unsigned int Val ); #endif /* _H_SIGNAL */ #ifdef _H_ODMI const unsigned char *ODMConst ( unsigned int Val ); #endif /* _H_ODMI */ #ifdef _PKCS11TYPES_H_ const unsigned char *PkcsReturn ( unsigned int Val ); const unsigned char *PkcsFlags ( unsigned int Val ); const unsigned char *PkcsMechanism ( unsigned int Val ); const unsigned char *PkcsObject ( unsigned int Val ); const unsigned char *PkcsKey ( unsigned int Val ); const unsigned char *PkcsAttribute ( unsigned int Val ); #endif /* _PKCS11TYPES_H_ */ const unsigned char *ResponseSeverity( unsigned int Val ); #endif /* _SLOTD_ERR_H */ opencryptoki+dfsg/usr/sbin/0000755000175000017500000000000012630407154015043 5ustar xnoxxnoxopencryptoki+dfsg/usr/sbin/pkcscca/0000755000175000017500000000000012630407154016452 5ustar xnoxxnoxopencryptoki+dfsg/usr/sbin/pkcscca/pkcscca.h0000644000175000017500000000727312630407154020243 0ustar xnoxxnox/* * Licensed materials - Property of IBM * * pkcscca - A tool for PKCS#11 CCA token. * Currently, only migrates CCA private token objects from using a * CCA cipher to using a software cipher. * * Copyright (C) International Business Machines Corp. 2014 * */ #ifndef __PKCSCCA_H_ #define __PKCSCCA_H_ #define CCA_LIBRARY "libcsulcca.so" #define TOK_DATASTORE CONFIG_PATH "/ccatok" #define MASTER_KEY_SIZE 64 #define SHA1_HASH_SIZE 20 #define MD5_HASH_SIZE 16 #define DES_BLOCK_SIZE 8 #define DES_KEY_SIZE 8 #define CCA_SUCCESS 0 #define AES_NAME "AES" #define DES_NAME "DES" #define DES2_NAME "2DES" #define DES3_NAME "3DES" #define ECC_NAME "ECC" #define HMAC_NAME "HMAC" #define RSA_NAME "RSA" #define BAD_NAME "Unknown" #define MK_AES 1 #define MK_APKA 2 #define MK_ASYM 3 #define MK_SYM 4 #define compute_sha1(a,b,c) compute_hash(HASH_SHA1,b,a,c) #define compute_md5(a,b,c) compute_hash(HASH_MD5,b,a,c) #define HASH_SHA1 1 #define HASH_MD5 2 typedef struct _MASTER_KEY_FILE_T { CK_BYTE key[MASTER_KEY_SIZE]; CK_BYTE sha_hash[SHA1_HASH_SIZE]; } MASTER_KEY_FILE_T; CK_RV sw_des3_cbc(CK_BYTE *, CK_ULONG, CK_BYTE *, CK_ULONG *, CK_BYTE *, CK_BYTE *, CK_BYTE); #define sw_des3_cbc_encrypt(clear, len, cipher, len2, iv, key) \ sw_des3_cbc(clear, len, cipher, len2, iv, key, 1) #define sw_des3_cbc_decrypt(clear, len, cipher, len2, iv, key) \ sw_des3_cbc(clear, len, cipher, len2, iv, key, 0) /* from host_defs.h */ #include "pkcs32.h" typedef struct _TWEAK_VEC { int allow_weak_des ; int check_des_parity ; int allow_key_mods ; int netscape_mods ; } TWEAK_VEC; typedef struct _TOKEN_DATA { CK_TOKEN_INFO_32 token_info; CK_BYTE user_pin_sha[3 * DES_BLOCK_SIZE]; CK_BYTE so_pin_sha[3 * DES_BLOCK_SIZE]; CK_BYTE next_token_object_name[8]; TWEAK_VEC tweak_vector; } TOKEN_DATA; #define EVP_SUCCESS 1 #define HASH_SHA1 1 #define HASH_MD5 2 #define print_openssl_errors() \ do { \ ERR_load_crypto_strings(); \ ERR_print_errors_fp(stderr); \ } while (0) int compute_hash(int hash_type, int buf_size, char* buf, char* digest); #define compute_sha(a,b,c) compute_hash(HASH_SHA1,b,a,c) #define compute_md5(a,b,c) compute_hash(HASH_MD5,b,a,c) char *p11strerror(CK_RV); #define p11_error(s,rc) fprintf(stderr, "%s:%d %s failed: rc=0x%lX (%s)\n", __FILE__, \ __LINE__, s, rc, p11strerror(rc)) #define print_error(x, ...) fprintf(stderr, "%s:%d " x "\n", __FILE__, __LINE__, ##__VA_ARGS__) #define cca_error(f,rc,rsn) fprintf(stderr, "%s:%d " f " failed. return code: %ld, reason" \ "code: %ld\n", __FILE__, __LINE__, rc, rsn) #define print_hex(x, y) \ do { \ unsigned char *hex = x; \ int i; \ for (i = 0; i < y; i++) { \ printf("%02x", hex[i]); \ if (((i+1) % 32) == 0) \ printf("\n"); \ else if (((i+1) % 4) == 0) \ printf(" "); \ } \ } while (0) struct key { CK_OBJECT_HANDLE handle; CK_ULONG type; CK_BYTE *opaque_attr; CK_ULONG attr_len; CK_CHAR_PTR label; struct key *next; }; struct algo { unsigned char *rule_array; unsigned char *name; long rule_array_count; }; struct key_count { int aes; int des; int des2; int des3; int ecc; int hmac; int rsa; }; #endif opencryptoki+dfsg/usr/sbin/pkcscca/Makefile.am0000644000175000017500000000062412630407154020510 0ustar xnoxxnoxsbin_PROGRAMS=pkcscca pkcscca_CFLAGS = -DSTDLL_NAME=\"pkcscca\" pkcscca_LDFLAGS = -lcrypto -ldl # Not all versions of automake observe sbinname_CFLAGS AM_CFLAGS = -DSTDLL_NAME=\"pkcscca\" pkcscca_SOURCES = ../../lib/pkcs11/common/p11util.c \ ../../lib/pkcs11/common/sw_crypt.c \ ../../lib/pkcs11/common/trace.c \ pkcscca.c INCLUDES = -I. -I../../include/pkcs11 -I../../lib/pkcs11/common opencryptoki+dfsg/usr/sbin/pkcscca/pkcscca.c0000644000175000017500000012175412630407154020237 0ustar xnoxxnox/* * Licensed materials - Property of IBM * * pkcscca - A tool for PKCS#11 CCA token. * Currently, only migrates CCA private token objects from CCA cipher * to using a software cipher. * * * Copyright (C) International Business Machines Corp. 2014 * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sw_crypt.h" #include "pkcscca.h" int v_flag = 0; void *p11_lib = NULL; void (*CSNDKTC)(); void (*CSNBKTC)(); void (*CSNBKTC2)(); void (*CSNBDEC)(); void *lib_csulcca; struct algo aes = {"RTCMK AES ", "AES", 2}; struct algo des = {"RTCMK ", "DES", 1}; struct algo hmac = {"RTCMK HMAC ", "HMAC", 2}; struct algo ecc = {"RTCMK ECC ", "ECC", 2}; struct algo rsa = {"RTCMK ", "RSA", 1}; int compute_hash(int hash_type, int buf_size, char *buf, char *digest) { EVP_MD_CTX md_ctx; unsigned int result_size; int rc; switch (hash_type) { case HASH_SHA1: rc = EVP_DigestInit(&md_ctx, EVP_sha1()); break; case HASH_MD5: rc = EVP_DigestInit(&md_ctx, EVP_md5()); break; default: return -1; break; } if (rc != 1) { fprintf(stderr, "EVP_DigestInit() failed: rc = %d\n", rc); return -1; } rc = EVP_DigestUpdate(&md_ctx, buf, buf_size); if (rc != 1) { fprintf(stderr, "EVP_DigestUpdate() failed: rc = %d\n", rc); return -1; } result_size = EVP_MD_CTX_size(&md_ctx); rc = EVP_DigestFinal(&md_ctx, (unsigned char *)digest, &result_size); if (rc != 1) { fprintf(stderr, "EVP_DigestFinal() failed: rc = %d\n", rc); return -1; } return 0; } int cca_decrypt(unsigned char *in_data, unsigned long in_data_len, unsigned char *out_data, unsigned long *out_data_len, unsigned char *init_v, unsigned char *key_value) { long return_code, reason_code, rule_array_count, length; unsigned char chaining_vector[18]; unsigned char rule_array[256]; length = in_data_len; rule_array_count = 1; memcpy(rule_array, "CBC ", 8); CSNBDEC(&return_code, &reason_code, NULL, NULL, key_value, &length, in_data, init_v, &rule_array_count, rule_array, chaining_vector, out_data); if (return_code != 0) { fprintf(stderr, "CSNBDEC (DES3 DECRYPT) failed: return_code=%ld reason_code=%ld\n", return_code, reason_code); return -1; } *out_data_len = length; return 0; } int reencrypt_private_token_object(unsigned char *data, unsigned long len, unsigned char *new_cipher, unsigned long *new_cipher_len, unsigned char *masterkey) { unsigned char *clear = NULL; unsigned char des3_key[64]; unsigned char sw_des3_key[3 * DES_KEY_SIZE]; unsigned long clear_len; CK_RV rc; int ret; /* cca wants 8 extra bytes for padding purposes */ clear_len = len + 8; clear = (unsigned char *) malloc(clear_len); if (!clear) { fprintf(stderr, "malloc() failed: %s.\n", strerror(errno)); ret =-1; goto done; } /* decrypt using cca des3 */ memcpy(des3_key, masterkey, MASTER_KEY_SIZE); ret = cca_decrypt(data, len, clear, &clear_len, "10293847", des3_key); if (ret) goto done; /* now encrypt using software des3 */ memcpy(sw_des3_key, masterkey, 3 * DES_KEY_SIZE); rc = sw_des3_cbc_encrypt(clear, clear_len, new_cipher, new_cipher_len, "10293847", sw_des3_key); if (rc != CKR_OK) ret = -1; done: if (clear) free(clear); return ret; } int load_private_token_objects(unsigned char *data_store, unsigned char *masterkey) { FILE *fp1 = NULL, *fp2 = NULL; unsigned char *buf = NULL; unsigned char tmp[PATH_MAX], fname[PATH_MAX], iname[PATH_MAX]; CK_BBOOL priv; unsigned int size; int rc = 0, scount = 0, fcount = 0; size_t read_size; unsigned char *new_cipher = NULL; unsigned long new_cipher_len; snprintf(iname, sizeof(iname), "%s/TOK_OBJ/OBJ.IDX", data_store); fp1 = fopen((char *)iname, "r"); if (!fp1) return -1; // no token objects while (!feof(fp1)) { (void)fgets((char *)tmp, 50, fp1); if (!feof(fp1)) { tmp[strlen((char *)tmp) - 1] = 0; snprintf((char *)fname, sizeof(fname), "%s/TOK_OBJ/", data_store); strcat((char *)fname, (char *)tmp); fp2 = fopen((char *)fname, "r"); if (!fp2) continue; fread(&size, sizeof(unsigned int), 1, fp2); fread(&priv, sizeof(CK_BBOOL), 1, fp2); if (priv == FALSE) { fclose(fp2); continue; } size = size - sizeof(unsigned int) - sizeof(CK_BBOOL); buf = (unsigned char *) malloc(size); if (!buf) { fprintf(stderr, "Cannot malloc for object %s " "(ignoring it).\n", tmp); goto cleanup; } read_size = fread((char *)buf, 1, size, fp2); if (read_size != size) { fprintf(stderr, "Cannot read object %s " "(ignoring it).\n", tmp); goto cleanup; } new_cipher_len = size; new_cipher = malloc(new_cipher_len); if (!new_cipher) { fprintf(stderr, "Cannot malloc space for new " "cipher (ignoring object %s).\n", tmp); goto cleanup; } /* After reading the private token object, * decrypt it using CCA des3 and then re-encrypt it * using software des3. */ memset(new_cipher, 0, new_cipher_len); rc = reencrypt_private_token_object(buf, size, new_cipher, &new_cipher_len, masterkey); if (rc) goto cleanup; fclose(fp2); /* now save the newly re-encrypted object back to * disk in its original file. */ fp2 = fopen((char *)fname, "w"); size = sizeof(unsigned int) + sizeof(CK_BBOOL) + new_cipher_len; (void)fwrite(&size, sizeof(unsigned int), 1, fp2); (void)fwrite(&priv, sizeof(CK_BBOOL), 1, fp2); (void)fwrite(new_cipher, new_cipher_len, 1, fp2); rc = 0; cleanup: if (fp2) fclose(fp2); if (buf) free(buf); if (new_cipher) free(new_cipher); if (rc) { if (v_flag) printf("Failed to process %s\n", fname); fcount++; } else { if (v_flag) printf("Processed %s.\n", fname); scount++; } } } fclose(fp1); printf("Successfully migrated %d object(s).\n", scount); if (v_flag && fcount) printf("Failed to migrate %d object(s).\n", fcount); return 0; } int load_masterkey(char *mkfile, char *pin, char *masterkey) { unsigned char des3_key[3 * DES_KEY_SIZE]; unsigned char hash_sha[SHA1_HASH_SIZE]; unsigned char pin_md5_hash[MD5_HASH_SIZE]; unsigned char *cipher = NULL; unsigned char *clear = NULL; unsigned long cipher_len, clear_len; int ret; CK_RV rc; FILE *fp = NULL; clear_len = cipher_len = (MASTER_KEY_SIZE + SHA1_HASH_SIZE + (DES_BLOCK_SIZE - 1)) & ~(DES_BLOCK_SIZE - 1); fp = fopen((char *)mkfile, "r"); if (!fp) { print_error("Could not open %s: %s\n", mkfile, strerror(errno)); return -1; } cipher = malloc(cipher_len); clear = malloc(clear_len); if (cipher == NULL || clear == NULL) { ret = -1; goto done; } ret = fread(cipher, cipher_len, 1, fp); if (ret != 1) { print_error("Could not read %s: %s\n", mkfile, strerror(errno)); ret = -1; goto done; } /* decrypt the masterkey */ ret = compute_md5(pin, strlen(pin), pin_md5_hash); if (ret) { print_error("Error calculating MD5 of PIN!\n"); goto done; } memcpy(des3_key, pin_md5_hash, MD5_HASH_SIZE); memcpy(des3_key + MD5_HASH_SIZE, pin_md5_hash, DES_KEY_SIZE); rc = sw_des3_cbc_decrypt(cipher, cipher_len, clear, &clear_len, (unsigned char *)"12345678", des3_key); if (rc != CKR_OK) { print_error("Error decrypting master key file after read"); ret = -1; goto done; } /* * technically should strip PKCS padding here but since I already know * what the length should be, I don't bother. * * compare the hashes to verify integrity */ ret = compute_sha1(clear, MASTER_KEY_SIZE, hash_sha); if (ret) { print_error("Failed to compute sha for masterkey.\n"); goto done; } if (memcmp(hash_sha, clear + MASTER_KEY_SIZE, SHA1_HASH_SIZE) != 0) { print_error("%s appears to have been tampered!\n", mkfile); print_error("Cannot migrate.\n"); ret = -1; goto done; } memcpy(masterkey, clear, MASTER_KEY_SIZE); ret = 0; done: if (fp) fclose(fp); if (clear) free(clear); if (cipher) free(cipher); return ret; } int get_pin(char **pin, size_t *pinlen) { struct termios old, new; int nread; char *buff = NULL; size_t buflen; int rc = 0; /* turn echoing off */ if (tcgetattr(fileno(stdin), &old) != 0) return -1; new = old; new.c_lflag &= ~ECHO; if (tcsetattr (fileno(stdin), TCSAFLUSH, &new) != 0) return -1; /* read the pin * Note: getline will allocate memory for buff. free it when done. */ nread = getline(&buff, &buflen, stdin); if (nread == -1) { rc = -1; goto done; } /* Restore terminal */ (void) tcsetattr(fileno(stdin), TCSAFLUSH, &old); /* start a newline */ printf("\n"); fflush(stdout); /* Allocate PIN. * Note: nread includes carriage return. * Replace with terminating NULL. */ *pin = (unsigned char *)malloc(nread); if (*pin == NULL) { rc = -ENOMEM; goto done; } /* strip the carriage return since not part of pin. */ buff[nread - 1] = '\0'; memcpy(*pin, buff, nread); /* don't include the terminating null in the pinlen */ *pinlen = nread - 1; done: if (buff) free(buff); return rc; } int verify_pins(char *data_store, char *sopin, unsigned long sopinlen, char *userpin, unsigned long userpinlen) { TOKEN_DATA td; unsigned char fname[PATH_MAX]; unsigned char pin_sha[SHA1_HASH_SIZE]; FILE *fp = NULL; int ret; /* read the NVTOK.DAT */ snprintf(fname, PATH_MAX, "%s/NVTOK.DAT", data_store); fp = fopen((char *)fname, "r"); if (!fp) { print_error("Could not open %s: %s\n", fname, strerror(errno)); return -1; } ret = fread(&td, sizeof(TOKEN_DATA), 1, fp); if (ret != 1) { print_error("Could not read %s: %s\n", fname, strerror(errno)); ret = -1; goto done; } /* Now compute the SHAs for the SO and USER pins entered. * Compare with the SHAs for SO and USER PINs saved in * NVTOK.DAT to verify. */ if (sopin != NULL) { ret = compute_sha1(sopin, sopinlen, pin_sha); if (ret) { print_error("Failed to compute sha for SO.\n"); goto done; } if (memcmp(td.so_pin_sha, pin_sha, SHA1_HASH_SIZE) != 0) { print_error("SO PIN is incorrect.\n"); ret = -1; goto done; } } if (userpin != NULL) { ret = compute_sha1(userpin, userpinlen, pin_sha); if (ret) { print_error("Failed to compute sha for USER.\n"); goto done; } if (memcmp(td.user_pin_sha, pin_sha, SHA1_HASH_SIZE) != 0) { print_error("USER PIN is incorrect.\n"); ret = -1; goto done; } } ret = 0; done: /* clear out the hash */ memset(pin_sha, 0, SHA1_HASH_SIZE); if (fp) fclose(fp); return ret; } CK_FUNCTION_LIST *p11_init(void) { CK_RV rv; CK_RV (*pfoo)(); char *loc1_lib = "/usr/lib/pkcs11/PKCS11_API.so64"; char *loc2_lib = "libopencryptoki.so"; CK_FUNCTION_LIST *funcs = NULL; p11_lib = dlopen(loc1_lib, RTLD_NOW); if (p11_lib != NULL) goto get_list; p11_lib = dlopen(loc2_lib, RTLD_NOW); if (p11_lib == NULL) { print_error("Couldn't get a handle to the PKCS#11 library."); return NULL; } get_list: pfoo = (CK_RV (*)())dlsym(p11_lib,"C_GetFunctionList"); if (pfoo == NULL) { print_error("Couldn't get the address of the C_GetFunctionList routine."); dlclose(p11_lib); return NULL; } rv = pfoo(&funcs); if (rv != CKR_OK) { p11_error("C_GetFunctionList", rv); dlclose(p11_lib); return NULL; } rv = funcs->C_Initialize(NULL_PTR); if (rv != CKR_OK) { p11_error("C_Initialize", rv); dlclose(p11_lib); return NULL; } if (v_flag) printf("PKCS#11 library initialized\n"); return funcs; } void p11_fini(CK_FUNCTION_LIST *funcs) { funcs->C_Finalize(NULL_PTR); if (p11_lib) dlclose(p11_lib); } /* Expect attribute array to have 3 entries, * 0 CKA_IBM_OPAQUE * 1 CKA_KEY_TYPE * 2 CKA_LABEL */ int add_key(CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *attrs, struct key **keys) { struct key *new_key; CK_ULONG key_type = *(CK_ULONG *)attrs[1].pValue; new_key = malloc(sizeof(struct key)); if (!new_key) { print_error("Malloc of %zd bytes failed!", sizeof(struct key)); return 1; } switch (key_type) { case CKK_AES: case CKK_DES: case CKK_DES2: case CKK_DES3: case CKK_EC: case CKK_GENERIC_SECRET: case CKK_RSA: break; default: free(new_key); return 0; } new_key->type = key_type; new_key->opaque_attr = malloc(attrs[0].ulValueLen); if (!new_key->opaque_attr) { print_error("Malloc of %lu bytes failed!", attrs[0].ulValueLen); return 2; } new_key->handle = handle; new_key->attr_len = attrs[0].ulValueLen; memcpy(new_key->opaque_attr, attrs[0].pValue, attrs[0].ulValueLen); new_key->label = malloc(attrs[2].ulValueLen+1); if (!new_key->label) { print_error("Malloc of %lu bytes failed!", attrs[2].ulValueLen+1); return 2; } memset(new_key->label, 0, attrs[2].ulValueLen+1); memcpy(new_key->label, attrs[2].pValue, attrs[2].ulValueLen); new_key->next = *keys; *keys = new_key; if (v_flag) { char *type_name; switch (new_key->type) { case CKK_AES: type_name = AES_NAME; break; case CKK_DES: type_name = DES_NAME; break; case CKK_DES2: type_name = DES2_NAME; break; case CKK_DES3: type_name = DES3_NAME; break; case CKK_EC: type_name = ECC_NAME; break; case CKK_GENERIC_SECRET: type_name = HMAC_NAME; break; case CKK_RSA: type_name = RSA_NAME; break; default: type_name = BAD_NAME; } printf("Migratable key found: type=%s, label=%s, handle=%lu\n", type_name, new_key->label, handle); } return 0; } int find_wrapped_keys(CK_FUNCTION_LIST *funcs, CK_SESSION_HANDLE sess, CK_KEY_TYPE *key_type, struct key **keys) { CK_RV rv; CK_OBJECT_HANDLE *handles = NULL, tmp; CK_ULONG ulObjectCount = 0, ulTotalCount = 0; CK_BBOOL true = TRUE; CK_ATTRIBUTE key_tmpl[] = { { CKA_KEY_TYPE, key_type, sizeof(*key_type) }, { CKA_TOKEN, &true, sizeof(true) }, { CKA_EXTRACTABLE, &true, sizeof(true) } }; CK_ATTRIBUTE attrs[] = { { CKA_IBM_OPAQUE, NULL, 0 }, { CKA_KEY_TYPE, NULL, 0 }, { CKA_LABEL, NULL, 0 } }; int i, rc, num_attrs = 3; /* Find all objects in the store */ rv = funcs->C_FindObjectsInit(sess, key_tmpl, 3); if (rv != CKR_OK) { p11_error("C_FindObjectsInit", rv); print_error("Error finding CCA key objects"); return 1; } while (1) { rv = funcs->C_FindObjects(sess, &tmp, 1, &ulObjectCount); if (rv != CKR_OK) { p11_error("C_FindObjects", rv); print_error("Error finding CCA key objects"); free(handles); return 1; } if (ulObjectCount == 0) break; handles = realloc(handles, sizeof(CK_OBJECT_HANDLE) * (++ulTotalCount)); if (!handles) { print_error("Malloc of %lu bytes failed!", ulTotalCount); break; } handles[ulTotalCount - 1] = tmp; } if (v_flag) printf("Found %lu keys to examine\n", ulTotalCount); /* Don't care if this fails */ funcs->C_FindObjectsFinal(sess); /* At this point we have an array with handles to every object in the * store. We only care about those with a CKA_IBM_OPAQUE attribute, * so whittle down the list accordingly */ for (tmp = 0; tmp < ulTotalCount; tmp++) { rv = funcs->C_GetAttributeValue(sess, handles[tmp], attrs, num_attrs); if (rv != CKR_OK) { p11_error("C_GetAttributeValue", rv); print_error("Error finding CCA key objects"); free(handles); return 1; } /* If the opaque attr DNE, move to the next key */ if (attrs[0].ulValueLen == ((CK_ULONG)-1)) { continue; } /* Allocate space in the template for the actual data */ for (i = 0; i < num_attrs; i++) { attrs[i].pValue = malloc(attrs[i].ulValueLen); if (!attrs[i].pValue) { print_error("Malloc of %lu bytes failed!", attrs[i].ulValueLen); free(handles); return 1; } } /* Pull in the actual data */ rv = funcs->C_GetAttributeValue(sess, handles[tmp], attrs, num_attrs); if (rv != CKR_OK) { p11_error("C_GetAttributeValue", rv); print_error("Error getting object attributes"); free(handles); return 1; } rc = add_key(handles[tmp], attrs, keys); if (rc) { free(handles); return 1; } for (i = 0; i < num_attrs; i++) { free(attrs[i].pValue); attrs[i].pValue = NULL_PTR; attrs[i].ulValueLen = 0; } } free(handles); return 0; } int replace_keys(CK_FUNCTION_LIST *funcs, CK_SESSION_HANDLE sess, struct key *keys) { CK_RV rv; CK_ATTRIBUTE new_attr[] = { { CKA_IBM_OPAQUE, NULL, 0 } }; struct key *key; for (key = keys; key; key = key->next) { new_attr->pValue = key->opaque_attr; new_attr->ulValueLen = key->attr_len; rv = funcs->C_SetAttributeValue(sess, key->handle, new_attr, 1); if (rv != CKR_OK) { p11_error("C_SetAttributeValue", rv); print_error("Error replacing old key with " "migrated key."); return 1; } } return 0; } int cca_migrate_asymmetric(struct key *key, char **out, struct algo algo) { long return_code, reason_code, exit_data_length, key_identifier_length; unsigned char *key_identifier; exit_data_length = 0; key_identifier_length = key->attr_len; key_identifier = calloc(1, key->attr_len); if (!key_identifier) { print_error("Malloc of %lu bytes failed!", key->attr_len); return 1; } memcpy(key_identifier, (char *)key->opaque_attr, key->attr_len); CSNDKTC(&return_code, &reason_code, &exit_data_length, NULL, &(algo.rule_array_count), algo.rule_array, &key_identifier_length, key_identifier); if (return_code != CCA_SUCCESS) { cca_error("CSNDKTC (Key Token Change)", return_code, reason_code); print_error("Migrating %s key failed. label=%s, handle=%lu", algo.name, key->label, key->handle); return 1; } else if (v_flag) { printf("Successfully migrated %s key. label=%s, handle=%lu\n", algo.name, key->label, key->handle); } *out = (char *)key_identifier; if (!memcmp((CK_BYTE *)key->opaque_attr, (CK_BYTE *)key_identifier, key_identifier_length)) printf("Skipping, %s token is wrapped with current master key. label=%s, handle=%lu\n", algo.name, key->label, key->handle); return 0; } int cca_migrate_symmetric(struct key *key, char **out, struct algo algo) { long return_code, reason_code, exit_data_length; unsigned char *key_identifier; exit_data_length = 0; key_identifier = calloc(1, key->attr_len); if (!key_identifier) { print_error("Malloc of %lu bytes failed!", key->attr_len); return 1; } memcpy(key_identifier, (char *)key->opaque_attr, key->attr_len); CSNBKTC(&return_code, &reason_code, &exit_data_length, NULL, &(algo.rule_array_count), algo.rule_array, key_identifier); if (return_code != CCA_SUCCESS) { cca_error("CSNBKTC (Key Token Change)", return_code, reason_code); print_error("Migrating %s key failed. label=%s, handle=%lu", algo.name, key->label, key->handle); return 1; } else if (v_flag) { printf("Successfully migrated %s key. label=%s, handle=%lu\n", algo.name, key->label, key->handle); } *out = (char *)key_identifier; if (!memcmp((CK_BYTE *)key->opaque_attr, (CK_BYTE *)key_identifier, key->attr_len)) printf("Skipping, %s token is wrapped with current master key. label=%s, handle=%lu\n", algo.name, key->label, key->handle); return 0; } int cca_migrate_hmac(struct key *key, char **out, struct algo algo) { long return_code, reason_code, exit_data_length, key_identifier_length; unsigned char *key_identifier; exit_data_length = 0; key_identifier_length = key->attr_len; key_identifier = calloc(1, key->attr_len); if (!key_identifier) { print_error("Malloc of %lu bytes failed!", key->attr_len); return 1; } memcpy(key_identifier, (char *)key->opaque_attr, key->attr_len); CSNBKTC2(&return_code, &reason_code, &exit_data_length, NULL, &(algo.rule_array_count), algo.rule_array, &key_identifier_length, key_identifier); if (return_code != CCA_SUCCESS) { cca_error("CSNBKTC2 (Key Token Change)", return_code, reason_code); print_error("Migrating %s key failed. label=%s, handle=%lu", algo.name, key->label, key->handle); return 1; } else if (v_flag) { printf("Successfully migrated %s key. label=%s, handle=%lu\n", algo.name, key->label, key->handle); } *out = (char *)key_identifier; if (!memcmp((CK_BYTE *)key->opaque_attr, (CK_BYTE *)key_identifier, key_identifier_length)) printf("Skipping, %s token is wrapped with current master key. label=%s, handle=%lu\n", algo.name, key->label, key->handle); return 0; } /* @keys: A linked list of data to migrate and the PKCS#11 handle for the * object in the data store. * @count: counter for number of keys migrated * @count_failed: counter for number of keys that failed to migrate */ int cca_migrate(struct key *keys, struct key_count *count, struct key_count *count_failed) { struct key *key; char *migrated_data; int rc; for (key = keys; key; key = key->next) { migrated_data = NULL; switch(key->type) { case CKK_AES: rc = cca_migrate_symmetric(key, &migrated_data, aes); if (rc) count_failed->aes++; else count->aes++; break; case CKK_DES: case CKK_DES2: case CKK_DES3: rc = cca_migrate_symmetric(key, &migrated_data, des); if (rc) count_failed->des++; else count->des++; break; case CKK_EC: rc = cca_migrate_asymmetric(key, &migrated_data, ecc); if (rc) count_failed->ecc++; else count->ecc++; break; case CKK_GENERIC_SECRET: rc = cca_migrate_hmac(key, &migrated_data, hmac); if (rc) count_failed->hmac++; else count->hmac++; break; case CKK_RSA: rc = cca_migrate_asymmetric(key, &migrated_data, rsa); if (rc) count_failed->rsa++; else count->rsa++; break; } /* replace the original key with the migrated key*/ if (!rc && migrated_data) { free(key->opaque_attr); key->opaque_attr = (CK_BYTE *)migrated_data; } } return 0; } int migrate_keytype(CK_FUNCTION_LIST *funcs, CK_SESSION_HANDLE sess, CK_KEY_TYPE *k_type, struct key_count *count, struct key_count *count_failed) { struct key *keys = NULL, *tmp, *to_free; int rc; rc = find_wrapped_keys(funcs, sess, k_type, &keys); if (rc) { goto done; } rc = cca_migrate(keys, count, count_failed); if (rc) { goto done; } rc = replace_keys(funcs, sess, keys); if (rc) { goto done; } done: for (to_free = keys; to_free; to_free = tmp) { tmp = to_free->next; free(to_free->opaque_attr); free(to_free); } return rc; } void key_migration_results(struct key_count migrated, struct key_count failed) { if (migrated.aes || migrated.des || migrated.des2 || migrated.des3 || migrated.ecc || migrated.hmac || migrated.rsa) printf("Successfully migrated: "); if (migrated.aes) printf("AES: %d. ", migrated.aes); if (migrated.des) printf("DES: %d. ", migrated.des); if (migrated.des2) printf("DES2: %d. ", migrated.des2); if (migrated.des3) printf("DES3: %d. ", migrated.des3); if (migrated.ecc) printf("ECC: %d. ", migrated.ecc); if (migrated.hmac) printf("HMAC: %d. ", migrated.hmac); if (migrated.rsa) printf("RSA: %d. ", migrated.rsa); if (failed.aes || failed.des || failed.des2 || failed.des3 || failed.ecc || failed.hmac || failed.rsa) printf("\nFailed to migrate: "); if (failed.aes) printf("AES: %d. ", failed.aes); if (failed.des) printf("DES: %d. ", failed.des); if (failed.des2) printf("DES2: %d. ", failed.des2); if (failed.des3) printf("DES3: %d. ", failed.des3); if (failed.ecc) printf("ECC: %d. ", failed.ecc); if (failed.hmac) printf("HMAC: %d. ", failed.hmac); if (failed.rsa) printf("RSA: %d. ", failed.rsa); printf("\n"); } int migrate_wrapped_keys(CK_SLOT_ID slot_id, char *userpin, int masterkey) { CK_FUNCTION_LIST *funcs; CK_KEY_TYPE key_type = 0; CK_ULONG slot_count; CK_SESSION_HANDLE sess; CK_RV rv; struct key_count count = {0,0,0,0,0,0,0}; struct key_count count_failed = {0,0,0,0,0,0,0}; int exit_code = 0, rc; funcs = p11_init(); if (!funcs) { return 2; } rv = funcs->C_GetSlotList(TRUE, NULL_PTR, &slot_count); if (rv != CKR_OK) { p11_error("C_GetSlotList" ,rv); exit_code = 3; goto finalize; } if (slot_id >= slot_count) { print_error("%lu is not a valid slot ID." , slot_id); exit_code = 4; goto finalize; } rv = funcs->C_OpenSession(slot_id, CKF_RW_SESSION| CKF_SERIAL_SESSION,NULL_PTR,NULL_PTR, &sess); if (rv != CKR_OK) { p11_error("C_OpenSession", rv); exit_code = 5; goto finalize; } rv = funcs->C_Login(sess, CKU_USER, (CK_BYTE *)userpin, strlen(userpin)); if (rv != CKR_OK) { p11_error("C_Login (USER)", rv); exit_code = 8; goto finalize; } switch(masterkey) { case MK_AES: if (v_flag) printf("Search for AES keys\n"); key_type = CKK_AES; rc = migrate_keytype(funcs, sess, &key_type, &count, &count_failed); if (rc) { goto done; } if (v_flag) printf("Search for HMAC keys\n"); key_type = CKK_GENERIC_SECRET; rc = migrate_keytype(funcs, sess, &key_type, &count, &count_failed); if (rc) { goto done; } break; case MK_APKA: if (v_flag) printf("Search for ECC keys\n"); key_type = CKK_EC; rc = migrate_keytype(funcs, sess, &key_type, &count, &count_failed); if (rc) { goto done; } break; case MK_ASYM: if (v_flag) printf("Search for RSA keys\n"); key_type = CKK_RSA; rc = migrate_keytype(funcs, sess, &key_type, &count, &count_failed); if (rc) { goto done; } break; case MK_SYM: if (v_flag) printf("Search for DES keys\n"); key_type = CKK_DES; rc = migrate_keytype(funcs, sess, &key_type, &count, &count_failed); if (rc) { goto done; } if (v_flag) printf("Search for DES2 keys\n"); key_type = CKK_DES2; rc = migrate_keytype(funcs, sess, &key_type, &count, &count_failed); if (rc) { goto done; } if (v_flag) printf("Search for DES3 keys\n"); key_type = CKK_DES3; rc = migrate_keytype(funcs, sess, &key_type, &count, &count_failed); if (rc) { goto done; } break; default: print_error("unknown key type (%lu)\n", key_type); return -1; } key_migration_results(count, count_failed); done: funcs->C_CloseSession(sess); finalize: p11_fini(funcs); return exit_code; } int migrate_version(char *sopin, char *userpin, unsigned char *data_store) { unsigned char masterkey[MASTER_KEY_SIZE]; char fname[PATH_MAX]; struct stat statbuf; int ret = 0; /* Verify that the data store is valid by looking for * MK_SO, MK_USER, and TOK_OBJ/OBJ.IDX. */ memset(fname, 0, PATH_MAX); snprintf(fname, PATH_MAX, "%s/MK_SO", data_store); if (stat(fname, &statbuf) != 0) { fprintf(stderr, "Cannot find %s.\n", fname); ret = -1; goto done; } memset(fname, 0, PATH_MAX); snprintf(fname, PATH_MAX, "%s/MK_USER", data_store); if (stat(fname, &statbuf) != 0) { fprintf(stderr, "Cannot find %s.\n", fname); ret = -1; goto done; } memset(fname, 0, PATH_MAX); snprintf(fname, PATH_MAX, "%s/TOK_OBJ/OBJ.IDX", data_store); if (stat(fname, &statbuf) != 0) { fprintf(stderr, "Cannot find %s.\n", fname); ret = -1; goto done; } /* If the OBJ.IDX is empty, then no objects to migrate. */ if (statbuf.st_size == 0) { printf("OBJ.IDX file is empty. Thus no objects to migrate.\n"); goto done; } if (v_flag) printf("%s has an MK_SO, MK_USER and TOK/OBJ.IDX\n", data_store); /* Get the masterkey from MK_SO. * This also helps verify that correct SO pin was entered. */ memset(masterkey, 0, MASTER_KEY_SIZE); memset(fname, 0, PATH_MAX); snprintf(fname, PATH_MAX, "%s/MK_SO", data_store); ret = load_masterkey(fname, sopin, masterkey); if (ret) { fprintf(stderr, "Could not load masterkey from MK_SO.\n"); goto done; } if (v_flag) printf("Successfully verified SO Pin.\n"); /* Get the masterkey from MK_USER. * This also helps verift that correct USER pin was entered. */ memset(masterkey, 0, MASTER_KEY_SIZE); memset(fname, 0, PATH_MAX); snprintf(fname, PATH_MAX, "%s/MK_USER", data_store); ret = load_masterkey(fname, userpin, masterkey); if (ret) { fprintf(stderr, "Could not load masterkey from MK_USER.\n"); goto done; } if (v_flag) printf("Successfully verified USER Pin.\n"); /* Load all the private token objects and re-encrypt them * using software des3, instead of CSNBENC. */ (void)load_private_token_objects(data_store, masterkey); done: return ret; } void usage(char *progname) { printf(" Help:\t\t\t\t%s -h\n", progname); printf(" -h\t\t\t\tShow this help\n\n"); printf(" Migrate Object Version:\t%s -m v2objectsv3 [OPTIONS] \n", progname); printf(" -m v2objectsv3.\t\tMigrates CCA private token objects from"); printf(" CCA\n\t\t\t\tencryption (used in v2) to software encryption"); printf(" \n\t\t\t\t(used in v3). \n"); printf(" Migrate Wrapped Keys:\t\t%s -m keys -s SLOTID -k KEYTYPE [OPTIONS] \n", progname); printf(" -m keys.\t\t\tUnwraps private keys with the"); printf(" old CCA master\n\t\t\t\tkey and wraps them with the"); printf(" new CCA master key\n"); printf(" -s, --slotid SLOTID\t\tPKCS slot number\n"); printf(" -k aes|apka|asym|sym\t\tMigrate selected keytype\n\n"); printf(" Options:\n"); printf(" -d, --datastore DATASTORE\tCCA token datastore location\n"); printf(" -v, --verbose\t\t\tProvide more detailed output\n"); printf(" \n\t\t\t\tthe migrated data\n\n"); return; } int main(int argc, char **argv) { int ret = 0, opt = 0, c_flag = 0, masterkey = 0; int data_store_len = 0; CK_SLOT_ID slot_id = 0; char *sopin = NULL, *userpin = NULL; size_t sopinlen, userpinlen; unsigned char *data_store = NULL; unsigned char *m_type = NULL; unsigned char *mk_type = NULL; void *lib_csulcca; int m_version = 0; int m_keys = 0; struct option long_opts[] = { { "datastore", required_argument, NULL, 'd' }, { "slotid", required_argument, NULL, 's' }, { "verbose", no_argument, NULL, 'v' }, { 0, 0, 0, 0 } }; while ((opt = getopt_long(argc, argv, "m:d:s:k:hv", long_opts, NULL)) != -1) { switch (opt) { case 'd': data_store = strdup(optarg); break; case 'h': usage(argv[0]); return 0; case 'k': mk_type = strdup(optarg); if (!memcmp(mk_type, "aes", 3)) masterkey = MK_AES; else if (!memcmp(mk_type, "apka", 4)) masterkey = MK_APKA; else if (!memcmp(mk_type, "asym", 4)) masterkey = MK_ASYM; else if (!memcmp(mk_type, "sym", 3)) masterkey = MK_SYM; else { print_error("unknown key type (%s)\n", mk_type); usage(argv[0]); return -1; } break; case 'm': m_type = strdup(optarg); if (!memcmp(m_type, "v2objectsv3", 11)) m_version = 1; else if (!memcmp(m_type, "keys", 4)) m_keys = 1; else { print_error("unknown migration type (%s)\n", m_type); usage(argv[0]); return -1; } break; case 's': c_flag++; slot_id = atoi(optarg); break; case 'v': v_flag++; break; default: usage(argv[0]); return -1; } } /* check for missing parameters */ if (!m_version && !m_keys) { print_error("missing migration type\n"); usage(argv[0]); return -1; } /* use default data_store if one is not given */ if (data_store == NULL) { data_store_len = strlen(TOK_DATASTORE); data_store = malloc(data_store_len + 1); if (data_store == NULL) { fprintf(stderr, "malloc failed: %s\n",strerror(errno)); return -1; } memset(data_store, 0, data_store_len + 1); memcpy(data_store, TOK_DATASTORE, data_store_len); } /* get the SO pin to authorize migration */ printf("Enter the SO PIN: "); fflush(stdout); ret = get_pin(&sopin, &sopinlen); if (ret != 0) { print_error("Could not get SO PIN.\n"); goto done; } /* get the USER pin to authorize migration */ printf("Enter the USER PIN: "); fflush(stdout); ret = get_pin(&userpin, &userpinlen); if (ret != 0) { print_error("Could not get USER PIN.\n"); goto done; } /* verify the SO and USER PINs entered. */ ret = verify_pins(data_store, sopin, sopinlen, userpin, userpinlen); if (ret) goto done; lib_csulcca = dlopen(CCA_LIBRARY, (RTLD_GLOBAL | RTLD_NOW)); if (lib_csulcca == NULL) { fprintf(stderr, "dlopen(%s) failed: %s\n", CCA_LIBRARY, strerror(errno)); return -1; } if (m_version) { CSNBDEC = dlsym(lib_csulcca, "CSNBDEC"); ret = migrate_version(sopin, userpin, data_store); } else if (m_keys) { if (!slot_id) { print_error("missing slot number\n"); usage(argv[0]); return -1; } if (!masterkey) { print_error("missing key type\n"); usage(argv[0]); return -1; } CSNDKTC = dlsym(lib_csulcca, "CSNDKTC_32"); CSNBKTC = dlsym(lib_csulcca, "CSNBKTC_32"); CSNBKTC2 = dlsym(lib_csulcca, "CSNBKTC2_32"); ret = migrate_wrapped_keys(slot_id, userpin, masterkey); } done: if (sopin) free(sopin); if (userpin) free(userpin); if (data_store) free(data_store); return ret; } char * p11strerror(CK_RV rc) { switch (rc) { case CKR_OK: return "CKR_OK"; case CKR_CANCEL: return "CKR_CANCEL"; case CKR_HOST_MEMORY: return "CKR_HOST_MEMORY"; case CKR_SLOT_ID_INVALID: return "CKR_SLOT_ID_INVALID"; case CKR_GENERAL_ERROR: return "CKR_GENERAL_ERROR"; case CKR_FUNCTION_FAILED: return "CKR_FUNCTION_FAILED"; case CKR_ARGUMENTS_BAD: return "CKR_ARGUMENTS_BAD"; case CKR_NO_EVENT: return "CKR_NO_EVENT"; case CKR_NEED_TO_CREATE_THREADS: return "CKR_NEED_TO_CREATE_THREADS"; case CKR_CANT_LOCK: return "CKR_CANT_LOCK"; case CKR_ATTRIBUTE_READ_ONLY: return "CKR_ATTRIBUTE_READ_ONLY"; case CKR_ATTRIBUTE_SENSITIVE: return "CKR_ATTRIBUTE_SENSITIVE"; case CKR_ATTRIBUTE_TYPE_INVALID: return "CKR_ATTRIBUTE_TYPE_INVALID"; case CKR_ATTRIBUTE_VALUE_INVALID: return "CKR_ATTRIBUTE_VALUE_INVALID"; case CKR_DATA_INVALID: return "CKR_DATA_INVALID"; case CKR_DATA_LEN_RANGE: return "CKR_DATA_LEN_RANGE"; case CKR_DEVICE_ERROR: return "CKR_DEVICE_ERROR"; case CKR_DEVICE_MEMORY: return "CKR_DEVICE_MEMORY"; case CKR_DEVICE_REMOVED: return "CKR_DEVICE_REMOVED"; case CKR_ENCRYPTED_DATA_INVALID: return "CKR_ENCRYPTED_DATA_INVALID"; case CKR_ENCRYPTED_DATA_LEN_RANGE: return "CKR_ENCRYPTED_DATA_LEN_RANGE"; case CKR_FUNCTION_CANCELED: return "CKR_FUNCTION_CANCELED"; case CKR_FUNCTION_NOT_PARALLEL: return "CKR_FUNCTION_NOT_PARALLEL"; case CKR_FUNCTION_NOT_SUPPORTED: return "CKR_FUNCTION_NOT_SUPPORTED"; case CKR_KEY_HANDLE_INVALID: return "CKR_KEY_HANDLE_INVALID"; case CKR_KEY_SIZE_RANGE: return "CKR_KEY_SIZE_RANGE"; case CKR_KEY_TYPE_INCONSISTENT: return "CKR_KEY_TYPE_INCONSISTENT"; case CKR_KEY_NOT_NEEDED: return "CKR_KEY_NOT_NEEDED"; case CKR_KEY_CHANGED: return "CKR_KEY_CHANGED"; case CKR_KEY_NEEDED: return "CKR_KEY_NEEDED"; case CKR_KEY_INDIGESTIBLE: return "CKR_KEY_INDIGESTIBLE"; case CKR_KEY_FUNCTION_NOT_PERMITTED: return "CKR_KEY_FUNCTION_NOT_PERMITTED"; case CKR_KEY_NOT_WRAPPABLE: return "CKR_KEY_NOT_WRAPPABLE"; case CKR_KEY_UNEXTRACTABLE: return "CKR_KEY_UNEXTRACTABLE"; case CKR_MECHANISM_INVALID: return "CKR_MECHANISM_INVALID"; case CKR_MECHANISM_PARAM_INVALID: return "CKR_MECHANISM_PARAM_INVALID"; case CKR_OBJECT_HANDLE_INVALID: return "CKR_OBJECT_HANDLE_INVALID"; case CKR_OPERATION_ACTIVE: return "CKR_OPERATION_ACTIVE"; case CKR_OPERATION_NOT_INITIALIZED: return "CKR_OPERATION_NOT_INITIALIZED"; case CKR_PIN_INCORRECT: return "CKR_PIN_INCORRECT"; case CKR_PIN_INVALID: return "CKR_PIN_INVALID"; case CKR_PIN_LEN_RANGE: return "CKR_PIN_LEN_RANGE"; case CKR_PIN_EXPIRED: return "CKR_PIN_EXPIRED"; case CKR_PIN_LOCKED: return "CKR_PIN_LOCKED"; case CKR_SESSION_CLOSED: return "CKR_SESSION_CLOSED"; case CKR_SESSION_COUNT: return "CKR_SESSION_COUNT"; case CKR_SESSION_HANDLE_INVALID: return "CKR_SESSION_HANDLE_INVALID"; case CKR_SESSION_PARALLEL_NOT_SUPPORTED: return "CKR_SESSION_PARALLEL_NOT_SUPPORTED"; case CKR_SESSION_READ_ONLY: return "CKR_SESSION_READ_ONLY"; case CKR_SESSION_EXISTS: return "CKR_SESSION_EXISTS"; case CKR_SESSION_READ_ONLY_EXISTS: return "CKR_SESSION_READ_ONLY_EXISTS"; case CKR_SESSION_READ_WRITE_SO_EXISTS: return "CKR_SESSION_READ_WRITE_SO_EXISTS"; case CKR_SIGNATURE_INVALID: return "CKR_SIGNATURE_INVALID"; case CKR_SIGNATURE_LEN_RANGE: return "CKR_SIGNATURE_LEN_RANGE"; case CKR_TEMPLATE_INCOMPLETE: return "CKR_TEMPLATE_INCOMPLETE"; case CKR_TEMPLATE_INCONSISTENT: return "CKR_TEMPLATE_INCONSISTENT"; case CKR_TOKEN_NOT_PRESENT: return "CKR_TOKEN_NOT_PRESENT"; case CKR_TOKEN_NOT_RECOGNIZED: return "CKR_TOKEN_NOT_RECOGNIZED"; case CKR_TOKEN_WRITE_PROTECTED: return "CKR_TOKEN_WRITE_PROTECTED"; case CKR_UNWRAPPING_KEY_HANDLE_INVALID: return "CKR_UNWRAPPING_KEY_HANDLE_INVALID"; case CKR_UNWRAPPING_KEY_SIZE_RANGE: return "CKR_UNWRAPPING_KEY_SIZE_RANGE"; case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"; case CKR_USER_ALREADY_LOGGED_IN: return "CKR_USER_ALREADY_LOGGED_IN"; case CKR_USER_NOT_LOGGED_IN: return "CKR_USER_NOT_LOGGED_IN"; case CKR_USER_PIN_NOT_INITIALIZED: return "CKR_USER_PIN_NOT_INITIALIZED"; case CKR_USER_TYPE_INVALID: return "CKR_USER_TYPE_INVALID"; case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: return "CKR_USER_ANOTHER_ALREADY_LOGGED_IN"; case CKR_USER_TOO_MANY_TYPES: return "CKR_USER_TOO_MANY_TYPES"; case CKR_WRAPPED_KEY_INVALID: return "CKR_WRAPPED_KEY_INVALID"; case CKR_WRAPPED_KEY_LEN_RANGE: return "CKR_WRAPPED_KEY_LEN_RANGE"; case CKR_WRAPPING_KEY_HANDLE_INVALID: return "CKR_WRAPPING_KEY_HANDLE_INVALID"; case CKR_WRAPPING_KEY_SIZE_RANGE: return "CKR_WRAPPING_KEY_SIZE_RANGE"; case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT"; case CKR_RANDOM_SEED_NOT_SUPPORTED: return "CKR_RANDOM_SEED_NOT_SUPPORTED"; case CKR_RANDOM_NO_RNG: return "CKR_RANDOM_NO_RNG"; case CKR_BUFFER_TOO_SMALL: return "CKR_BUFFER_TOO_SMALL"; case CKR_SAVED_STATE_INVALID: return "CKR_SAVED_STATE_INVALID"; case CKR_INFORMATION_SENSITIVE: return "CKR_INFORMATION_SENSITIVE"; case CKR_STATE_UNSAVEABLE: return "CKR_STATE_UNSAVEABLE"; case CKR_CRYPTOKI_NOT_INITIALIZED: return "CKR_CRYPTOKI_NOT_INITIALIZED"; case CKR_CRYPTOKI_ALREADY_INITIALIZED: return "CKR_CRYPTOKI_ALREADY_INITIALIZED"; case CKR_MUTEX_BAD: return "CKR_MUTEX_BAD"; case CKR_MUTEX_NOT_LOCKED: return "CKR_MUTEX_NOT_LOCKED"; default: return "UNKNOWN"; } return "UNKNOWN"; } opencryptoki+dfsg/usr/sbin/pkcsep11_migrate/0000755000175000017500000000000012630407154020202 5ustar xnoxxnoxopencryptoki+dfsg/usr/sbin/pkcsep11_migrate/ep11adm.h0000644000175000017500000000714412630407154021611 0ustar xnoxxnox/*---------------------------------------------------------------------- * (C) COPYRIGHT INTERNATIONAL BUSINESS MACHINES CORPORATION 2011 * ALL RIGHTS RESERVED * IBM Research & Development *---------------------------------------------------------------------- * Author: Gehrmann, Tobias (tobias.gehrmann@de.ibm.com) *----------------------------------------------------------------------*/ #if !defined(__EP11ADM_H__) #define __EP11ADM_H__ #if !defined(INT64_MIN) #error "We need 32/64-bit types, please include before this file." #endif // these numbers apply to current version, subject to change // #if !defined(EP11_SERIALNR_CHARS) #define EP11_SERIALNR_CHARS 8 #endif #if !defined(EP11_KEYCSUM_BYTES) #define EP11_KEYCSUM_BYTES (256/8) /* full size of verific. pattern */ #endif #if !defined(EP11_ADMCTR_BYTES) #define EP11_ADMCTR_BYTES (128/8) /* admin transaction ctrs */ #endif #if !defined(EP11_ADM_REENCRYPT) #define EP11_ADM_REENCRYPT 25 /* transform blobs to next WK */ #endif #if !defined(CK_IBM_EP11Q_DOMAIN) #define CK_IBM_EP11Q_DOMAIN 3 /* list domain's WK hashes */ #endif #if !defined(CK_IBM_DOM_COMMITTED_NWK) #define CK_IBM_DOM_COMMITTED_NWK 8 /* next WK is active(committed) */ #endif typedef struct ep11_admresp { uint32_t fn; uint32_t domain; uint32_t domainInst; /* module ID || module instance */ unsigned char module[ EP11_SERIALNR_CHARS + EP11_SERIALNR_CHARS ]; unsigned char modNr[ EP11_SERIALNR_CHARS ]; unsigned char modInst[ EP11_SERIALNR_CHARS ]; unsigned char tctr[ EP11_ADMCTR_BYTES ]; /* transaction counter */ CK_RV rv; uint32_t reason; // points to original response; NULL if no payload // make sure it's copied if used after releasing response block // const unsigned char *payload; size_t pllen; } *ep11_admresp_t; #if !defined(__XCP_H__) typedef struct CK_IBM_DOMAIN_INFO { CK_ULONG domain; CK_BYTE wk[ EP11_KEYCSUM_BYTES ]; CK_BYTE nextwk[ EP11_KEYCSUM_BYTES ]; CK_ULONG flags; CK_BYTE mode[ 8 ]; } CK_IBM_DOMAIN_INFO; #endif /*---------------------------------------------------------------------- * build a command block to (blk,blen), querying 'fn' * (payload,plen) copied to query block if non-NULL * * returns written bytecount; size query if blk is NULL * *minf used for module ID and transaction counter * ignored for commands where those fields are ignored */ long ep11a_cmdblock(unsigned char *blk, size_t blen, unsigned int fn, const struct ep11_admresp *minf, const unsigned char *tctr, /* EP11_ADMCTR_BYTES */ const unsigned char *payload, size_t plen); /*---------------------------------------------------------------------- * returns <0 if response is malformed, or contents invalid * * parse embedded return value from response, writes to *rv if non-NULL * (outside envelope always reports CKR_OK, unless infrastructure * failed) */ long ep11a_internal_rv(const unsigned char *rsp, size_t rlen, struct ep11_admresp *rspblk, CK_RV *rv); /*---------------------------------------------------------------------- * in: [0] query type * out: [0] packed info structure * * outputs are fixed size, except CK_IBM_XCPQ_DOMAINS, which returns a * list therefore, infbytes is ignored by other types (we still check * if present) */ CK_RV m_get_ep11_info(CK_VOID_PTR pinfo, CK_ULONG_PTR infbytes, unsigned int query, unsigned int subquery, uint64_t target); #endif /* !defined(__EP11ADM_H__) */ opencryptoki+dfsg/usr/sbin/pkcsep11_migrate/Makefile.am0000644000175000017500000000071412630407154022240 0ustar xnoxxnoxsbin_PROGRAMS=pkcsep11_migrate pkcsep11_migrate_SOURCES = ../../lib/pkcs11/common/p11util.c pkcsep11_migrate.c pkcsep11_migrate_CFLAGS = -I ../../include/pkcs11/ -I../../lib/pkcs11/ep11_stdll/ -DLINUX -DPROGRAM_NAME=\"$(@)\" pkcsep11_migrate_LDFLAGS = -lc -ldl -lpthread INCLUDES = -I. -I../../lib/pkcs11/common # Not all versions of automake observe sbinname_CFLAGS # AM_CFLAGS = -DLINUX -DPROGRAM_NAME=\"$(@)\" # # INCLUDES = -I. -I../../include/pkcs11 opencryptoki+dfsg/usr/sbin/pkcsep11_migrate/pkcsep11_migrate.c0000644000175000017500000003114312630407154023507 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * (C) COPYRIGHT International Business Machines Corp. 2013 * */ /* Reenryption of EP11 secure keys. The secure key is reencrypted at the card by a new wrapping (still pending) key. Needed also for SPKIs of public keys. */ #include #include #include #include #include #include #include #include #include #include #include #define EP11SHAREDLIB "libep11.so" #define PKCS11_MAX_PIN_LEN 128 #define PKCS11_SO_PIN_ENV_VAR "PKCS11_SO_PIN" #define PKCS11_USER_PIN_ENV_VAR "PKCS11_USER_PIN" CK_FUNCTION_LIST *funcs; CK_SLOT_ID SLOT_ID = -1; CK_LONG adapter = -1; CK_LONG domain = -1; CK_OBJECT_HANDLE key_store[4096]; int (*_m_get_ep11_info)(CK_VOID_PTR pinfo, CK_ULONG_PTR, unsigned int, unsigned int, uint64_t); long (*_ep11a_cmdblock)(unsigned char *, size_t , unsigned int , const struct ep11_admresp *, const unsigned char *, const unsigned char *, size_t ); unsigned long int (*_m_admin) (unsigned char *, size_t *, unsigned char *, size_t *, const unsigned char *, size_t , const unsigned char *, size_t, uint64_t) ; long (*_ep11a_internal_rv)(const unsigned char *, size_t , struct ep11_admresp *, CK_RV *); typedef struct { short format; short length; short apqns[512]; } __attribute__((packed)) ep11_target_t; #define blobsize 2048*4 typedef struct { size_t blob_size; size_t blob_id; unsigned char blob[blobsize]; } ep11_opaque; static int reencrypt(CK_SESSION_HANDLE session, CK_ULONG obj, CK_BYTE *old) { CK_BYTE req[blobsize]; CK_BYTE resp[blobsize]; CK_LONG req_len; size_t resp_len; struct ep11_admresp rb; struct ep11_admresp lrb; ep11_target_t target; CK_RV rc; CK_BYTE name[256]; ep11_opaque *op_old = (ep11_opaque *) old; ep11_opaque op_new; CK_ATTRIBUTE opaque_template[] = { {CKA_IBM_OPAQUE, &op_new, sizeof(op_new)} }; CK_ATTRIBUTE name_template[] = { {CKA_LABEL, NULL_PTR, 0} }; memset(name,0,256); /* print CKA_LABEL if it exists, only informational exist and size query */ rc = funcs->C_GetAttributeValue(session, key_store[obj], name_template, 1); if (rc == CKR_OK && name_template[0].ulValueLen < 256) { name_template[0].pValue = name; /* knowing its size, after mem allocation, get the name value */ rc = funcs->C_GetAttributeValue(session, key_store[obj], name_template, 1); } memset(&rb,0, sizeof(rb)); memset(&lrb,0, sizeof(lrb)); memset(&target,0,sizeof(target)); target.length = 1; target.apqns[0] = adapter; target.apqns[1] = domain; rb.domain = domain; lrb.domain = domain; fprintf(stderr,"going to reencrpyt key %lx with blob len %lx %s\n",obj,op_old->blob_size,name); resp_len = blobsize; req_len = _ep11a_cmdblock(req, blobsize, EP11_ADM_REENCRYPT, &rb, NULL, op_old->blob, op_old->blob_size); if (req_len < 0) { fprintf(stderr,"reencrypt cmd block construction failed\n"); return -2; } rc = _m_admin(resp, &resp_len, NULL, 0, req, req_len, NULL, 0, (unsigned long long) &target); if(rc != CKR_OK || resp_len == 0 || resp == NULL) { fprintf(stderr,"reencryption failed %lx %ld\n",rc,req_len); return -3; } if (_ep11a_internal_rv(resp, resp_len, &lrb, &rc) < 0) { fprintf(stderr, "reencryption response malformed %lx\n",rc); return -4; } if(op_old->blob_size != lrb.pllen) { fprintf(stderr, "reencryption blob size changed %lx %lx %lx %lx\n", op_old->blob_size,lrb.pllen,resp_len,req_len); return -5; } memset(&op_new,0,sizeof(op_new)); op_new.blob_id = op_old->blob_id; op_new.blob_size = op_old->blob_size; memcpy(op_new.blob,lrb.payload,op_new.blob_size); rc = funcs->C_SetAttributeValue(session, key_store[obj], opaque_template, 1); if (rc != CKR_OK) { fprintf(stderr, "reencryption C_SetAttributeValue failed obj %lx %s rc %lx\n",obj,name,rc); return -6; } fprintf(stderr, "reencryption success obj %lx %s\n",obj,name); return 0; } static int check_card_status() { CK_RV rc; ep11_target_t target; CK_IBM_DOMAIN_INFO dinf; CK_ULONG dinf_len = sizeof(dinf); if (adapter == -1 || domain == -1) { fprintf(stderr,"adapter/domain specification missing.\n"); return -1; } target.format = 0; target.length = 1; target.apqns[0] = adapter; target.apqns[1] = domain; rc = _m_get_ep11_info ((CK_VOID_PTR) &dinf, &dinf_len, CK_IBM_EP11Q_DOMAIN, 0, (unsigned long long) &target); if (rc != CKR_OK) { fprintf(stderr,"m_get_ep11_info rc 0x%lx, valid apapter/domain 0x%02lx/%ld?.\n", rc,adapter,domain); return -1; } if (CK_IBM_DOM_COMMITTED_NWK & dinf.flags) { fprintf(stderr,"Card ID 0x%02lx, domain ID %ld has committed pending(next) WK\n", adapter, domain); } else { fprintf(stderr,"Card ID 0x%02lx, domain ID %ld has no committed pending WK\n", adapter, domain); return -1; } return 0; } static int get_user_pin(CK_BYTE *dest) { char *val; val = getenv(PKCS11_USER_PIN_ENV_VAR); if (val == NULL) { fprintf(stderr, "The environment variable %s must be set.\n" , PKCS11_USER_PIN_ENV_VAR); return -1; } if ((strlen(val) + 1) > PKCS11_MAX_PIN_LEN) { fprintf(stderr, "The environment variable %s must hold a " "value less than %d chars in length.\n", PKCS11_USER_PIN_ENV_VAR, (int)PKCS11_MAX_PIN_LEN); return -1; } memcpy(dest, val, strlen(val) + 1); return 0; } static int do_GetFunctionList( void ) { CK_RV rc; CK_RV (*func_list)() = NULL; void *d; char *evar; char *evar_default = "libopencryptoki.so"; evar = getenv("PKCSLIB"); if ( evar == NULL) { evar = evar_default; } d = dlopen(evar,RTLD_NOW); if ( d == NULL ) { return 0; } func_list = (CK_RV (*)())dlsym(d,"C_GetFunctionList"); if (func_list == NULL ) { return 0; } rc = func_list(&funcs); if (rc != CKR_OK) { return 0; } return 1; } static void usage (char *fct) { printf("usage: %s [-slot ] [-adapter ] [-domain ] [-h]\n\n", fct ); return; } static int do_ParseArgs(int argc, char **argv) { int i; if (argc <= 1) { printf ("No Arguments given. For help use the '--help' or '-h' option.\n"); return -1; } for (i = 1; i < argc; i++) { if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "--help") == 0) { usage (argv [0]); return 0; } else if (strcmp (argv[i], "-slot") == 0) { if (!isdigit(*argv[i+1])) { printf("Slot parameter is not numeric!\n"); return -1; } SLOT_ID = (int)strtol(argv[i+1], NULL, 0); i++; } else if (strcmp (argv[i], "-adapter") == 0) { if (!isdigit(*argv[i+1])) { printf("Adapter parameter is not numeric!\n"); return -1; } adapter = (int)strtol(argv[i+1], NULL, 0); i++; } else if (strcmp (argv[i], "-domain") == 0) { if (!isdigit(*argv[i+1])) { printf("Domain parameter is not numeric!\n"); return -1; } domain = (int)strtol(argv[i+1], NULL, 0); i++; } else { printf ("Invalid argument passed as option: %s\n", argv [i]); usage (argv [0]); return -1; } } if (SLOT_ID == -1) { printf("Slot-ID not set!\n"); return -1; } if (adapter == -1) { printf("Adapter-ID not set!\n"); return -1; } if (domain == -1) { printf("Domain-ID not set!\n"); return -1; } return 1; } int main (int argc, char **argv){ int rc; int obj; void *lib_ep11; CK_C_INITIALIZE_ARGS cinit_args; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_FLAGS flags; CK_SESSION_HANDLE session; CK_ULONG user_pin_len; CK_ULONG keys_found = 0; rc = do_ParseArgs(argc, argv); if(rc != 1){ return rc; } /* dynamically load in the ep11 shared library */ lib_ep11 = dlopen(EP11SHAREDLIB, RTLD_GLOBAL | RTLD_NOW); if (!lib_ep11) { fprintf(stderr,"ERROR loading shared lib '%s' [%s]", EP11SHAREDLIB, dlerror()); return CKR_FUNCTION_FAILED; } _m_get_ep11_info = dlsym(lib_ep11, "m_get_ep11_info"); _ep11a_cmdblock = dlsym(lib_ep11, "ep11a_cmdblock"); _m_admin = dlsym(lib_ep11, "m_admin"); _ep11a_internal_rv = dlsym(lib_ep11, "ep11a_internal_rv"); if (!_m_get_ep11_info || !_ep11a_cmdblock || !_m_admin || !_ep11a_internal_rv) { fprintf(stderr,"ERROR getting function pointer from shared lib '%s'", EP11SHAREDLIB); return CKR_FUNCTION_FAILED; } printf("Using slot #%lu...\n\n", SLOT_ID); rc = do_GetFunctionList(); if(! rc) { fprintf(stderr,"ERROR do_GetFunctionList() Failed, rx = 0x%0x\n", rc); return rc; } memset( &cinit_args, 0x0, sizeof(cinit_args) ); cinit_args.flags = CKF_OS_LOCKING_OK; funcs->C_Initialize( &cinit_args ); { CK_SESSION_HANDLE hsess = 0; rc = funcs->C_GetFunctionStatus(hsess); if (rc != CKR_FUNCTION_NOT_PARALLEL){ return rc; } rc = funcs->C_CancelFunction(hsess); if (rc != CKR_FUNCTION_NOT_PARALLEL){ return rc; } } flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; rc = funcs->C_OpenSession(SLOT_ID, flags, NULL, NULL, &session ); if (rc != CKR_OK) { fprintf(stderr,"C_OpenSession() rc = 0x%02x [%s]\n",rc, p11_get_ckr(rc)); session = CK_INVALID_HANDLE; return rc; } if (get_user_pin(user_pin)) { fprintf(stderr,"get_user_pin() failed\n"); rc = funcs->C_CloseAllSessions(SLOT_ID); if (rc != CKR_OK) fprintf(stderr,"C_CloseAllSessions() rc = 0x%02x [%s]\n",rc, p11_get_ckr(rc)); return rc; } user_pin_len = (CK_ULONG) strlen( (char *) user_pin); rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len); if (rc != CKR_OK) { fprintf(stderr,"C_Login() rc = 0x%02x [%s]\n",rc, p11_get_ckr(rc)); return rc; } if (check_card_status() != 0) return 1; /* find all objects */ rc = funcs->C_FindObjectsInit(session,NULL,0); do { rc = funcs->C_FindObjects(session, key_store, 4096, &keys_found); if (rc != CKR_OK) { fprintf(stderr,"C_FindObjects() rc = 0x%02x [%s]\n",rc, p11_get_ckr(rc)); return rc; } for (obj = 0; obj < keys_found; obj++) { CK_ATTRIBUTE opaque_template[] = { {CKA_IBM_OPAQUE, NULL_PTR, 0} }; CK_KEY_TYPE keytype; CK_ATTRIBUTE key_type_template[] = { {CKA_KEY_TYPE, &keytype, sizeof(CK_KEY_TYPE)} }; CK_BYTE *old_blob; /* only for keys */ rc = funcs->C_GetAttributeValue(session, key_store[obj], key_type_template, 1); if (rc != CKR_OK) continue; /* exist and size query CKA_IBM_QPAQUE*/ rc = funcs->C_GetAttributeValue(session, key_store[obj], opaque_template, 1); if (rc == CKR_OK) { old_blob = malloc(opaque_template[0].ulValueLen); opaque_template[0].pValue = old_blob; /* get the blob after knowing its size */ rc = funcs->C_GetAttributeValue(session, key_store[obj], opaque_template, 1); if (rc != CKR_OK) { fprintf(stderr,"second C_GetAttributeValue failed rc = 0x%02x [%s]\n", rc, p11_get_ckr(rc)); return rc; } else { if (reencrypt(session,obj,(CK_BYTE *) opaque_template[0].pValue) != 0) { /* reencrypt failed */ return -1; } } free(old_blob); } } } /* next 4096 objects */ while(keys_found != 0); rc = funcs->C_FindObjectsFinal(session); fprintf(stderr,"all keys successfully reencrypted\n"); rc = funcs->C_Logout(session); rc = funcs->C_CloseAllSessions(SLOT_ID); return rc; } opencryptoki+dfsg/usr/sbin/pkcsconf/0000755000175000017500000000000012630407154016651 5ustar xnoxxnoxopencryptoki+dfsg/usr/sbin/pkcsconf/pkcsconf.c0000755000175000017500000014107012630407154020631 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "slotmgr.h" #include "pkcsconf_msg.h" #include "p11util.h" #define LEEDS_DEFAULT_PIN "87654321" #define PIN_SIZE 80 #define BACK_SPACE 8 #define DELETE 127 #define LINE_FEED 10 #define CFG_SO_PIN 0x0001 #define CFG_USER_PIN 0x0002 #define CFG_SLOT 0x0004 #define CFG_PKCS_INFO 0x0008 #define CFG_TOKEN_INFO 0x0010 #define CFG_SLOT_INFO 0x0020 #define CFG_MECHANISM_INFO 0x0040 #define CFG_INITIALIZE 0x0080 #define CFG_INIT_USER 0x0100 #define CFG_SET_USER 0x0200 #define CFG_SET_SO 0x0400 #define CFG_NEW_PIN 0x0800 #define CFG_SHARED_MEM 0x1000 #define CFG_LIST_SLOT 0x2000 CK_RV init(void); void usage(char *); int echo(int); int get_pin(CK_CHAR **); CK_RV cleanup(void); CK_RV display_pkcs11_info(void); CK_RV get_slot_list(void); CK_RV display_slot_info(int); CK_RV display_token_info(int); CK_RV display_mechanism_info(int); CK_RV init_token(int, CK_CHAR_PTR); CK_RV init_user_pin(int, CK_CHAR_PTR, CK_CHAR_PTR); CK_RV list_slot(int); CK_RV set_user_pin(int, CK_USER_TYPE, CK_CHAR_PTR, CK_CHAR_PTR); void * dllPtr; CK_FUNCTION_LIST_PTR FunctionPtr = NULL; CK_SLOT_ID_PTR SlotList = NULL; CK_ULONG SlotCount = 0; Slot_Mgr_Shr_t * shmp = NULL; int in_slot; int main(int argc, char *argv[]){ CK_RV rc = CKR_OK; // Return Code CK_FLAGS flags = 0; // Bit mask for what options were passed in CK_CHAR_PTR sopin = NULL, // The Security Office PIN pin = NULL, // The User PIN newpin = NULL, // To store PIN changes newpin2 = NULL, // To store validation of PIN change slot = NULL; // The PKCS slot number int c, // To store passed in options newpinlen, newpin2len, errflag = 0; // Error Flag /* Parse the command line parameters */ while ((c = getopt (argc, argv, "itsmIc:S:U:upPn:lh")) != (-1)){ switch (c){ case 'c': /* a specific card (slot) is specified */ if (flags & CFG_SLOT) { printf("Must specify a single slot.\n"); fflush(stdout); errflag++; } else { flags |= CFG_SLOT; slot = (CK_CHAR_PTR) malloc(strlen(optarg)+1); memcpy(slot, optarg, strlen(optarg)+1); } break; case 'S': /* the SO pin */ if (flags & CFG_SO_PIN) { printf("Must specify a single SO PIN.\n"); fflush(stdout); errflag++; } else { flags |= CFG_SO_PIN; sopin = (CK_CHAR_PTR) malloc(strlen(optarg)+1); memcpy(sopin, optarg, strlen(optarg)+1); } break; case 'U': /* the user pin */ if (flags & CFG_USER_PIN) { printf("Must specify a single user PIN.\n"); fflush(stdout); errflag++; } else { flags |= CFG_USER_PIN; pin = (CK_CHAR_PTR) malloc(strlen(optarg)+1); memcpy(pin, optarg, strlen(optarg)+1); } break; case 'n': /* the new pin */ if (flags & CFG_NEW_PIN) { printf("Must specify a single new PIN.\n"); fflush(stdout); errflag++; } else { flags |= CFG_NEW_PIN; newpin = (CK_CHAR_PTR) malloc(strlen(optarg)+1); memcpy(newpin, optarg, strlen(optarg)+1); } break; case 'i': /* display PKCS11 info */ flags |= CFG_PKCS_INFO; break; case 't': /* display token info */ flags |= CFG_TOKEN_INFO; break; case 's': /* display slot info */ flags |= CFG_SLOT_INFO; break; case 'm': /* display mechanism info */ flags |= CFG_MECHANISM_INFO; break; case 'I': /* initialize the token */ flags |= CFG_INITIALIZE; break; case 'u': /* initialize the user PIN */ flags |= CFG_INIT_USER; break; case 'p': /* set the user PIN */ flags |= CFG_SET_USER; break; case 'P': /* set the SO PIN */ flags |= CFG_SET_SO; break; case 'l': /* display slot description */ flags |= CFG_LIST_SLOT; break; case 'h': /* display command line options */ usage(argv[0]); break; default: /* if something else was passed in it is an error */ errflag++; break; } } if (errflag != 0) /* If there was an error print the usage statement */ usage(argv[0]); if (!flags) /* If there was no options print the usage statement */ usage(argv[0]); /* Eliminate the ability to specify -I -p -u -P without a slot number */ if ( (flags & (CFG_INITIALIZE | CFG_INIT_USER | CFG_SET_USER | CFG_SET_SO)) && !(flags & CFG_SLOT)){ usage(argv[0]); } /* Load the PKCS11 library and start the slotmanager if it is not running */ if ( init() != CKR_OK ) exit(-1); if (flags & CFG_SLOT) { in_slot = atol((char *)slot); } /* Get the slot list and indicate if a slot number was passed in or not */ if ((rc = get_slot_list())) goto done; /* If the user tries to set the user and SO pin at the same time print an * error massage and exit indicating the function failed */ if ((flags & CFG_SET_USER) && (flags & CFG_SET_SO)) { printf("Setting the SO and user PINs are mutually exclusive.\n"); fflush(stdout); return CKR_FUNCTION_FAILED; } /* If the user wants to display PKCS11 info call the function to do so */ if (flags & CFG_PKCS_INFO) if ((rc = display_pkcs11_info())) goto done; /* If the user wants to display token info call the function to do so */ if (flags & CFG_TOKEN_INFO) if ((rc = display_token_info((flags & CFG_SLOT) ? in_slot : -1))) goto done; /* If the user wants to display slot info call the function to do so */ if (flags & CFG_SLOT_INFO) if ((rc = display_slot_info((flags & CFG_SLOT) ? in_slot : -1))) goto done; /* If the user wants to display slot info call the function to do so */ if (flags & CFG_LIST_SLOT) if ((rc = list_slot((flags & CFG_SLOT) ? in_slot : -1))) goto done; /* If the user wants to display mechanism info call the function to do so */ if (flags & CFG_MECHANISM_INFO) if ((rc = display_mechanism_info((flags & CFG_SLOT) ? in_slot : -1))) goto done; /* If the user wants to initialize the card check to see if they passed in * the SO pin, if not ask for the PIN */ if (flags & CFG_INITIALIZE){ if (flags & CFG_SLOT){ if (~flags & CFG_SO_PIN){ int rc; do { printf("Enter the SO PIN: "); fflush(stdout); rc = get_pin(&(sopin)); } while (rc == -EINVAL); } rc = init_token(in_slot, sopin); } else { printf("Must specify one slot"); fflush(stdout); rc = -EINVAL; } } /* If the user wants to initialize the User PIN, check to see if they have * passed in the SO PIN, if not ask for it. Then check to see if they passed * the New User PIN on the command line if not ask for the PIN and verify it */ if (flags & CFG_INIT_USER){ if (flags & CFG_SLOT){ if (~flags & CFG_SO_PIN) { int rc; do { printf("Enter the SO PIN: "); fflush(stdout); rc = get_pin(&sopin); } while (rc == -EINVAL); } if (~flags & CFG_NEW_PIN) { int rc; do { printf("Enter the new user PIN: "); fflush(stdout); rc = get_pin(&newpin); } while (rc == -EINVAL); newpinlen = strlen((char *)newpin); do { printf("Re-enter the new user PIN: "); fflush(stdout); rc = get_pin(&newpin2); } while (rc == -EINVAL); newpin2len = strlen((char *)newpin2); if (newpinlen != newpin2len || memcmp(newpin, newpin2, strlen((char *)newpin)) != 0) { printf("New PINs do not match.\n"); fflush(stdout); exit(CKR_PIN_INVALID); } } rc = init_user_pin(in_slot, newpin, sopin); } else { printf("Must specify one slot"); fflush(stdout); rc = -EINVAL; } } /* If the user wants to set the SO PIN, check to see if they have passed the * current SO PIN and the New PIN in. If not prompt and validate them. */ if (flags & CFG_SET_SO){ if (flags & CFG_SLOT){ if (~flags & CFG_SO_PIN) { int rc; do { printf("Enter the SO PIN: "); fflush(stdout); rc = get_pin(&sopin); } while (rc == -EINVAL); } if (~flags & CFG_NEW_PIN) { int rc; do { printf("Enter the new SO PIN: "); fflush(stdout); rc = get_pin(&newpin); } while (rc == -EINVAL); newpinlen = strlen((char *)newpin); do { printf("Re-enter the new SO PIN: "); fflush(stdout); rc = get_pin(&newpin2); } while (rc == -EINVAL); newpin2len = strlen((char *)newpin2); if (newpinlen != newpin2len || memcmp(newpin, newpin2, strlen((char *)newpin)) != 0) { printf("New PINs do not match.\n"); fflush(stdout); exit(CKR_PIN_INVALID); } } rc = set_user_pin(in_slot, CKU_SO, sopin, newpin); } else { printf("Must specify one slot"); fflush(stdout); rc = -EINVAL; } } /* If the user wants to set the User PIN, check to see if they have passed the * current User PIN and the New PIN in. If not prompt and validate them. */ if (flags & CFG_SET_USER){ if (flags & CFG_SLOT){ if (~flags & CFG_USER_PIN) { int rc; do { printf("Enter user PIN: "); fflush(stdout); rc = get_pin(&pin); } while (rc == -EINVAL); } if (~flags & CFG_NEW_PIN) { do { printf("Enter the new user PIN: "); fflush(stdout); rc = get_pin(&newpin); } while (rc == -EINVAL); newpinlen = strlen((char *)newpin); do { printf("Re-enter the new user PIN: "); fflush(stdout); rc = get_pin(&newpin2); } while (rc == -EINVAL); newpin2len = strlen((char *)newpin2); if (newpinlen != newpin2len || memcmp(newpin, newpin2, strlen((char *)newpin)) != 0) { printf("New PINs do not match.\n"); fflush(stdout); exit(CKR_PIN_INVALID); } } rc = set_user_pin(in_slot, CKU_USER, pin, newpin); } else { printf("Must specify one slot"); fflush(stdout); rc = -EINVAL; } } /* We are done, detach from shared memory, and free the memory we may have * allocated. In the case of PIN's we memset them to ensure that they are not * left around in system memory*/ done: if (sopin) { memset(sopin, 0, strlen((char *)sopin)); free (sopin); } if (pin) { memset(pin, 0, strlen((char *)pin)); free (pin); } if (newpin) { memset(newpin, 0, strlen((char *)newpin)); free (newpin); } if (newpin2) { memset(newpin2, 0, strlen((char *)newpin2)); free (newpin2); } return ((rc == 0) || (rc % 256) ? rc : -1); } int get_pin(CK_CHAR **pin) { int count; char buff[PIN_SIZE] = { 0 }, c = 0; int rc = 0; *pin = NULL; /* Turn off echoing to the terminal when getting the password */ echo(FALSE); /* Get each character and print out a '*' for each input */ for (count = 0; (c != LINE_FEED) && (count < PIN_SIZE);) { buff[count] = getc(stdin); c = buff[count]; if (c == BACK_SPACE || c == DELETE) { if (count) count--; continue; } fflush(stdout); count++; } echo(TRUE); /* After we get the password go to the next line */ printf("\n"); fflush(stdout); /* Allocate 80 bytes for the user PIN. This is large enough * for the tokens supported in AIX 5.0 and 5.1 */ *pin = (unsigned char *)malloc(PIN_SIZE); if (!(*pin)) { rc = -ENOMEM; goto out; } /* Strip the carage return from the user input (it is not part * of the PIN) and put the PIN in the return buffer */ buff[count - 1] = '\0'; /* keep the trailing null for the strlen */ strncpy((char *)*pin, buff, (strlen((char *)buff) + 1)); out: return rc; } int echo(int bool){ struct termios term; /* flush standard out to make sure everything that needs to be displayed has * been displayed */ fflush(stdout); /* get the current terminal attributes */ if (tcgetattr(STDIN_FILENO, &term) != 0) return -1; /* Since we are calling this function we must want to read in a char at a * time. Therefore set the cc structure before setting the terminal attrs */ term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; /* If we are turning off the display of input characters AND with the inverse * of the ECHO mask, if we are turning on the display OR with the ECHO mask. * We also set if we are reading in canonical or noncanonical mode. */ if (bool) term.c_lflag |= (ECHO | ICANON); else term.c_lflag &= ~(ECHO | ICANON); /* Set the attributes, and flush the streams so that any input already * displayed on the terminal is invalid */ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term) != 0) return -1; return 0; } CK_RV display_pkcs11_info(void){ CK_RV rc; CK_INFO CryptokiInfo; /* Get the PKCS11 infomation structure and if fails print message */ rc = FunctionPtr->C_GetInfo(&CryptokiInfo); if (rc != CKR_OK) { printf("Error getting PKCS#11 info: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } /* display the header and information */ printf("PKCS#11 Info\n"); printf("\tVersion %d.%d \n", CryptokiInfo.cryptokiVersion.major, CryptokiInfo.cryptokiVersion.minor); printf("\tManufacturer: %.32s \n", CryptokiInfo.manufacturerID); printf("\tFlags: 0x%lX \n", CryptokiInfo.flags); printf("\tLibrary Description: %.32s \n", CryptokiInfo.libraryDescription); printf("\tLibrary Version %d.%d \n", CryptokiInfo.libraryVersion.major, CryptokiInfo.libraryVersion.minor); return rc; } CK_RV get_slot_list(){ CK_RV rc; // Return Code /* Find out how many tokens are present in slots */ rc = FunctionPtr->C_GetSlotList(TRUE, NULL_PTR, &SlotCount); if (rc != CKR_OK) { printf("Error getting number of slots: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } if (SlotCount == 0) { printf("C_GetSlotList returned 0 slots. Check that your tokens" " are installed correctly.\n"); return -ENODEV; } /* Allocate enough space for the slots information */ SlotList = (CK_SLOT_ID_PTR) malloc(SlotCount * sizeof(CK_SLOT_ID)); rc = FunctionPtr->C_GetSlotList(TRUE, SlotList, &SlotCount); if (rc != CKR_OK) { printf("Error getting slot list: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } return CKR_OK; } void display_mechanism_name(CK_MECHANISM_TYPE mech) { CK_ULONG i; for (i = 0; pkcs11_mech_list[i].name; i++) { if (pkcs11_mech_list[i].mech == mech) { printf("(%s)", pkcs11_mech_list[i].name); return; } } } void display_mechanism_flags(CK_FLAGS flags) { CK_ULONG i, firsties = 1; for (i = 0; pkcs11_mech_flags[i].name; i++) { if (pkcs11_mech_flags[i].flag & flags) { if (firsties) { printf("("); firsties = 0; } printf("%s|", pkcs11_mech_flags[i].name); } } if (!firsties) { printf(")"); } } CK_RV print_mech_info(int slot_id) { CK_RV rc; // Return Code CK_MECHANISM_TYPE_PTR MechanismList = NULL; // Head to Mechanism list CK_MECHANISM_INFO MechanismInfo; // Structure to hold Mechanism Info CK_ULONG MechanismCount = 0; // Number of supported mechanisms unsigned int i; /* For each slot find out how many mechanisms are supported */ rc = FunctionPtr->C_GetMechanismList(slot_id, NULL_PTR, &MechanismCount); if (rc != CKR_OK) { printf("Error getting number of mechanisms: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } /* Allocate enough memory to store all the supported mechanisms */ MechanismList = (CK_MECHANISM_TYPE_PTR) malloc(MechanismCount * sizeof(CK_MECHANISM_TYPE)); /* This time get the mechanism list */ rc = FunctionPtr->C_GetMechanismList(slot_id, MechanismList, &MechanismCount); if (rc != CKR_OK) { printf("Error getting mechanisms list: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } /* For each Mechanism in the List */ for (i = 0; i < MechanismCount; i++){ /* Get the Mechanism Info and display it */ rc = FunctionPtr->C_GetMechanismInfo(slot_id, MechanismList[i], &MechanismInfo); if (rc != CKR_OK) { printf("Error getting mechanisms info: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } printf("Mechanism #%d\n", i); printf("\tMechanism: 0x%lX ", MechanismList[i]); display_mechanism_name(MechanismList[i]); printf("\n"); printf("\tKey Size: %lu-%lu\n", MechanismInfo.ulMinKeySize, MechanismInfo.ulMaxKeySize); printf("\tFlags: 0x%lX ", MechanismInfo.flags); display_mechanism_flags(MechanismInfo.flags); printf("\n"); } /* Free the memory we allocated for the mechanism list */ free (MechanismList); return CKR_OK; } CK_RV display_mechanism_info(int slot_id){ CK_ULONG lcv; if (slot_id == -1) { for (lcv = 0; lcv < SlotCount; lcv++) { printf("Mechanism Info for Slot #%lu:\n", SlotList[lcv]); print_mech_info(SlotList[lcv]); } } else return print_mech_info(slot_id); return CKR_OK; } void print_slot_info(int slot_id, CK_SLOT_INFO *SlotInfo) { /* Display the slot information */ printf("Slot #%d Info\n", slot_id); printf("\tDescription: %.64s\n", SlotInfo->slotDescription); printf("\tManufacturer: %.32s\n", SlotInfo->manufacturerID); printf("\tFlags: 0x%lX (", SlotInfo->flags); if (SlotInfo->flags & CKF_TOKEN_PRESENT) printf("TOKEN_PRESENT|"); if (SlotInfo->flags & CKF_REMOVABLE_DEVICE) printf("REMOVABLE_DEVICE|"); if (SlotInfo->flags & CKF_HW_SLOT) printf("HW_SLOT|"); printf(")\n"); printf("\tHardware Version: %d.%d\n", SlotInfo->hardwareVersion.major, SlotInfo->hardwareVersion.minor); printf("\tFirmware Version: %d.%d\n", SlotInfo->firmwareVersion.major, SlotInfo->firmwareVersion.minor); } CK_RV display_slot_info(int slot_id) { CK_RV rc; // Return Code CK_SLOT_INFO SlotInfo; // Structure to hold slot information unsigned int lcv; // Loop control Variable if (slot_id != -1) { rc = FunctionPtr->C_GetSlotInfo(slot_id, &SlotInfo); if (rc != CKR_OK) { printf("Error getting slot info: 0x%lX (%s) \n", rc, p11_get_ckr(rc)); return rc; } print_slot_info(slot_id, &SlotInfo); return CKR_OK; } for (lcv = 0; lcv < SlotCount; lcv++){ /* Get the info for the slot we are examining and store in SlotInfo*/ rc = FunctionPtr->C_GetSlotInfo(SlotList[lcv], &SlotInfo); if (rc != CKR_OK) { printf("Error getting slot info: 0x%lX (%s) \n", rc, p11_get_ckr(rc)); return rc; } print_slot_info(SlotList[lcv], &SlotInfo); } return CKR_OK; } CK_RV list_slot(int slot_id){ CK_RV rc; // Return code CK_SLOT_INFO SlotInfo; // Structure to hold slot information unsigned int lcv; // Loop control variable if (slot_id != -1) { rc = FunctionPtr->C_GetSlotInfo(slot_id, &SlotInfo); if (rc != CKR_OK) { printf("Error getting slot info: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } /* Display the slot description */ printf("%d:", slot_id); printf("\tDescription: %.64s\n", SlotInfo.slotDescription); return CKR_OK; } for (lcv = 0; lcv < SlotCount; lcv++){ /* Get the info for the slot we are examining and store in SlotInfo*/ rc = FunctionPtr->C_GetSlotInfo(SlotList[lcv], &SlotInfo); if (rc != CKR_OK) { printf("Error getting slot info: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } /* Display the slot description */ printf("%ld:", SlotList[lcv]); printf("\tDescription: %.64s\n", SlotInfo.slotDescription); } return CKR_OK; } void print_token_info(int slot_id, CK_TOKEN_INFO *TokenInfo) { /* Display the token information */ printf("Token #%d Info:\n", slot_id); printf("\tLabel: %.32s\n", TokenInfo->label); printf("\tManufacturer: %.32s\n", TokenInfo->manufacturerID); printf("\tModel: %.16s\n", TokenInfo->model); printf("\tSerial Number: %.16s\n", TokenInfo->serialNumber); printf("\tFlags: 0x%lX (", TokenInfo->flags); /* print more informative flag message */ if (TokenInfo->flags & CKF_RNG) printf("RNG|"); if (TokenInfo->flags & CKF_WRITE_PROTECTED) printf("WRITE_PROTECTED|"); if (TokenInfo->flags & CKF_LOGIN_REQUIRED) printf("LOGIN_REQUIRED|"); if (TokenInfo->flags & CKF_USER_PIN_INITIALIZED) printf("USER_PIN_INITIALIZED|"); if (TokenInfo->flags & CKF_RESTORE_KEY_NOT_NEEDED) printf("RESTORE_KEY_NOT_NEEDED|"); if (TokenInfo->flags & CKF_CLOCK_ON_TOKEN) printf("CLOCK_ON_TOKEN|"); if (TokenInfo->flags & CKF_PROTECTED_AUTHENTICATION_PATH) printf("PROTECTED_AUTHENTICATION_PATH|"); if (TokenInfo->flags & CKF_DUAL_CRYPTO_OPERATIONS) printf("DUAL_CRYPTO_OPERATIONS|"); if (TokenInfo->flags & CKF_TOKEN_INITIALIZED) printf("TOKEN_INITIALIZED|"); if (TokenInfo->flags & CKF_SECONDARY_AUTHENTICATION) printf("SECONDARY_AUTHENTICATION|"); if (TokenInfo->flags & CKF_USER_PIN_COUNT_LOW) printf("USER_PIN_COUNT_LOW|"); if (TokenInfo->flags & CKF_USER_PIN_FINAL_TRY) printf("USER_PIN_FINAL_TRY|"); if (TokenInfo->flags & CKF_USER_PIN_LOCKED) printf("USER_PIN_LOCKED|"); if (TokenInfo->flags & CKF_USER_PIN_TO_BE_CHANGED) printf("USER_PIN_TO_BE_CHANGED|"); if (TokenInfo->flags & CKF_SO_PIN_COUNT_LOW) printf("SO_PIN_COUNT_LOW|"); if (TokenInfo->flags & CKF_SO_PIN_FINAL_TRY) printf("SO_PIN_FINAL_TRY|"); if (TokenInfo->flags & CKF_SO_PIN_LOCKED) printf("SO_PIN_LOCKED|"); if (TokenInfo->flags & CKF_SO_PIN_TO_BE_CHANGED) printf("SO_PIN_TO_BE_CHANGED|"); printf(")\n"); printf("\tSessions: %lu/%lu\n", TokenInfo->ulSessionCount, TokenInfo->ulMaxSessionCount); printf("\tR/W Sessions: %lu/%lu\n", TokenInfo->ulRwSessionCount, TokenInfo->ulMaxRwSessionCount); printf("\tPIN Length: %lu-%lu\n", TokenInfo->ulMinPinLen, TokenInfo->ulMaxPinLen); printf("\tPublic Memory: 0x%lX/0x%lX\n", TokenInfo->ulFreePublicMemory, TokenInfo->ulTotalPublicMemory); printf("\tPrivate Memory: 0x%lX/0x%lX\n", TokenInfo->ulFreePrivateMemory, TokenInfo->ulTotalPrivateMemory); printf("\tHardware Version: %d.%d\n", TokenInfo->hardwareVersion.major, TokenInfo->hardwareVersion.minor); printf("\tFirmware Version: %d.%d\n", TokenInfo->firmwareVersion.major, TokenInfo->firmwareVersion.minor); printf("\tTime: %.16s\n", TokenInfo->utcTime); } CK_RV display_token_info(int slot_id) { CK_RV rc; // Return Code CK_TOKEN_INFO TokenInfo; // Variable to hold Token Information unsigned int lcv; // Loop control variable if (slot_id != -1) { rc = FunctionPtr->C_GetTokenInfo(slot_id, &TokenInfo); if (rc != CKR_OK) { printf("Error getting token info: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } print_token_info(slot_id, &TokenInfo); return CKR_OK; } for (lcv = 0; lcv < SlotCount; lcv++){ /* Get the Token info for each slot in the system */ rc = FunctionPtr->C_GetTokenInfo(SlotList[lcv], &TokenInfo); if (rc != CKR_OK) { printf("Error getting token info: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); return rc; } print_token_info(SlotList[lcv], &TokenInfo); } return CKR_OK; } CK_RV init_token(int slot_id, CK_CHAR_PTR pin){ /* Note this function reinitializes a token to the state it was * in just after the initial install * It does the following actions (if SO pin is correct): * (1) Purges all Token Objects * (2) Resets SO PIN back to the default * (3) Purges the USER PIN * (4) Sets the Token Label */ CK_RV rc; // Return Code CK_ULONG pinlen; // Length of the PIN CK_CHAR label[32], // What we want to set the Label of the card to enteredlabel[33]; // Max size of 32 + carriage return; /* Find out the size of the entered PIN */ pinlen = strlen((char *)pin); /* Get the token label from the user, NOTE it states to give a unique label * but it is never verified as unique. This is becuase Netscape requires a * unique token label; however the PKCS11 spec does not. */ printf("Enter a unique token label: "); fflush(stdout); memset(enteredlabel, 0, sizeof(enteredlabel)); if (fgets((char *)enteredlabel, sizeof(enteredlabel), stdin) == NULL) printf("\n"); else enteredlabel[strcspn((const char*)enteredlabel,"\n")] = '\0'; /* First clear the label array. Per PKCS#11 spec, We must PAD this field to * 32 bytes, and it should NOT be null-terminated */ memset(label, ' ', sizeof(label)); strncpy((char *)label, (char *)enteredlabel, strlen((char *)enteredlabel)); rc = FunctionPtr->C_InitToken(slot_id, pin, pinlen, label); if (rc != CKR_OK) { if (rc == CKR_PIN_INCORRECT) { printf("Incorrect PIN Entered.\n"); fflush(stdout); } else { printf("Error initializing token: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); } return rc; } return CKR_OK; } CK_RV init_user_pin(int slot_id, CK_CHAR_PTR pin, CK_CHAR_PTR sopin){ CK_RV rc; // Return Value CK_FLAGS flags = 0; // Mask that we will use when opening the session CK_SESSION_HANDLE session_handle; // The session handle we get CK_ULONG pinlen, sopinlen; // Length of the user and SO PINs /* get the length of the PINs */ pinlen = strlen((char *)pin); sopinlen = strlen((char *)sopin); /* set the mask we will use for Open Session */ flags |= CKF_SERIAL_SESSION; flags |= CKF_RW_SESSION; /* We need to open a read/write session to the adapter to initialize the user * PIN. Attempt to do so */ rc = FunctionPtr->C_OpenSession(slot_id, flags, NULL, NULL, &session_handle); if (rc != CKR_OK){ printf("Error opening session: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); return rc; } /* After the session is open, we must login as the SO to initialize the PIN */ rc = FunctionPtr->C_Login(session_handle, CKU_SO, sopin, sopinlen); if (rc != CKR_OK){ if (rc == CKR_PIN_INCORRECT) { printf("Incorrect PIN Entered.\n"); fflush(stdout); } else { printf("Error logging in: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); } return rc; } /* Call the function to Init the PIN */ rc = FunctionPtr->C_InitPIN(session_handle, pin, pinlen); if (rc != CKR_OK){ printf("Error setting PIN: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); } /* Logout so that others can use the PIN */ rc = FunctionPtr->C_Logout(session_handle); if (rc != CKR_OK){ printf("Error logging out: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); } /* Close the session */ rc = FunctionPtr->C_CloseSession(session_handle); if (rc != CKR_OK){ printf("Error closing session: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); return rc; } return CKR_OK; } CK_RV set_user_pin(int slot_id, CK_USER_TYPE user, CK_CHAR_PTR oldpin, CK_CHAR_PTR newpin){ CK_RV rc; // Return Value CK_FLAGS flags = 0; // Mash ot open the session with CK_SESSION_HANDLE session_handle; // The handle of the session we will open CK_ULONG oldpinlen, newpinlen; // The size of the new and ole PINS /* NOTE: This function is used for both the settinf of the SO and USER pins, * the CK_USER_TYPE specifes which we are changing. */ /* Get the size of the PINs */ oldpinlen = strlen((char *)oldpin); newpinlen = strlen((char *)newpin); /* set the flags we will open the session with */ flags |= CKF_SERIAL_SESSION; flags |= CKF_RW_SESSION; /* Open the Session */ rc = FunctionPtr->C_OpenSession(slot_id, flags, NULL, NULL, &session_handle); if (rc != CKR_OK){ printf("Error opening session: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); return rc; } /* Login to the session we just created as the pkcs11 passed in USER type */ rc = FunctionPtr->C_Login(session_handle, user, oldpin, oldpinlen); if (rc != CKR_OK){ if (rc == CKR_PIN_INCORRECT) { printf("Incorrect PIN Entered.\n"); fflush(stdout); } else { printf("Error logging in: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); } return rc; } /* set the new PIN */ rc = FunctionPtr->C_SetPIN(session_handle, oldpin, oldpinlen, newpin, newpinlen); if (rc != CKR_OK){ printf("Error setting PIN: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); } /* and of course clean up after ourselves */ rc = FunctionPtr->C_CloseSession(session_handle); if (rc != CKR_OK){ printf("Error closing session: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); return rc; } return CKR_OK; } CK_RV init(void){ CK_RV rc = CKR_OK; // Return Code void (*symPtr)(); // Pointer for the Dll /* Open the PKCS11 API shared library, and inform the user is there is an * error */ /* The host machine should have the right library in the * LD_LIBRARY_PATH */ dllPtr = dlopen("libopencryptoki.so", RTLD_NOW); if (!dllPtr) { printf("Error loading PKCS#11 library\n"); printf("dlopen error: %s\n", dlerror()); fflush(stdout); return -1; } /* Get the list of the PKCS11 functions this token support */ symPtr = (void (*)())dlsym(dllPtr, "C_GetFunctionList"); if (!symPtr) { rc = errno; printf("Error getting function list: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); return rc; } symPtr(&FunctionPtr); /* If we get here we know the slot manager is running and we can use PKCS11 * calls, so we will execute the PKCS11 Initilize command. */ rc = FunctionPtr->C_Initialize(NULL); if (rc != CKR_OK) { printf("Error initializing the PKCS11 library: 0x%lX (%s)\n", rc, p11_get_ckr(rc)); fflush(stdout); cleanup(); } return rc; } CK_RV cleanup(void){ CK_RV rc; // Return Code /* To clean up we will free the slot list we create, call the Finalize * routine for PKCS11 and close the dynamically linked library */ free (SlotList); rc = FunctionPtr->C_Finalize(NULL); if (dllPtr) dlclose(dllPtr); exit (rc); } void usage(char *progname){ /* If we get here the user needs help, so give it to them */ printf("usage:\t%s [-itsmIupPh] [-c slotnumber -U userPIN -S SOPin -n newpin]\n", progname); printf("\t-i display PKCS11 info\n"); printf("\t-t display token info\n"); printf("\t-s display slot info\n"); printf("\t-m display mechanism list\n"); printf("\t-l display slot description\n"); printf("\t-I initialize token \n"); printf("\t-u initialize user PIN\n"); printf("\t-p set the user PIN\n"); printf("\t-P set the SO PIN\n"); printf("\t-h show this help\n"); exit(-1); } opencryptoki+dfsg/usr/sbin/pkcsconf/pkcsconf_msg.h0000755000175000017500000006255612630407154021517 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/sbin/pkcsconf/pkcsconf_msg.h,v 1.1 2005/04/11 20:22:18 mhalcrow Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _H_PKCSCONF_MSG #define _H_PKCSCONF_MSG /* list of mechanism flags and their printable string names */ struct _pkcs11_mech_flags { char *name; CK_FLAGS flag; } pkcs11_mech_flags[] = { { "CKF_HW", CKF_HW }, { "CKF_ENCRYPT", CKF_ENCRYPT }, { "CKF_DECRYPT", CKF_DECRYPT }, { "CKF_DIGEST", CKF_DIGEST }, { "CKF_SIGN", CKF_SIGN }, { "CKF_SIGN_RECOVER", CKF_SIGN_RECOVER }, { "CKF_VERIFY", CKF_VERIFY }, { "CKF_VERIFY_RECOVER", CKF_VERIFY_RECOVER }, { "CKF_GENERATE", CKF_GENERATE }, { "CKF_GENERATE_KEY_PAIR", CKF_GENERATE_KEY_PAIR }, { "CKF_WRAP", CKF_WRAP }, { "CKF_UNWRAP", CKF_UNWRAP }, { "CKF_DERIVE", CKF_DERIVE }, { "CKF_EC_F_P", CKF_EC_F_P }, { "CKF_EC_F_2M", CKF_EC_F_2M }, { "CKF_EC_ECPARAMETERS", CKF_EC_ECPARAMETERS }, { "CKF_EC_NAMEDCURVE", CKF_EC_NAMEDCURVE }, { "CKF_EC_UNCOMPRESS", CKF_EC_UNCOMPRESS }, { "CKF_EC_COMPRESS", CKF_EC_COMPRESS }, { "CKF_EXTENSION", CKF_EXTENSION }, { NULL_PTR, 0xFFFFFFFF } }; /* list of mechanisms and their printable string names */ struct _pkcs11_mech_list { char *name; CK_MECHANISM_TYPE mech; } pkcs11_mech_list[] = { { "CKM_RSA_PKCS_KEY_PAIR_GEN", CKM_RSA_PKCS_KEY_PAIR_GEN }, { "CKM_RSA_PKCS", CKM_RSA_PKCS }, { "CKM_RSA_9796", CKM_RSA_9796 }, { "CKM_RSA_X_509", CKM_RSA_X_509 }, { "CKM_MD2_RSA_PKCS", CKM_MD2_RSA_PKCS }, { "CKM_MD5_RSA_PKCS", CKM_MD5_RSA_PKCS }, { "CKM_SHA1_RSA_PKCS", CKM_SHA1_RSA_PKCS }, { "CKM_RIPEMD128_RSA_PKCS", CKM_RIPEMD128_RSA_PKCS }, { "CKM_RIPEMD160_RSA_PKCS", CKM_RIPEMD160_RSA_PKCS }, { "CKM_RSA_PKCS_OAEP", CKM_RSA_PKCS_OAEP }, { "CKM_RSA_X9_31_KEY_PAIR_GEN", CKM_RSA_X9_31_KEY_PAIR_GEN }, { "CKM_RSA_X9_31", CKM_RSA_X9_31 }, { "CKM_SHA1_RSA_X9_31", CKM_SHA1_RSA_X9_31 }, { "CKM_RSA_PKCS_PSS", CKM_RSA_PKCS_PSS }, { "CKM_SHA1_RSA_PKCS_PSS", CKM_SHA1_RSA_PKCS_PSS }, { "CKM_DSA_KEY_PAIR_GEN", CKM_DSA_KEY_PAIR_GEN }, { "CKM_DSA", CKM_DSA }, { "CKM_DSA_SHA1", CKM_DSA_SHA1 }, { "CKM_DH_PKCS_KEY_PAIR_GEN", CKM_DH_PKCS_KEY_PAIR_GEN }, { "CKM_DH_PKCS_DERIVE", CKM_DH_PKCS_DERIVE }, { "CKM_X9_42_DH_KEY_PAIR_GEN", CKM_X9_42_DH_KEY_PAIR_GEN }, { "CKM_X9_42_DH_DERIVE", CKM_X9_42_DH_DERIVE }, { "CKM_X9_42_DH_HYBRID_DERIVE", CKM_X9_42_DH_HYBRID_DERIVE }, { "CKM_X9_42_MQV_DERIVE", CKM_X9_42_MQV_DERIVE }, { "CKM_SHA256_RSA_PKCS", CKM_SHA256_RSA_PKCS }, { "CKM_SHA384_RSA_PKCS", CKM_SHA384_RSA_PKCS }, { "CKM_SHA512_RSA_PKCS", CKM_SHA512_RSA_PKCS }, { "CKM_RC2_KEY_GEN", CKM_RC2_KEY_GEN }, { "CKM_RC2_ECB", CKM_RC2_ECB }, { "CKM_RC2_CBC", CKM_RC2_CBC }, { "CKM_RC2_MAC", CKM_RC2_MAC }, { "CKM_RC2_MAC_GENERAL", CKM_RC2_MAC_GENERAL }, { "CKM_RC2_CBC_PAD", CKM_RC2_CBC_PAD }, { "CKM_RC4_KEY_GEN", CKM_RC4_KEY_GEN }, { "CKM_RC4", CKM_RC4 }, { "CKM_DES_KEY_GEN", CKM_DES_KEY_GEN }, { "CKM_DES_ECB", CKM_DES_ECB }, { "CKM_DES_CBC", CKM_DES_CBC }, { "CKM_DES_MAC", CKM_DES_MAC }, { "CKM_DES_MAC_GENERAL", CKM_DES_MAC_GENERAL }, { "CKM_DES_CBC_PAD", CKM_DES_CBC_PAD }, { "CKM_DES_OFB64", CKM_DES_OFB64 }, { "CKM_DES_CFB8", CKM_DES_CFB8 }, { "CKM_DES_CFB64", CKM_DES_CFB64 }, { "CKM_DES2_KEY_GEN", CKM_DES2_KEY_GEN }, { "CKM_DES3_KEY_GEN", CKM_DES3_KEY_GEN }, { "CKM_DES3_ECB", CKM_DES3_ECB }, { "CKM_DES3_CBC", CKM_DES3_CBC }, { "CKM_DES3_MAC", CKM_DES3_MAC }, { "CKM_DES3_MAC_GENERAL", CKM_DES3_MAC_GENERAL }, { "CKM_DES3_CBC_PAD", CKM_DES3_CBC_PAD }, { "CKM_CDMF_KEY_GEN", CKM_CDMF_KEY_GEN }, { "CKM_CDMF_ECB", CKM_CDMF_ECB }, { "CKM_CDMF_CBC", CKM_CDMF_CBC }, { "CKM_CDMF_MAC", CKM_CDMF_MAC }, { "CKM_CDMF_MAC_GENERAL", CKM_CDMF_MAC_GENERAL }, { "CKM_CDMF_CBC_PAD", CKM_CDMF_CBC_PAD }, { "CKM_MD2", CKM_MD2 }, { "CKM_MD2_HMAC", CKM_MD2_HMAC }, { "CKM_MD2_HMAC_GENERAL", CKM_MD2_HMAC_GENERAL }, { "CKM_MD5", CKM_MD5 }, { "CKM_MD5_HMAC", CKM_MD5_HMAC }, { "CKM_MD5_HMAC_GENERAL", CKM_MD5_HMAC_GENERAL }, { "CKM_SHA_1", CKM_SHA_1 }, { "CKM_SHA_1_HMAC", CKM_SHA_1_HMAC }, { "CKM_SHA_1_HMAC_GENERAL", CKM_SHA_1_HMAC_GENERAL }, { "CKM_RIPEMD128", CKM_RIPEMD128 }, { "CKM_RIPEMD128_HMAC", CKM_RIPEMD128_HMAC }, { "CKM_RIPEMD128_HMAC_GENERAL", CKM_RIPEMD128_HMAC_GENERAL }, { "CKM_RIPEMD160", CKM_RIPEMD160 }, { "CKM_RIPEMD160_HMAC", CKM_RIPEMD160_HMAC }, { "CKM_RIPEMD160_HMAC_GENERAL", CKM_RIPEMD160_HMAC_GENERAL }, { "CKM_SHA256", CKM_SHA256 }, { "CKM_SHA256_HMAC", CKM_SHA256_HMAC }, { "CKM_SHA256_HMAC_GENERAL", CKM_SHA256_HMAC_GENERAL }, { "CKM_SHA384", CKM_SHA384 }, { "CKM_SHA384_HMAC", CKM_SHA384_HMAC }, { "CKM_SHA384_HMAC_GENERAL", CKM_SHA384_HMAC_GENERAL }, { "CKM_SHA512", CKM_SHA512 }, { "CKM_SHA512_HMAC", CKM_SHA512_HMAC }, { "CKM_SHA512_HMAC_GENERAL", CKM_SHA512_HMAC_GENERAL }, { "CKM_CAST_KEY_GEN", CKM_CAST_KEY_GEN }, { "CKM_CAST_ECB", CKM_CAST_ECB }, { "CKM_CAST_CBC", CKM_CAST_CBC }, { "CKM_CAST_MAC", CKM_CAST_MAC }, { "CKM_CAST_MAC_GENERAL", CKM_CAST_MAC_GENERAL }, { "CKM_CAST_CBC_PAD", CKM_CAST_CBC_PAD }, { "CKM_CAST3_KEY_GEN", CKM_CAST3_KEY_GEN }, { "CKM_CAST3_ECB", CKM_CAST3_ECB }, { "CKM_CAST3_CBC", CKM_CAST3_CBC }, { "CKM_CAST3_MAC", CKM_CAST3_MAC }, { "CKM_CAST3_MAC_GENERAL", CKM_CAST3_MAC_GENERAL }, { "CKM_CAST3_CBC_PAD", CKM_CAST3_CBC_PAD }, { "CKM_CAST5_KEY_GEN", CKM_CAST5_KEY_GEN }, { "CKM_CAST128_KEY_GEN", CKM_CAST128_KEY_GEN }, { "CKM_CAST5_ECB", CKM_CAST5_ECB }, { "CKM_CAST128_ECB", CKM_CAST128_ECB }, { "CKM_CAST5_CBC", CKM_CAST5_CBC }, { "CKM_CAST128_CBC", CKM_CAST128_CBC }, { "CKM_CAST5_MAC", CKM_CAST5_MAC }, { "CKM_CAST128_MAC", CKM_CAST128_MAC }, { "CKM_CAST5_MAC_GENERAL", CKM_CAST5_MAC_GENERAL }, { "CKM_CAST128_MAC_GENERAL", CKM_CAST128_MAC_GENERAL }, { "CKM_CAST5_CBC_PAD", CKM_CAST5_CBC_PAD }, { "CKM_CAST128_CBC_PAD", CKM_CAST128_CBC_PAD }, { "CKM_RC5_KEY_GEN", CKM_RC5_KEY_GEN }, { "CKM_RC5_ECB", CKM_RC5_ECB }, { "CKM_RC5_CBC", CKM_RC5_CBC }, { "CKM_RC5_MAC", CKM_RC5_MAC }, { "CKM_RC5_MAC_GENERAL", CKM_RC5_MAC_GENERAL }, { "CKM_RC5_CBC_PAD", CKM_RC5_CBC_PAD }, { "CKM_IDEA_KEY_GEN", CKM_IDEA_KEY_GEN }, { "CKM_IDEA_ECB", CKM_IDEA_ECB }, { "CKM_IDEA_CBC", CKM_IDEA_CBC }, { "CKM_IDEA_MAC", CKM_IDEA_MAC }, { "CKM_IDEA_MAC_GENERAL", CKM_IDEA_MAC_GENERAL }, { "CKM_IDEA_CBC_PAD", CKM_IDEA_CBC_PAD }, { "CKM_GENERIC_SECRET_KEY_GEN", CKM_GENERIC_SECRET_KEY_GEN }, { "CKM_CONCATENATE_BASE_AND_KEY", CKM_CONCATENATE_BASE_AND_KEY }, { "CKM_CONCATENATE_BASE_AND_DATA", CKM_CONCATENATE_BASE_AND_DATA }, { "CKM_CONCATENATE_DATA_AND_BASE", CKM_CONCATENATE_DATA_AND_BASE }, { "CKM_XOR_BASE_AND_DATA", CKM_XOR_BASE_AND_DATA }, { "CKM_EXTRACT_KEY_FROM_KEY", CKM_EXTRACT_KEY_FROM_KEY }, { "CKM_SSL3_PRE_MASTER_KEY_GEN", CKM_SSL3_PRE_MASTER_KEY_GEN }, { "CKM_SSL3_MASTER_KEY_DERIVE", CKM_SSL3_MASTER_KEY_DERIVE }, { "CKM_SSL3_KEY_AND_MAC_DERIVE", CKM_SSL3_KEY_AND_MAC_DERIVE }, { "CKM_SSL3_MASTER_KEY_DERIVE_DH", CKM_SSL3_MASTER_KEY_DERIVE_DH }, { "CKM_TLS_PRE_MASTER_KEY_GEN", CKM_TLS_PRE_MASTER_KEY_GEN }, { "CKM_TLS_MASTER_KEY_DERIVE", CKM_TLS_MASTER_KEY_DERIVE }, { "CKM_TLS_KEY_AND_MAC_DERIVE", CKM_TLS_KEY_AND_MAC_DERIVE }, { "CKM_TLS_MASTER_KEY_DERIVE_DH", CKM_TLS_MASTER_KEY_DERIVE_DH }, { "CKM_SSL3_MD5_MAC", CKM_SSL3_MD5_MAC }, { "CKM_SSL3_SHA1_MAC", CKM_SSL3_SHA1_MAC }, { "CKM_MD5_KEY_DERIVATION", CKM_MD5_KEY_DERIVATION }, { "CKM_MD2_KEY_DERIVATION", CKM_MD2_KEY_DERIVATION }, { "CKM_SHA1_KEY_DERIVATION", CKM_SHA1_KEY_DERIVATION }, { "CKM_SHA256_KEY_DERIVATION", CKM_SHA256_KEY_DERIVATION }, { "CKM_PBE_MD2_DES_CBC", CKM_PBE_MD2_DES_CBC }, { "CKM_PBE_MD5_DES_CBC", CKM_PBE_MD5_DES_CBC }, { "CKM_PBE_MD5_CAST_CBC", CKM_PBE_MD5_CAST_CBC }, { "CKM_PBE_MD5_CAST3_CBC", CKM_PBE_MD5_CAST3_CBC }, { "CKM_PBE_MD5_CAST5_CBC", CKM_PBE_MD5_CAST5_CBC }, { "CKM_PBE_MD5_CAST128_CBC", CKM_PBE_MD5_CAST128_CBC }, { "CKM_PBE_SHA1_CAST5_CBC", CKM_PBE_SHA1_CAST5_CBC }, { "CKM_PBE_SHA1_CAST128_CBC", CKM_PBE_SHA1_CAST128_CBC }, { "CKM_PBE_SHA1_RC4_128", CKM_PBE_SHA1_RC4_128 }, { "CKM_PBE_SHA1_RC4_40", CKM_PBE_SHA1_RC4_40 }, { "CKM_PBE_SHA1_DES3_EDE_CBC", CKM_PBE_SHA1_DES3_EDE_CBC }, { "CKM_PBE_SHA1_DES2_EDE_CBC", CKM_PBE_SHA1_DES2_EDE_CBC }, { "CKM_PBE_SHA1_RC2_128_CBC", CKM_PBE_SHA1_RC2_128_CBC }, { "CKM_PBE_SHA1_RC2_40_CBC", CKM_PBE_SHA1_RC2_40_CBC }, { "CKM_PKCS5_PBKD2", CKM_PKCS5_PBKD2 }, { "CKM_PBA_SHA1_WITH_SHA1_HMAC", CKM_PBA_SHA1_WITH_SHA1_HMAC }, { "CKM_KEY_WRAP_LYNKS", CKM_KEY_WRAP_LYNKS }, { "CKM_KEY_WRAP_SET_OAEP", CKM_KEY_WRAP_SET_OAEP }, { "CKM_SKIPJACK_KEY_GEN", CKM_SKIPJACK_KEY_GEN }, { "CKM_SKIPJACK_ECB64", CKM_SKIPJACK_ECB64 }, { "CKM_SKIPJACK_CBC64", CKM_SKIPJACK_CBC64 }, { "CKM_SKIPJACK_OFB64", CKM_SKIPJACK_OFB64 }, { "CKM_SKIPJACK_CFB64", CKM_SKIPJACK_CFB64 }, { "CKM_SKIPJACK_CFB32", CKM_SKIPJACK_CFB32 }, { "CKM_SKIPJACK_CFB16", CKM_SKIPJACK_CFB16 }, { "CKM_SKIPJACK_CFB8", CKM_SKIPJACK_CFB8 }, { "CKM_SKIPJACK_WRAP", CKM_SKIPJACK_WRAP }, { "CKM_SKIPJACK_PRIVATE_WRAP", CKM_SKIPJACK_PRIVATE_WRAP }, { "CKM_SKIPJACK_RELAYX", CKM_SKIPJACK_RELAYX }, { "CKM_KEA_KEY_PAIR_GEN", CKM_KEA_KEY_PAIR_GEN }, { "CKM_KEA_KEY_DERIVE", CKM_KEA_KEY_DERIVE }, { "CKM_FORTEZZA_TIMESTAMP", CKM_FORTEZZA_TIMESTAMP }, { "CKM_BATON_KEY_GEN", CKM_BATON_KEY_GEN }, { "CKM_BATON_ECB128", CKM_BATON_ECB128 }, { "CKM_BATON_ECB96", CKM_BATON_ECB96 }, { "CKM_BATON_CBC128", CKM_BATON_CBC128 }, { "CKM_BATON_COUNTER", CKM_BATON_COUNTER }, { "CKM_BATON_SHUFFLE", CKM_BATON_SHUFFLE }, { "CKM_BATON_WRAP", CKM_BATON_WRAP }, { "CKM_ECDSA_KEY_PAIR_GEN", CKM_ECDSA_KEY_PAIR_GEN }, { "CKM_EC_KEY_PAIR_GEN", CKM_EC_KEY_PAIR_GEN }, { "CKM_ECDSA", CKM_ECDSA }, { "CKM_ECDSA_SHA1", CKM_ECDSA_SHA1 }, { "CKM_ECDH1_DERIVE", CKM_ECDH1_DERIVE }, { "CKM_ECDH1_COFACTOR_DERIVE", CKM_ECDH1_COFACTOR_DERIVE }, { "CKM_ECMQV_DERIVE", CKM_ECMQV_DERIVE }, { "CKM_JUNIPER_KEY_GEN", CKM_JUNIPER_KEY_GEN }, { "CKM_JUNIPER_ECB128", CKM_JUNIPER_ECB128 }, { "CKM_JUNIPER_CBC128", CKM_JUNIPER_CBC128 }, { "CKM_JUNIPER_COUNTER", CKM_JUNIPER_COUNTER }, { "CKM_JUNIPER_SHUFFLE", CKM_JUNIPER_SHUFFLE }, { "CKM_JUNIPER_WRAP", CKM_JUNIPER_WRAP }, { "CKM_FASTHASH", CKM_FASTHASH }, { "CKM_AES_KEY_GEN", CKM_AES_KEY_GEN }, { "CKM_AES_ECB", CKM_AES_ECB }, { "CKM_AES_CBC", CKM_AES_CBC }, { "CKM_AES_MAC", CKM_AES_MAC }, { "CKM_AES_MAC_GENERAL", CKM_AES_MAC_GENERAL }, { "CKM_AES_CBC_PAD", CKM_AES_CBC_PAD }, { "CKM_AES_CTR", CKM_AES_CTR}, { "CKM_AES_GCM", CKM_AES_GCM}, { "CKM_AES_OFB", CKM_AES_OFB}, { "CKM_AES_CFB8", CKM_AES_CFB8}, { "CKM_AES_CFB64", CKM_AES_CFB64}, { "CKM_AES_CFB128", CKM_AES_CFB128}, { "CKM_DSA_PARAMETER_GEN", CKM_DSA_PARAMETER_GEN }, { "CKM_DH_PKCS_PARAMETER_GEN", CKM_DH_PKCS_PARAMETER_GEN }, { "CKM_X9_42_DH_PARAMETER_GEN", CKM_X9_42_DH_PARAMETER_GEN }, { "CKM_VENDOR_DEFINED", CKM_VENDOR_DEFINED }, { NULL_PTR, 0xFFFFFFFF } }; #endif opencryptoki+dfsg/usr/sbin/pkcsconf/Makefile.am0000644000175000017500000000062012630407154020703 0ustar xnoxxnoxsbin_PROGRAMS=pkcsconf pkcsconf_LDFLAGS = -lpthread -ldl # Not all versions of automake observe sbinname_CFLAGS pkcsconf_CFLAGS = -D_THREAD_SAFE -DDEBUG -DDEV -DAPI # Not all versions of automake observe sbinname_CFLAGS AM_CFLAGS = -D_THREAD_SAFE -DDEBUG -DDEV -DAPI pkcsconf_SOURCES = ../../lib/pkcs11/common/p11util.c pkcsconf.c INCLUDES = -I../../include/pkcs11 -I. -I../../lib/pkcs11/common opencryptoki+dfsg/usr/sbin/pkcsicsf/0000755000175000017500000000000012630407154016650 5ustar xnoxxnoxopencryptoki+dfsg/usr/sbin/pkcsicsf/pkcsicsf.c0000644000175000017500000003702512630407154020630 0ustar xnoxxnox/* * Licensed materials, Property of IBM Corp. * * OpenCryptoki ICSF token configuration tool. * * (C) COPYRIGHT International Business Machines Corp. 2012 * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "icsf.h" #include "slotmgr.h" #include "pbkdf.h" #include "defs.h" #define CFG_ADD 0x0001 #define CFG_LIST 0x0002 #define CFG_BINDDN 0x0004 #define CFG_CERT 0x0008 #define CFG_PRIVKEY 0x0010 #define CFG_CACERT 0x0020 #define CFG_URI 0x0040 #define CFG_MECH 0x0080 #define CFG_MECH_SASL 0x0100 #define CFG_MECH_SIMPLE 0x0200 #define MAX_RECORDS 10 #define SALT_SIZE 16 #define SASL "sasl" #define SLOT "slot" #define TMPSIZ 64 #define LINESIZ 512 #define TOKBUF 2056 #define STDLL "libpkcs11_icsf.so" LDAP *ld; char *binddn = NULL; char *uri = NULL; char *mech = NULL; char *cert = NULL; char *cacert = NULL; char *privkey = NULL; unsigned long flags = 0; void usage(char *progname) { printf("usage:\t%s [-h] [ -l | -a token-name] [-b BINDDN]" " [-c client-cert-file] [-C CA-cert-file] [-k key] [-u URI]" " [-m MECHANISM]\n", progname); printf("\t-a add specified token\n"); printf("\t-b the distinguish name to bind for simple mode\n"); printf("\t-C the CA certificate file for SASL mode\n"); printf("\t-c the client certificate file for SASL mode\n"); printf("\t-h show this help\n"); printf("\t-k the client private key file for SASL mode\n"); printf("\t-l list available tokens\n"); printf("\t-m the authentication mechanism, " "it can be 'simple' or 'sasl'\n"); printf("\t-u the URI to connect to\n"); exit(-1); } int get_pin(char **pin, size_t *pinlen) { struct termios old, new; int nread; char *buff = NULL; size_t buflen; int rc = 0; /* turn echoing off */ if (tcgetattr(fileno(stdin), &old) != 0) return -1; new = old; new.c_lflag &= ~ECHO; if (tcsetattr (fileno(stdin), TCSAFLUSH, &new) != 0) return -1; /* read the pin * Note: getline will allocate memory for buff. free it when done. */ nread = getline(&buff, &buflen, stdin); if (nread == -1) { rc = -1; goto done; } /* Restore terminal */ (void) tcsetattr(fileno(stdin), TCSAFLUSH, &old); /* start a newline */ printf("\n"); fflush(stdout); /* Allocate PIN. * Note: nread includes carriage return. * Replace with terminating NULL. */ *pin = (unsigned char *)malloc(nread); if (*pin == NULL) { rc = -ENOMEM; goto done; } /* strip the carriage return since not part of pin. */ buff[nread - 1] = '\0'; memcpy(*pin, buff, nread); /* don't include the terminating null in the pinlen */ *pinlen = nread - 1; done: if (buff) free(buff); return rc; } int get_start_slot(void) { FILE *fp; char temp[LINESIZ]; int num; int found = -1; struct stat statbuf; /* if file doesn't exist, then first slot will be 0. */ if ((stat(OCK_CONFIG, &statbuf) < 0) && (errno == ENOENT)) return 0; fp = fopen(OCK_CONFIG, "r"); if (fp == NULL) { fprintf(stderr, "open failed, line %d: %s\n", __LINE__, strerror(errno)); return(-1); } /* step thru config file and get biggest slot number used */ while (fgets(temp, LINESIZ, fp) != NULL) { if (strstr(temp, SLOT) != NULL) { if (sscanf(temp, "%*s %d", &num) == 1) if (num > found) found = num; } } /* bump up the slot number, since this will be next new slot entry. * if it was an empty file or a file with no slot entries, * then next new slot entry will be 0. */ fclose(fp); return (++found); } int remove_file(char *filename) { struct stat statbuf; /* if file exists, then remove it */ if ((stat(filename, &statbuf) < 0) && (errno == ENOENT)) { if (unlink(filename) == -1) { fprintf(stderr, "unlink failed for %s, line %d: %s\n", filename, __LINE__, strerror(errno)); return(-1); } } return 0; } static void add_token_config_entry(FILE *fp, const char *key, const char *value) { if (!key || !value) return; fprintf(fp, "%s = \"%s\"\n", key, value); } int add_token_config(const char *configname, struct icsf_token_record token, int slot) { FILE *tfp; int rc = 0; /* create the token config file */ tfp = fopen(configname, "w"); if (tfp == NULL) { fprintf(stderr, "fopen failed, line %d: %s\n", __LINE__, strerror(errno)); return (-1); } /* add the info */ fprintf(tfp, "slot %d {\n", slot); add_token_config_entry(tfp, "TOKEN_NAME", token.name); add_token_config_entry(tfp, "TOKEN_MANUFACTURE", token.manufacturer); add_token_config_entry(tfp, "TOKEN_MODEL", token.model); add_token_config_entry(tfp, "TOKEN_SERIAL", token.serial); add_token_config_entry(tfp, "MECH", (flags & CFG_MECH_SIMPLE) ? "SIMPLE" : "SASL" ); /* add BIND info */ if (memcmp(mech, "simple", strlen("simple")) == 0) { add_token_config_entry(tfp, "BINDDN", binddn); add_token_config_entry(tfp, "URI", uri); } else { add_token_config_entry(tfp, "URI", uri); add_token_config_entry(tfp, "CERT", cert); add_token_config_entry(tfp, "CACERT", cacert); add_token_config_entry(tfp, "KEY", privkey); } fprintf(tfp, "}\n"); fflush(tfp); if (ferror(tfp) != 0) { fprintf(stderr, "failed to add token named, %s\n", token.name); rc = -1; } fclose(tfp); return(rc); } int config_add_slotinfo(int num_of_slots, struct icsf_token_record *tokens) { struct stat statbuf; FILE *fp; int start_slot = -1; char configname[LINESIZ]; int i, rc; /* get the starting slot for next entry */ start_slot = get_start_slot(); if (start_slot == -1) return (-1); /* open the config file. if it doesn't exist, create it */ if ((stat(OCK_CONFIG, &statbuf) == -1) && (errno == ENOENT)) /* doesn't exist, create it */ fp = fopen(OCK_CONFIG, "w"); else fp = fopen(OCK_CONFIG, "a"); if (fp == NULL) { fprintf(stderr, "open failed, line %d: %s\n", __LINE__, strerror(errno)); return (-1); } /* For each token in the list do, * - Create a slot entry in ock config file that contains * the stdll and token config name. * - Create a token config file that contains the token info * from the ICSF and the BIND authentication info. */ for (i = 0; i < num_of_slots; i++) { /* create the config name using the token's name */ memset(configname, 0, sizeof(configname)); snprintf(configname, sizeof(configname), "%s/%s.conf", OCK_CONFDIR, tokens[i].name); /* write the token info to the token's config file */ rc = add_token_config(configname, tokens[i], start_slot); if (rc == -1) { fprintf(stderr, "failed to add %s token.\n", tokens[i].name); /* skip adding this entry */ continue; } /* add the slot entry to the ock config file */ fprintf(fp, "\nslot %d {\n", start_slot); fprintf(fp, "stdll = %s\n", STDLL); fprintf(fp, "confname = %s\n", configname); fprintf(fp, "}\n"); fflush(fp); if (ferror(fp) != 0) { fprintf(stderr, "Failed to add an entry for %s token: " "%s\n", tokens[i].name, strerror(errno)); remove_file(configname); continue; } /* bump the slot number */ start_slot++; } fclose(fp); return (0); } int list_tokens(void) { size_t tokenCount = MAX_RECORDS; struct icsf_token_record *previous = NULL; struct icsf_token_record tokens[MAX_RECORDS]; int rc, i, num_seen = 0; do { /* get the token list from remote z/OS host */ rc = icsf_list_tokens(ld, NULL, previous, tokens, &tokenCount); if (ICSF_RC_IS_ERROR(rc)) return -1; for (i = 0; i < tokenCount; i++) { printf("Token #: %d\n" "Token name: %s\n" "Manufacturer: %s\n" "Model: %s\n" "Serial: %s\n" "Read-only: %s\n\n", num_seen, tokens[i].name, tokens[i].manufacturer, tokens[i].model, tokens[i].serial, tokens[i].flags ? "yes" : "no"); num_seen++; } if (tokenCount) previous = &tokens[tokenCount - 1]; } while (tokenCount); return 0; } int lookup_name(char *name, struct icsf_token_record *found) { size_t tokenCount = MAX_RECORDS; struct icsf_token_record *previous = NULL; struct icsf_token_record tokens[MAX_RECORDS]; int rc, i; do { /* get the token list from remote z/OS host */ rc = icsf_list_tokens(ld, NULL, previous, tokens, &tokenCount); if (ICSF_RC_IS_ERROR(rc)) { fprintf(stderr, "Could not get list of tokens.\n"); found = NULL; return -1; } for (i = 0; i < tokenCount; i++) { if (strncasecmp(name, tokens[i].name, sizeof(tokens[i].name)) == 0) { memcpy(found, &tokens[i], sizeof(struct icsf_token_record)); return 0; } } if (tokenCount) previous = &tokens[tokenCount - 1]; } while (tokenCount); /* if we get here, we could not find the token in the list. */ found = NULL; return -1; } void remove_racf_file(void) { unsigned char fname[PATH_MAX]; /* remove the so and user files */ snprintf(fname, sizeof(fname), "%s/RACF", ICSF_CONFIG_PATH); remove_file(fname); } int retrieve_all(void) { size_t tokenCount; struct icsf_token_record *previous = NULL; struct icsf_token_record tokens[MAX_RECORDS]; int rc; /* since pkcsslotd can only manage * NUMBER_SLOTS_MANAGED at a time, use this as * the maxiumum amount of tokens to retrieve... */ tokenCount = NUMBER_SLOTS_MANAGED; rc = icsf_list_tokens(ld, NULL, previous, tokens, &tokenCount); if (ICSF_RC_IS_ERROR(rc)) { fprintf(stderr, "Could not get list of tokens.\n"); return -1; } /* add slot and token entry(ies) */ rc = config_add_slotinfo(tokenCount, tokens); if (rc) { fprintf(stderr, "Could not add list of tokens.\n"); return -1; } return 0; } int secure_racf_passwd(char *racfpwd, unsigned int len) { char *sopin = NULL; char masterkey[AES_KEY_SIZE_256]; char fname[PATH_MAX]; int rc; size_t sopinlen; /* get the SO PIN */ printf("Enter the SO PIN: "); fflush(stdout); rc = get_pin(&sopin, &sopinlen); if (rc != 0) { fprintf(stderr, "Could not get SO PIN.\n"); rc = -1; goto cleanup; } /* generate a masterkey */ if ((get_randombytes(masterkey, AES_KEY_SIZE_256)) != CKR_OK) { fprintf(stderr, "Could not generate masterkey.\n"); rc = -1; goto cleanup; } /* use the master key to secure the racf passwd */ rc = secure_racf(racfpwd, len, masterkey, AES_KEY_SIZE_256); if (rc != 0) { fprintf(stderr, "Failed to secure racf passwd.\n"); rc = -1; goto cleanup; } /* now secure the master key with a derived key */ /* first get the filename to put the encrypted masterkey */ snprintf(fname, sizeof(fname), "%s/MK_SO", ICSF_CONFIG_PATH); rc = secure_masterkey(masterkey, AES_KEY_SIZE_256, sopin, strlen(sopin), fname); if (rc != 0) { fprintf(stderr, "Failed to secure masterkey.\n"); /* remove the racf file */ remove_racf_file(); rc = -1; goto cleanup; } cleanup: if (sopin) free(sopin); return rc; } int main(int argc, char **argv) { char *racfpwd = NULL; size_t racflen; char *tokenname = NULL; int c; int rc = 0; struct icsf_token_record found_token; while ((c = getopt(argc, argv, "hla:b:u:m:k:c:C:")) != (-1)) { switch (c) { case 'a': flags |= CFG_ADD; if ((tokenname = strdup(optarg)) == NULL) { rc = -1; fprintf(stderr, "strdup failed: line %d\n", __LINE__); goto cleanup; } break; case 'l': flags |= CFG_LIST; break; case 'b': flags |= CFG_BINDDN; if ((binddn = strdup(optarg)) == NULL) { rc = -1; fprintf(stderr, "strdup failed: line %d\n", __LINE__); goto cleanup; } break; case 'c': flags |= CFG_CERT; if ((cert = strdup(optarg)) == NULL) { rc = -1; fprintf(stderr, "strdup failed: line %d\n", __LINE__); goto cleanup; } break; case 'k': flags |= CFG_PRIVKEY; if ((privkey = strdup(optarg)) == NULL) { rc = -1; fprintf(stderr, "strdup failed: line %d\n", __LINE__); goto cleanup; } break; case 'C': flags |= CFG_CACERT; if ((cacert = strdup(optarg)) == NULL) { rc = -1; fprintf(stderr, "strdup failed: line %d\n", __LINE__); goto cleanup; } break; case 'u': flags |= CFG_URI; if ((uri = strdup(optarg)) == NULL) { rc = -1; fprintf(stderr, "strdup failed: line %d\n", __LINE__); goto cleanup; } break; case 'm': flags |= CFG_MECH; if ((mech = strdup(optarg)) == NULL) { rc = -1; fprintf(stderr, "strdup failed: line %d\n", __LINE__); goto cleanup; } if (memcmp(mech, SASL, sizeof(SASL)) == 0) flags |= CFG_MECH_SASL; else flags |= CFG_MECH_SIMPLE; break; case 'h': default: usage(argv[0]); break; } } /* Noticed that if a user misses an argument after an option, * sometimes getopt misses it. * For example, pkcsiscf -a -m -b xxxx -u xxxx" * To catch these anomalies, check that optind == argc. */ if (optind != argc) usage(argv[0]); /* If there were no options, print usage. */ if ((!flags) || (!(flags & CFG_ADD) && !(flags & CFG_LIST ))) usage(argv[0]); /* Currently, do not allow user to add a list of tokens. * When ready to support multiple icsf tokens, this * check can be removed. */ if ((flags & CFG_ADD) && !(memcmp(tokenname, "all", strlen(tokenname)))) usage(argv[0]); /* If add, then must specify a mechanism and a name*/ if ((flags & CFG_ADD ) && (!(flags & CFG_MECH) || tokenname == NULL)) usage(argv[0]); /* If list, then must specify a mechanism */ if ((flags & CFG_LIST ) && !(flags & CFG_MECH)) usage(argv[0]); /* Cannot add and list at the same time */ if ((flags & CFG_LIST ) && (flags & CFG_ADD)) usage(argv[0]); /* May only specify one mechanism */ if ((flags & CFG_MECH_SASL) && (flags & CFG_MECH_SIMPLE)) usage(argv[0]); /* Cannot specify bind DN with SASL */ if ((flags & CFG_MECH_SASL) && (flags & CFG_BINDDN)) usage(argv[0]); /* Cannot specify certs or key with SIMPLE */ if ((flags & CFG_MECH_SIMPLE) && (flags & (CFG_CERT | CFG_PRIVKEY | CFG_CACERT))) usage(argv[0]); /* get racf password if needed */ if ((flags & CFG_ADD) || (flags & CFG_LIST)) { if (flags & CFG_MECH_SIMPLE) { printf("Enter the RACF passwd: "); fflush(stdout); rc = get_pin(&racfpwd, &racflen); if (rc != 0) { fprintf(stderr, "Could not get RACF passwd.\n"); return (-1); } /* bind to ldap server */ rc = icsf_login(&ld, uri, binddn, racfpwd); } else { rc = icsf_sasl_login(&ld, uri, NULL, NULL, NULL, NULL); } if (rc) { fprintf(stderr, "Failed to bind to the ldap server.\n"); goto cleanup; } } /* Add token(s) */ if (flags & CFG_ADD) { if (memcmp(tokenname, "all", strlen(tokenname)) == 0) { rc = retrieve_all(); if (rc) { fprintf(stderr, "Could not add the list of " "tokens.\n"); goto cleanup; } } else { /* add only the specified tokenname. * first, find it in the list. */ rc = lookup_name(tokenname, &found_token); if (rc != 0) { fprintf(stderr, "Could not find %s in token list.\n", tokenname); rc = -1; goto cleanup; } /* add the entry */ rc = config_add_slotinfo(1, &found_token); if (rc != 0) goto cleanup; } if (flags & CFG_MECH_SIMPLE) { /* when using simple auth, secure racf passwd. */ rc = secure_racf_passwd(racfpwd, strlen(racfpwd)); if (rc != 0) goto cleanup; } } if (flags & CFG_LIST) { /* print the list of available tokens */ rc = list_tokens(); if (rc != 0) fprintf(stderr, "Could not get full list of tokens.\n"); } cleanup: if (ld) icsf_logout(ld); if (tokenname) free(tokenname); if (binddn) free(binddn); if (cert) free(cert); if (privkey) free(privkey); if (cacert) free(cacert); if (uri) free(uri); if (mech) free(mech); if (racfpwd) free(racfpwd); return rc; } opencryptoki+dfsg/usr/sbin/pkcsicsf/Makefile.am0000644000175000017500000000106212630407154020703 0ustar xnoxxnoxsbin_PROGRAMS=pkcsicsf pkcsicsf_LDFLAGS = -lldap -lssl -llber -lcrypto # Not all versions of automake observe sbinname_CFLAGS pkcsicsf_CFLAGS = -D_THREAD_SAFE -DDEV -DAPI -DSTDLL_NAME=\"icsf\" # Not all versions of automake observe sbinname_CFLAGS AM_CFLAGS = -D_THREAD_SAFE -DDEV -DAPI -DSTDLL_NAME=\"icsf\" pkcsicsf_SOURCES = ../../lib/pkcs11/icsf_stdll/icsf.c \ ../../lib/pkcs11/icsf_stdll/pbkdf.c \ ../../lib/pkcs11/common/trace.c \ pkcsicsf.c INCLUDES = -I../../include/pkcs11 -I. -I../../lib/pkcs11/common -I../../lib/pkcs11/icsf_stdll opencryptoki+dfsg/usr/sbin/Makefile.am0000644000175000017500000000037612630407154017105 0ustar xnoxxnox if ENABLE_ICSFTOK PKCSICSF_DIR = pkcsicsf endif if ENABLE_PKCSEP11_MIGRATE PKCSEP11_MIGRATE_DIR = pkcsep11_migrate endif if ENABLE_CCATOK PKCSCCA_DIR = pkcscca endif SUBDIRS = pkcsslotd pkcsconf $(PKCSICSF_DIR) $(PKCSEP11_MIGRATE_DIR) $(PKCSCCA_DIR) opencryptoki+dfsg/usr/sbin/pkcsslotd/0000755000175000017500000000000012630407154017051 5ustar xnoxxnoxopencryptoki+dfsg/usr/sbin/pkcsslotd/pkcsslotd.h0000755000175000017500000004232312630407154021237 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/sbin/pkcsslotd/pkcsslotd.h,v 1.3 2006/04/05 20:07:48 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ /*********************************************************************** * * Slot Manager Daemon header file * ***********************************************************************/ #ifndef _PKCSSLOTMGR_H #define _PKCSSLOTMGR_H 1 /*********** * Defines * ***********/ #ifdef DEV #ifndef BECOME_DAEMON #define BECOME_DAEMON FALSE #endif /* BECOME_DAEMON */ #ifndef DEFAULT_LOG_FILE #define DEFAULT_LOG_FILE (TOK_PATH ".log") #endif /* DEFAULT_LOG_FILE */ #ifndef DEFAULT_DEBUG_LEVEL #define DEFAULT_DEBUG_LEVEL DEBUG_LEVEL0 #endif /* DEFAULT_DEBUG_LEVEL */ #else /* DEV not defined */ #define BECOME_DAEMON TRUE #define DEFAULT_DEBUG_LEVEL DEBUG_NONE #endif /* DEV */ /******************** * Global Variables * ********************/ extern Slot_Mgr_Shr_t *shmp; // pointer to the shared memory region. extern int shmid; extern key_t tok; extern Slot_Info_t_64 sinfo[NUMBER_SLOTS_MANAGED]; extern unsigned char NumberSlotsInDB; extern int socketfd; extern Slot_Mgr_Socket_t socketData; /*********************** * Function Prototypes * ***********************/ BOOL IsDaemon(void); BOOL GetStartDirectory(char *Buffer, u_int32 BufSize); BOOL SaveStartupDirectory(char *Arg0); BOOL StopGCThread(void *Ptr); BOOL StartGCThread(Slot_Mgr_Shr_t *MemPtr); BOOL CheckForGarbage(Slot_Mgr_Shr_t *MemPtr); int InitializeMutexes(void); int DestroyMutexes(void); int CreateSharedMemory(void); int AttachToSharedMemory(void); int InitSharedMemory(Slot_Mgr_Shr_t *sp); void DetachFromSharedMemory(void); void DestroySharedMemory(void); int SetupSignalHandlers(void); void slotdGenericSignalHandler(int Signal); void PopulateCKInfo(CK_INFO_PTR_64 ckinf); void PopulateSlotInfo(Slot_Info_t_64 *slot_info, int *processed); int XProcLock(void); int XProcUnLock(void); int CreateXProcLock(void); int CreateListenerSocket(void); int InitSocketData(Slot_Mgr_Socket_t *sp); int SocketConnectionHandler(int socketfd, int timeout_secs); void DetachSocketListener(int socketfd); int load_and_parse(const char *configfile); #endif /* _SLOTMGR_H */ opencryptoki+dfsg/usr/sbin/pkcsslotd/parser.y0000644000175000017500000004633312630407154020550 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2013 */ %{ /* * Parse openCryptoki's config file. */ #include #include #include #include #include "log.h" #include "slotmgr.h" #include "pkcsslotd.h" Slot_Info_t_64 sinfo_struct; unsigned long int Index; int slot_count = 0; #define ERRSTRLEN 256 #define DEF_MANUFID "IBM" #define DEF_SLOTDESC "Linux" static char errbuf[ERRSTRLEN + 1]; extern char *strsep(char **stringp, const char *delim); extern FILE *yyin; extern int yyparse(); extern void yyerror(const char *s); extern int line_num; typedef enum { KW_STDLL, KW_SLOTDESC, KW_MANUFID, KW_HWVERSION, KW_FWVERSION, KW_CONFNAME, KW_MAX } keyword_token; struct ock_key { char *name; keyword_token token; }; static const struct ock_key ock_keywords[] = { {"stdll", KW_STDLL}, {"description", KW_SLOTDESC}, {"manufacturer", KW_MANUFID}, {"hwversion", KW_HWVERSION}, {"firmwareversion", KW_FWVERSION}, {"confname", KW_CONFNAME} }; void set_init(void); void set_defaults(void); %} %union { char *str; unsigned int num; } %token EQUAL SLOT EOL OCKVERSION BEGIN_DEF END_DEF %token STRING %token KEYWORD %token INTEGER %% config_file: config_file sections | ; sections: OCKVERSION STRING EOL { free($2); } | SLOT INTEGER BEGIN_DEF EOL { /* inititalize sinfo_struct */ set_init(); sinfo_struct.slot_number = $2; Index = $2; } keyword_defs END_DEF { /* set some defaults if needed before copying */ set_defaults(); memcpy(&sinfo[Index], &sinfo_struct, sizeof(sinfo_struct)); slot_count++; } | EOL ; keyword_defs: STRING EQUAL STRING EOL keyword_defs { int kw; kw = lookup_keyword($1); switch (kw) { case KW_STDLL: sinfo_struct.present = TRUE; sinfo_struct.pk_slot.flags |= (CKF_TOKEN_PRESENT); memset(sinfo_struct.dll_location, 0, sizeof(sinfo_struct.dll_location)); memcpy(sinfo_struct.dll_location, $3, strlen($3)); break; case KW_SLOTDESC: do_str(sinfo_struct.pk_slot.slotDescription, sizeof(sinfo_struct.pk_slot.slotDescription), $1, $3); break; case KW_MANUFID: do_str(sinfo_struct.pk_slot.manufacturerID, sizeof(sinfo_struct.pk_slot.manufacturerID), $1, $3); break; case KW_HWVERSION: do_vers(&sinfo_struct.pk_slot.hardwareVersion, $1, $3); break; case KW_FWVERSION: do_vers(&sinfo_struct.pk_slot.firmwareVersion, $1, $3); break; case KW_CONFNAME: memset(sinfo_struct.confname, 0, sizeof(sinfo_struct.confname)); memcpy(sinfo_struct.confname, $3, strlen($3)); break; default: yyerror("unknown config keyword"); break; } free ($3); } | ; %% void yyerror(const char *s) { fprintf(stderr, "parse error on line %d: %s\n", line_num, s); } void set_init(void) { memset(&sinfo_struct, 0, sizeof(sinfo_struct)); } void set_defaults(void) { /* set some defaults if user hasn't set these. */ if (!sinfo_struct.pk_slot.slotDescription[0]) memcpy(&sinfo_struct.pk_slot.slotDescription[0], DEF_SLOTDESC, strlen(DEF_SLOTDESC)); if (!sinfo_struct.pk_slot.manufacturerID[0]) memcpy(&sinfo_struct.pk_slot.manufacturerID[0], DEF_MANUFID, strlen(DEF_MANUFID)); } int do_str(char *slotinfo, int size, char* kw, char *val) { if (strlen(val) > size) { snprintf(errbuf, ERRSTRLEN, "%s has too many characters\n", kw); yyerror(errbuf); return -1 ; } memcpy(slotinfo, val, strlen(val)); return 0; } int do_vers(CK_VERSION *slotinfo, char *kw, char *val) { char **ap, *argp[2]; char *valp; if (!val) { snprintf(errbuf, ERRSTRLEN, "%s has no value\n", kw); yyerror(errbuf); return -1 ; } valp = val; for (ap = argp; (*ap = strsep(&valp, ".")) != NULL;) if (**ap != '\0') if (++ap >= &argp[2]) break; slotinfo->major = (char) atoi(argp[0]); if(!argp[1]) slotinfo->minor = 0; else slotinfo->minor = (char) atoi(argp[1]); return 0; } int lookup_keyword(const char *key) { int i; for (i = 0; i < KW_MAX ; i++ ) { if (strncmp(key, ock_keywords[i].name, strlen(key)) == 0) return ock_keywords[i].token; } /* if we get here that means did not find a match... */ return -1; } int load_and_parse(const char *configfile) { FILE *conf; extern FILE *yyin; conf = fopen(configfile, "r"); if (!conf) { fprintf(stderr, "Failed to open %s: %s\n", configfile, strerror(errno)); return -1; } yyin = conf; do { yyparse(); } while (!feof(yyin)); fclose(conf); NumberSlotsInDB = slot_count; return 0; } opencryptoki+dfsg/usr/sbin/pkcsslotd/shmem.c0000755000175000017500000005572612630407154020350 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include #include #include #include "slotmgr.h" #include "log.h" #include "pkcsslotd.h" #define MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) #define MAPFILENAME CONFIG_PATH "/.apimap" pthread_mutexattr_t mtxattr; // Mutex attribute for the shared memory Mutex /*********************************************************************** * CreateSharedMemory - * * Creates and initializes a shared memory file. This function will fail if the * memory is already allocated since we're the owner of it. * ***********************************************************************/ int CreateSharedMemory ( void ) { struct stat statbuf; char *Path = NULL; struct group *grp; struct shmid_ds shm_info; #if !MMAP if ( ((Path = getenv("PKCS11_SHMEM_FILE")) == NULL ) || ( Path[0] == '\0' ) ) { Path = TOK_PATH; } InfoLog( "Shared memory file is %s", Path); // Get shared memory key token all users of the shared memory // need to get the same token if ( stat(Path, &statbuf) < 0 ) { ErrLog("Shared Memory Key Token creation file does not exist"); return FALSE; } // SAB Get the group information for the PKCS#11 group... fail if // it does not exist grp = getgrnam("pkcs11"); if ( !grp ) { ErrLog("Group PKCS#11 does not exist "); return FALSE; // Group does not exist... setup is wrong.. } tok = ftok(Path ,'b'); // Allocate the shared memory... Fail if the memory is already // allocated since the slot mgr is the owner of it. // Is this some attempt at exclusivity, or is that just a side effect? - SCM 9/1 shmid = shmget( tok, sizeof( Slot_Mgr_Shr_t ), IPC_CREAT | IPC_EXCL | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP ); // Explanation of options to shmget(): /* * IPC_CREAT Creates the data structure if it does not already exist. * IPC_EXCL Causes the shmget subroutine to be unsuccessful if the * IPC_CREAT flag is also set, and the data structure already exists. * S_IRUSR Permits the process that owns the data structure to read it. * S_IWUSR Permits the process that owns the data structure to modify it. * S_IRGRP Permits the group associated with the data structure to read it. * S_IWGRP Permits the group associated with the data structure to modify it. * * * WE DON"T WANT OTHERS * S_IROTH Permits others to read the data structure. * S_IWOTH Permits others to modify the data structure. */ if ( shmid < 0 ) { ErrLog("Shared memory creation failed (0x%X)\n", errno); ErrLog("Reclaiming 0x%X\n", tok); shmid = shmget( tok, sizeof( Slot_Mgr_Shr_t ), 0 ); DestroySharedMemory(); shmid = shmget( tok, sizeof( Slot_Mgr_Shr_t ), IPC_CREAT | IPC_EXCL | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP ); if ( shmid < 0 ) { ErrLog("Shared memory reclamation failed (0x%X)\n", errno); ErrLog("perform ipcrm -M 0x%X\n", tok); return FALSE; } } // SAB Set the group ownership of the shared mem segment.. // we already have the group structure.. if ( shmctl(shmid, IPC_STAT,&shm_info) == 0 ) { shm_info.shm_perm.gid = grp->gr_gid; if (shmctl(shmid,IPC_SET,&shm_info) == -1) { ErrLog("Failed to set group ownership for shm \n"); shmctl(shmid, IPC_RMID,NULL); } } else { ErrLog("Can't get status of shared memory %d\n",errno); // we know it was created... we need to destroy it... shmctl(shmid, IPC_RMID,NULL); } return TRUE; #else { #warning "EXPERIMENTAL" int fd; int i; char *buffer; grp = getgrnam("pkcs11"); if ( !grp ) { ErrLog("Group \"pkcs11\" does not exist! Please run %s/pkcs11_startup.", SBIN_PATH); return FALSE; // Group does not exist... setup is wrong.. } fd = open(MAPFILENAME,O_RDWR,MODE); if (fd < 0 ) { // File does not exist... this is cool, we creat it here fd = open(MAPFILENAME,O_RDWR|O_CREAT,MODE); // Create the file if (fd < 0 ){ // We are really hosed here, since we should be able // to create the file now ErrLog("%s: open(%s): %s", __FUNCTION__, MAPFILENAME, strerror(errno)); return FALSE; } else { if (fchmod(fd, MODE) == -1) { ErrLog("%s: fchmod(%s): %s", __FUNCTION__, MAPFILENAME, strerror(errno)); close(fd); return FALSE; } if (fchown(fd, 0, grp->gr_gid) == -1) { ErrLog("%s: fchown(%s, root, pkcs11): %s", __FUNCTION__, MAPFILENAME, strerror(errno)); close(fd); return FALSE; } // Create a buffer and make the file the right length i = sizeof(Slot_Mgr_Shr_t); buffer = malloc(sizeof(Slot_Mgr_Shr_t)); memset(buffer,'\0',i); write(fd,buffer,i); free(buffer); close(fd); } } else { ErrLog("%s: [%s] exists; you may already have a pkcsslot daemon running. If this " "is not the case, then the prior daemon was not shut down cleanly. " "Please delete this file and try again\n", __FUNCTION__, MAPFILENAME); close(fd); return FALSE; } return TRUE; } #endif } /*********************************************************************** * * AttachToSharedMemory - * * Called after creating the shared memory file * Basically allows us to have access to the memory we've just created * ***********************************************************************/ int AttachToSharedMemory ( void ) { #if !MMAP shmp = NULL; shmp = (Slot_Mgr_Shr_t *) shmat( shmid, NULL, 0 ); if ( !shmp ) { ErrLog("Shared memory attach failed (0x%X)\n", errno); return FALSE; } /* Initizalize the memory to 0 */ memset ( shmp, '\0', sizeof(*shmp) ); return TRUE; #else { #warning "EXPERIMENTAL" int fd; int i; char *buffer; fd = open(MAPFILENAME,O_RDWR,MODE); if (fd < 0 ){ return FALSE; //Failed } shmp = (Slot_Mgr_Shr_t *)mmap(NULL,sizeof(Slot_Mgr_Shr_t),PROT_READ|PROT_WRITE, MAP_SHARED,fd,0); close(fd); if ( ! shmp ) { return FALSE; } return TRUE; } #endif } /*********************************************************************** * * DetachFromSharedMemory - * * Un-does AttachToSharedMemory() :) * ***********************************************************************/ void DetachFromSharedMemory ( void ) { #if !MMAP if ( shmp == NULL ) return; if ( shmdt(shmp) != 0 ) { ErrLog("Attempted to detach from an invalid shared memory pointer"); } shmp = NULL; return; #else if ( shmp == NULL ) return; munmap((void *)shmp,sizeof(*shmp)); unlink(MAPFILENAME); #endif } /*********************************************************************** * * DestroySharedMemory - * * Closes (destroys) the shared memory file we created with CreateSharedMemory() * * We should make sure that everyone else has detached before we do this * if we manage to exit before this gets called, you have to call ipcrm * to clean things up... * ***********************************************************************/ void DestroySharedMemory ( void ) { if (shmctl (shmid, IPC_RMID, 0) != 0) { perror ("error in closing shared memory segment"); } return; } /*********************************************************************** * * InitSharedMemory - * * Set up our newly allocated shared memory segment * * ***********************************************************************/ int InitSharedMemory ( Slot_Mgr_Shr_t *sp ) { uint16 procindex; memset(sp->slot_global_sessions, 0, NUMBER_SLOTS_MANAGED * sizeof(uint32)); /* Initialize the process side of things. */ /* for now don't worry about the condition variables */ for ( procindex=0; procindex < NUMBER_PROCESSES_ALLOWED; procindex++ ) { /* Initialize the mutex variables. */ sp->proc_table[procindex].inuse = FALSE; } return TRUE; } opencryptoki+dfsg/usr/sbin/pkcsslotd/log.h0000755000175000017500000004425112630407154020014 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/sbin/pkcsslotd/log.h,v 1.2 2005/02/22 20:49:30 mhalcrow Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _LOG_H #define _LOG_H 1 #ifndef FALSE #define FALSE 0 #endif /* FALSE */ #ifndef TRUE #define TRUE (!(FALSE)) #endif /* TRUE */ #ifndef MAX_LOGGING_FACILITIES #define MAX_LOGGING_FACILITIES 16 #endif /* MAX_LOGGING_FACILITIES */ #ifndef TRUNCATE_LOGS_ON_START #define TRUNCATE_LOGS_ON_START 0 #endif /* TRUNCATE_LOGS_ON_START */ /* Use an enum here? */ #define DEBUG_NONE (0) #define DEBUG_LEVEL0 (100) /* Less detail */ #define DEBUG_LEVEL1 (DEBUG_LEVEL0 + 100) /* . */ #define DEBUG_LEVEL2 (DEBUG_LEVEL1 + 100) /* v */ #define DEBUG_LEVEL3 (DEBUG_LEVEL2 + 100) /* More detail */ #define DEBUG_LEVEL4 (DEBUG_LEVEL3 + 100) #define DEBUG_LEVEL5 (DEBUG_LEVEL4 + 100) #define DNONE (DEBUG_NONE) #define DL0 (DEBUG_LEVEL0) #define DL1 (DEBUG_LEVEL1) #define DL2 (DEBUG_LEVEL2) #define DL3 (DEBUG_LEVEL3) #define DL4 (DEBUG_LEVEL4) #define DL5 (DEBUG_LEVEL5) #ifndef DbgPrint #define DbgPrint DbgLog #endif /* DbgPrint */ /************** * Structures * **************/ /************************************************************************ * Yes, the structures are somewhat redundant; this is an evolutionary * side-effect. They should probably be combined into a single struct * - SCM ************************************************************************/ typedef unsigned int u_int32; typedef u_int32 LogHandle, *pLogHandle; typedef u_int32 BOOL, bool, BOOLEAN, boolean; typedef struct _logging_facility_info { BOOL Initialized; char Descrip[255]; u_int32 LogOption; char *Filename; BOOL UseSyslog; u_int32 LogLevel; pid_t pid; } LoggingFacilityInfo, *pLoggingFacilityInfo; typedef struct _LoggingFacility { char *Label; pLogHandle phLog; char *Filename; BOOL UseSyslog; u_int32 LogLevel; } LoggingFacility, *pLoggingFacility; /******************************** * Exported Function Prototypes * ********************************/ void DbgLog ( u_int32 DebugLevel, char *Format, ... ); void ErrLog ( char *Format, ... ); void LogLog ( char *Format, ... ); void WarnLog ( char *Format, ... ); void TraceLog ( char *Format, ... ); void InfoLog ( char *Format, ... ); BOOL PKCS_Log ( LogHandle *phLog, char *Format, va_list ap ); BOOL NewLoggingFacility ( char *ID, pLoggingFacility pStuff ); BOOL CloseLoggingFacility ( LogHandle hLog ); BOOL GetCurrentTimeString ( char *Buffer ); u_int32 SetDebugLevel ( u_int32 Val ); u_int32 GetDebugLevel ( void ); #endif /* _LOG_H */ opencryptoki+dfsg/usr/sbin/pkcsslotd/garbage_linux.c0000755000175000017500000007207312630407154022040 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include #include #include #include "log.h" #include "slotmgr.h" #include "pkcsslotd.h" #include "err.h" #define PROC_BASE "/proc" extern BOOL GCBlockSignals (void); #if !defined(NOGARBAGE) #include "garbage_linux.h" BOOL IsValidProcessEntry ( pid_t_64 pid, time_t_64 RegTime ); int Stat2Proc ( int pid, proc_t *p ); pthread_t GCThread; /* Garbage Collection thread's handle */ static BOOL ThreadRunning = FALSE; /* If we're already running or not */ #if THREADED static void *GCMain ( void *Ptr ); static void GCCancel ( void *Ptr ); #else void *GCMain ( void *Ptr ); void GCCancel ( void *Ptr ); #endif /********************************************************************************* * StartGCThread - * * Entry point that starts the garbage collection thread * *********************************************************************************/ BOOL StartGCThread ( Slot_Mgr_Shr_t *MemPtr ) { int err; #if !(THREADED) return TRUE; #endif if ( ThreadRunning ) { DbgLog (DL0, "StartGCThread: Thread already running."); return FALSE; } if ( ( err = pthread_create( &GCThread, NULL, GCMain, ((void *)MemPtr) ) ) != 0 ) { DbgLog(DL0,"StartGCThread: pthread_create returned %s (%d; %#x)", SysConst(err), err, err ); return FALSE; } ThreadRunning = TRUE; #ifdef DEV // Only development builds LogLog ( "StartGCThread: garbage collection thread started as ID %d (%#x) by ID %d (%#x)", GCThread, GCThread, pthread_self(), pthread_self() ); #endif return TRUE; } /********************************************************************************* * StopGCThread - * * Entry point which causes the Garbage collection thread to terminate * Waits for the thread to terminate before continuing * *********************************************************************************/ BOOL StopGCThread ( void *Ptr ) { int err; void *Status; #if !(THREADED) return TRUE; #endif if ( ! ThreadRunning ) { DbgLog(DL0,"StopGCThread was called when the garbage collection thread was not running"); return FALSE; } DbgLog(DL0, "StopGCThread: tid %d is stopping the garbage collection thread (tid %d)", pthread_self(), GCThread); /* Cause the GC thread to be cancelled */ if ( ( err = pthread_cancel(GCThread)) != 0 ) { DbgLog(DL0,"StopGCThread: pthread_cancel returned %s (%d; %#x)", SysConst(err), err, err ); return FALSE; } /* Synchronize with the GC thread (aka: wait for it to terminate) */ if ( (err = pthread_join ( GCThread, &Status ) ) != 0 ) { DbgLog(DL0,"StopGCThread: pthread_join returned %s (%d; %#x)", SysConst(err), err, err ); return FALSE; } if ( Status != PTHREAD_CANCELED ) { DbgLog(DL0,"Hmm. Thread was cancelled, but didn't return the appropriate return status"); } ThreadRunning = FALSE; return TRUE; } /********************************************************************************* * GCMain - * * The Garbage collection thread's main() * Basically, run until cancelled by another thread * *********************************************************************************/ void *GCMain ( void *Ptr) { #if THREADED int OrigCancelState; int OrigCancelType; int LastCancelState; #endif Slot_Mgr_Shr_t *MemPtr = (Slot_Mgr_Shr_t *) Ptr; ASSERT ( MemPtr != NULL ); sleep(2); // SAB Linux likes to have us delay // Linux threading model appears to have some issues with regards to // signals.... Need to look at this FIXME.. /* setup */ /* Block the signals that go to the main thread */ /* FIXME: We probably want to make it so that signals go only to the main thread by default */ // SBADE .... FIXME... remove the blocking of signals see what happens.. // GCBlockSignals(); /* Make it so that we can only be cancelled when we reach a cancellation point */ /* cancellation points are listed here: http://techlib.austin.ibm.com/techlib/manuals/adoclib/aixprggd/genprogc/termthre.htm#D3A4499176manu */ /* PTHREAD_CANCEL_DEFERRED should be the default */ #if THREADED pthread_setcancelstate ( PTHREAD_CANCEL_ENABLE, &OrigCancelState ); pthread_setcanceltype ( PTHREAD_CANCEL_DEFERRED, &OrigCancelType ); /* push cleanup routines */ pthread_cleanup_push ( GCCancel, MemPtr ); #endif DbgLog(DL0, "Garbage collection running... PID %d\n",getpid()); while ( 1 ) { DbgLog(DL0, "Garbage collection running..."); /* Don't allow cancellations while mucking with shared memory or holding mutexes */ #if THREADED pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE, &LastCancelState ); #endif CheckForGarbage(MemPtr); #if THREADED /* re-enable cancellations */ pthread_setcancelstate ( PTHREAD_CANCEL_ENABLE, &LastCancelState ); /* Test for cancellation by the main thread */ pthread_testcancel(); #endif DbgLog(DL5, "Garbage collection finished."); /* now we pause */ sleep(10); } /* end while 1 */ #if THREADED /* Yeah, yeah. Has to be here because some implementations use macros that have to be balanced */ pthread_cleanup_pop ( 0 ); #endif /* return implicitly calls pthread_cancel() */ /* but it'll never really get executed; pthread_testcancel() implicitly calls pthread_exit() if there's a cancellation pending */ return NULL; } /********************************************************************************* * GCCancel - * * Cleanup routine called when Garbage collection thread exits/is cancelled * *********************************************************************************/ void GCCancel ( void *Ptr ) { /* Yeah, yeah. Doesn't do anything, but I had plans */ DbgLog(DL3, "GCCancel: tid: %d running cleanup routine", pthread_self()); return; } /********************************************************************************* * CheckForGarbage - * * The routine that actually does cleanup * *********************************************************************************/ BOOL CheckForGarbage ( Slot_Mgr_Shr_t *MemPtr ) { int SlotIndex; int ProcIndex; int Err; BOOL ValidPid; ASSERT( MemPtr != NULL_PTR ); #ifdef DEV DbgLog(DL5, "Thread %d is checking for garbage", pthread_self()); #endif /* DEV */ #ifdef DEV DbgLog (DL5, "Garbage collection attempting global shared memory lock"); #endif /* DEV */ /* Grab the global Shared mem mutex since we might modify global_session_count */ Err = XProcLock(); if ( Err != TRUE ) { DbgLog (DL0, "Garbage collection: Locking attempt for global shmem mutex returned %s", SysConst(Err) ); return FALSE; } #ifdef DEV DbgLog ( DL5, "Garbage collection: Got global shared memory lock"); #endif /* DEV */ for ( ProcIndex = 0; ProcIndex < NUMBER_PROCESSES_ALLOWED; ProcIndex++ ) { Slot_Mgr_Proc_t_64 *pProc = &(MemPtr->proc_table[ProcIndex]); ASSERT(pProc != NULL_PTR); if ( ! (pProc->inuse) ) { continue; } ValidPid = ( (IsValidProcessEntry ( pProc->proc_id, pProc->reg_time )) && (pProc->proc_id != 0) ); if ( ( pProc->inuse ) && (! ValidPid ) ) { #ifdef DEV DbgLog(DL1, "Garbage collection routine found bad entry for pid %d (Index: %d); removing from table", pProc->proc_id, ProcIndex ); #endif /* DEV */ /* */ /* Clean up session counts */ /* */ for ( SlotIndex = 0; SlotIndex < NUMBER_SLOTS_MANAGED; SlotIndex++ ) { unsigned int *pGlobalSessions = &(MemPtr->slot_global_sessions[SlotIndex]); unsigned int *pProcSessions = &(pProc->slot_session_count[SlotIndex]); if ( *pProcSessions > 0 ) { #ifdef DEV DbgLog ( DL2, "GC: Invalid pid (%d) is holding %d sessions open on slot %d. Global session count for this slot is %d", pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions ); #endif /* DEV */ if ( *pProcSessions > *pGlobalSessions ) { #ifdef DEV WarnLog ( "Garbage Collection: Illegal values in table for defunct process"); DbgLog ( DL0, "Garbage collection: A process ( Index: %d, pid: %d ) showed %d sessions open on slot %s, but the global count for this slot is only %d", ProcIndex, pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions ); #endif /* DEV */ *pGlobalSessions = 0; } else { *pGlobalSessions -= *pProcSessions; } *pProcSessions = 0; } /* end if *pProcSessions */ } /* end for SlotIndex */ /* */ /* NULL out everything except the mutex */ /* */ memset( &(pProc->inuse), '\0', sizeof(pProc->inuse) ); memset( &(pProc->proc_id), '\0', sizeof(pProc->proc_id) ); memset( &(pProc->slotmap), '\0', sizeof(pProc->slotmap) ); memset( &(pProc->blocking), '\0', sizeof(pProc->blocking )); memset( &(pProc->error), '\0', sizeof(pProc->error) ); memset( &(pProc->slot_session_count), '\0', sizeof(pProc->slot_session_count) ); memset( &(pProc->reg_time), '\0', sizeof(pProc->reg_time) ); } /* end if inuse && ValidPid */ } /* end for ProcIndex */ XProcUnLock(); DbgLog ( DL5, "Garbage collection: Released global shared memory lock"); return TRUE; } /********************************************************************************* * Stat2Proc - * * Fills a proc_t structure (defined in garbage_linux.h) * with a given pid's stat information found in the /proc//stat file * *********************************************************************************/ int Stat2Proc (int pid, proc_t *p) { char buf[800]; // about 40 fields, 64-bit decimal is about 20 chars char fbuf[800]; // about 40 fields, 64-bit decimal is about 20 chars char *tmp; int fd, num; // FILE *fp; // sprintf(buf, "%s/%d/stat", PROC_BASE, pid); // if( (fp = fopen(buf, "r")) == NULL ) // return FALSE; sprintf(fbuf, "%s/%d/stat", PROC_BASE, pid); printf("Buff = %s \n",fbuf); fflush(stdout); if( (fd = open(fbuf, O_RDONLY, 0)) == -1) return FALSE; num = read(fd, buf, 800); close(fd); if(num < 80) return FALSE; // buf[num] = '\0'; tmp = strrchr(buf, ')'); // split into "PID (cmd" and "" *tmp = '\0'; // replacing trailing ')' with NULL // Tmp now points to the rest of the buffer. // buff points to the command... /* fill in default values for older kernels */ p->exit_signal = SIGCHLD; p->processor = 0; /* now parse the two strings, tmp & buf, separately, skipping the leading "(" */ memset(p->cmd, 0, sizeof(p->cmd)); sscanf(buf, "%d (%15c", &p->pid, p->cmd); // comm[16] in kernel num = sscanf(tmp + 2, // skip space after ')' as well "%c " "%d %d %d %d %d " "%lu %lu %lu %lu %lu %lu %lu " "%ld %ld %ld %ld %ld %ld " "%lu %lu " "%ld " "%lu %lu %lu %lu %lu %lu " "%*s %*s %*s %*s " // discard, no RT signals & Linux 2.1 used hex (no use for RT signals) "%lu %lu %lu " "%d %d", &p->state, &p->ppid, &p->pgrp, &p->session, &p->tty, &p->tpgid, &p->flags, &p->min_flt, &p->cmin_flt, &p->maj_flt, &p->cmaj_flt, &p->utime, &p->stime, &p->cutime, &p->cstime, &p->priority, &p->nice, &p->timeout, &p->it_real_value, &p->start_time, &p->vsize, &p->rss, &p->rss_rlim, &p->start_code, &p->end_code, &p->start_stack, &p->kstk_esp, &p->kstk_eip, /* p->signal, p->blocked, p->sigignore, p->sigcatch, */ /* can't use */ &p->wchan, &p->nswap, &p->cnswap, /* -- Linux 2.0.35 ends here -- */ &p->exit_signal, &p->processor /* 2.2.1 ends with "exit_signal" */ /* -- Linux 2.2.8 and 2.3.47 end here -- */ ); /* fprintf(stderr, "Stat2Proc() converted %d fields.\n", num); */ if (p->tty == 0) p->tty = -1; // the old notty val, updated elsewhere before moving to 0 p->vsize /= 1024; if(num < 30) return FALSE; if(p->pid != pid) return FALSE; return TRUE; } /********************************************************************************* * IsValidProcessEntry - * * Checks to see if the process identifed by pid is the same process * that registered with us * *********************************************************************************/ BOOL IsValidProcessEntry ( pid_t_64 pid, time_t_64 RegTime ) { int Err; int valid; proc_t *p; proc_t procstore; /* If kill(pid, 0) returns -1 and errno/Err = ESRCH, the pid doesn't exist */ if ( kill(pid, 0) == -1 ) { Err = errno; if ( Err == ESRCH ) { /* The process was not found */ DbgLog(DL3, "IsValidProcessEntry: PID %d was not found in the process table (kill() returned %s)", pid, SysConst(Err) ); return FALSE; } else { /* some other error occurred */ DbgLog(DL3, "IsValidProcessEntry: kill() returned %s (%d; %#x)", SysConst(Err), Err, Err); return FALSE; } } /* end if kill */ /* Okay, the process exists, now we see if it's really ours */ #ifdef ALLOCATE p = (proc_t *)malloc(sizeof(proc_t)); #else p = &procstore; memset(p, 0, sizeof(proc_t)); #endif if( !(valid = Stat2Proc( (int)pid, p )) ) return FALSE; if ( p->pid == pid ) { if ( RegTime >= p->start_time ) { // checking for matching start times return TRUE; } else { /* p->start_time contains the time at which the process began ?? (22nd element in /proc//stat file) */ DbgLog(DL1, "IsValidProcessEntry: PID %d started at %lu; registered at %ld", pid, p->start_time, RegTime); DbgLog(DL4, "IsValidProcessEntry: PID Returned %d flags at %#x; state at %#x", p->pid, p->flags, p->state); } } return FALSE; } #endif // NO Garbage opencryptoki+dfsg/usr/sbin/pkcsslotd/mutex.c0000755000175000017500000004242312630407154020367 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include #include #include #include #include "log.h" #include "slotmgr.h" static int xplfd=-1; int CreateXProcLock(void) { struct group *grp; mode_t mode = (S_IRUSR|S_IRGRP); struct stat statbuf; if (xplfd == -1) { if (stat(OCK_API_LOCK_FILE, &statbuf) == 0) xplfd = open(OCK_API_LOCK_FILE, O_RDONLY, mode); else { xplfd = open(OCK_API_LOCK_FILE, O_CREAT|O_RDONLY, mode); if (xplfd != -1) { if (fchmod(xplfd, mode) == -1) { DbgLog(DL0,"%s:fchmod(%s):%s\n", __FUNCTION__, OCK_API_LOCK_FILE, strerror(errno)); goto error; } grp = getgrnam("pkcs11"); if (grp != NULL) { if (fchown(xplfd,-1,grp->gr_gid) == -1) { DbgLog(DL0,"%s:fchown(%s):%s\n", __FUNCTION__, OCK_API_LOCK_FILE, strerror(errno)); goto error; } } else { DbgLog(DL0,"%s:getgrnam():%s\n", __FUNCTION__, strerror(errno)); goto error; } } } if (xplfd == -1) { DbgLog(DL0,"open(%s): %s\n", OCK_API_LOCK_FILE, strerror(errno)); return FALSE; } } return TRUE; error: if (xplfd != -1) close(xplfd); return FALSE; } int XProcLock(void) { if (xplfd != -1) flock(xplfd, LOCK_EX); return TRUE; } int XProcUnLock(void) { if (xplfd != -1) flock(xplfd, LOCK_UN); return TRUE; } /********************************************************************************* * * InitializeMutexes - * * Initializes the global shared memory mutex, and sets up mtxattr, * the attribute identifier used to create all the per-process mutexes * *********************************************************************************/ int InitializeMutexes ( void ) { int err; if ((err = CreateXProcLock()) != TRUE){ DbgLog(DL0,"InitializeMutexes: CreateXProcLock() failed - returned %#x\n", err); return FALSE; } return TRUE; } /*********************************************************************** * DestroyMutexes - * * Destroys all the mutexes used by the program * ***********************************************************************/ int DestroyMutexes ( void ) { /* Get the global shared memory mutex */ XProcLock(); /* Give up the global shared memory mutex */ XProcUnLock(); return TRUE; } opencryptoki+dfsg/usr/sbin/pkcsslotd/opencryptoki.conf0000644000175000017500000000124212630407154022445 0ustar xnoxxnoxversion opencryptoki-3.1 # The following defaults are defined: # hwversion = 0.0 # firmwareversion = 0.0 # description = Linux # manufacturer = IBM # # The slot definitions below may be overriden and/or customized. # For example: # slot 0 # { # stdll = libpkcs11_cca.so # description = "OCK CCA Token" # manufacturer = "MyCompany Inc." # hwversion = 2.32 # firmwareversion = 1.0 # } # # See man(5) opencryptoki.conf for further information. # slot 0 { stdll = libpkcs11_tpm.so } slot 1 { stdll = libpkcs11_ica.so } slot 2 { stdll = libpkcs11_cca.so } slot 3 { stdll = libpkcs11_sw.so } slot 4 { stdll = libpkcs11_ep11.so confname = ep11tok.conf } opencryptoki+dfsg/usr/sbin/pkcsslotd/slotmgr.c0000755000175000017500000005200612630407154020712 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include #include "log.h" #include "slotmgr.h" #include "pkcsslotd.h" #include "parser.h" Slot_Mgr_Shr_t *shmp; // pointer to the shared memory region. int shmid; key_t tok; Slot_Info_t_64 sinfo[NUMBER_SLOTS_MANAGED]; unsigned char NumberSlotsInDB = 0; int socketfd; Slot_Mgr_Socket_t socketData; /* We make main() able to modify Daemon so that we can daemonize or not based on a command-line argument */ extern BOOL Daemon; extern BOOL IveDaemonized; void DumpSharedMemory(void) { u_int32 *p; char Buf[PATH_MAX]; u_int32 i; p = (u_int32 *) shmp; for ( i = 0; i < 15; i++ ) { sprintf(Buf, "%08X %08X %08X %08X", p[0+(i*4)], p[1+(i*4)], p[2+(i*4)], p[3+(i*4)]); LogLog(Buf); } return; } /***************************************** * main() - * You know what main does. * Comment block for ease of spotting * it when paging through file * *****************************************/ int main ( int argc, char *argv[], char *envp[]) { int ret; /**********************************/ /* Read in command-line arguments */ /**********************************/ /* FIXME: Argument for daemonizing or not */ /* FIXME: Argument for debug level */ /* FIXME: Arguments affecting the log files, whether to use syslog, etc. (Read conf file?) */ /* Report our debug level */ if ( GetDebugLevel() > DEBUG_NONE) { DbgLog(GetDebugLevel(), "Starting with debugging messages logged at level %d (%d = No messages; %d = few; %d = more, etc.)", GetDebugLevel(), DEBUG_NONE, DEBUG_LEVEL0, DEBUG_LEVEL1); } /* Save our startup directory */ SaveStartupDirectory( argv[0] ); ret = load_and_parse(OCK_CONFIG); if (ret != 0) { ErrLog("Failed to read config file.\n"); return 1; } else DbgLog (DL0, "Parse config file succeeded.\n"); /* Allocate and Attach the shared memory region */ if ( ! CreateSharedMemory() ) { /* CreateSharedMemory() does it's own error logging */ return 1; } DbgLog(DL0,"SHMID %d token %#X \n", shmid, tok); /* Now that we've created the shared memory segment, we attach to it */ if ( ! AttachToSharedMemory() ) { /* AttachToSharedMemory() does it's own error logging */ DestroySharedMemory(); return 2; } /* Initialize the global shared memory mutex (and the attribute used to create the per-process mutexes */ if ( ! InitializeMutexes() ) { DetachFromSharedMemory(); DestroySharedMemory(); return 3; } /* Get the global shared memory mutex */ XProcLock(); /* Populate the Shared Memory Region */ if ( ! InitSharedMemory(shmp) ) { XProcUnLock(); DetachFromSharedMemory(); DestroySharedMemory(); return 4; } /* Release the global shared memory mutex */ XProcUnLock(); if ((socketfd = CreateListenerSocket()) < 0) { DestroyMutexes(); DetachFromSharedMemory(); DestroySharedMemory(); return 5; } if (!InitSocketData(&socketData)) { DetachSocketListener(socketfd); DestroyMutexes(); DetachFromSharedMemory(); DestroySharedMemory(); return 6; } /* * Become a Daemon, if called for */ if ( Daemon ) { pid_t pid; if ( (pid = fork()) < 0 ){ DetachSocketListener(socketfd); DestroyMutexes(); DetachFromSharedMemory(); DestroySharedMemory(); return 7; } else { if ( pid != 0) { exit(0); // Terminate the parent } else { setsid(); // Session leader #ifndef DEV fclose(stderr); fclose(stdout); fclose(stdin); #endif } } } else { #ifdef DEV // Log only on development builds LogLog("Not becoming a daemon...\n"); #endif } /***************************************** * * Register Signal Handlers * Daemon probably should ignore ALL signals possible, since termination * while active is a bad thing... however one could check for * any processes active in the shared memory, and destroy the shm if * the process wishes to terminate. * *****************************************/ /* * We have to set up the signal handlers after we daemonize because * the daemonization process redefines our handler for (at least) SIGTERM */ if ( ! SetupSignalHandlers() ) { DetachSocketListener(socketfd); DestroyMutexes(); DetachFromSharedMemory(); DestroySharedMemory(); return 8; } /* ultimatly we will create a couple of threads which monitor the slot db and handle the insertion and removal of tokens from the slot. */ /* For Testing the Garbage collection routines */ /* shmp->proc_table[3].inuse = TRUE; shmp->proc_table[3].proc_id = 24328; */ #if !defined(NOGARBAGE) printf("Start garbage \n"); /* start garbage collection thread */ if ( ! StartGCThread(shmp) ) { DetachSocketListener(socketfd); DestroyMutexes(); DetachFromSharedMemory(); DestroySharedMemory(); return 9; } #endif // We've fully become a daemon. Now create the PID file { FILE *pidfile; pidfile = fopen(PID_FILE_PATH,"w"); if (pidfile) { fprintf(pidfile,"%d",getpid()); fclose(pidfile); } } while (1) { #if !(THREADED) && !(NOGARBAGE) CheckForGarbage(shmp); #endif SocketConnectionHandler(socketfd, 10); } /************************************************************* * * Here we need to actualy go through the processes and verify that thye * still exist. If not, then they terminated with out properly calling * C_Finalize and therefore need to be removed from the system. * Look for a system routine to determine if the shared memory is held by * the process to further verify that the proper processes are in the * table. * *************************************************************/ } /* end main */ opencryptoki+dfsg/usr/sbin/pkcsslotd/log.c0000755000175000017500000010071712630407154020007 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include #include #include #include "log.h" #include "err.h" #include "slotmgr.h" #include "pkcsslotd.h" #define DEFAULT_PROGRAM_NAME "Program" #ifndef PROGRAM_NAME #define PROGRAM_NAME DEFAULT_PROGRAM_NAME #endif /* PROGRAM_NAME */ #ifdef DEV #ifndef DEFAULT_LOG_FILE #define DEFAULT_LOG_FILE "/tmp/" ## PROGRAM_NAME ## ".log" #endif /* DEFAULT_LOG_FILE */ #else /* production build */ #ifndef DEFAULT_LOG_FILE #define DEFAULT_LOG_FILE NULL #endif /* DEFAULT_LOG_FILE */ #endif /* DEV */ #ifndef LOG_FILE #define LOG_FILE DEFAULT_LOG_FILE #endif /* LOG_FILE */ #ifndef DEFAULT_DEBUG_LEVEL /********************* DEFAULT_DEBUG_LEVEL is generally defined in another file (pkcsslotd.h?) The #defines here generally won't change much. *********************/ #ifdef DEV #define DEFAULT_DEBUG_LEVEL DEBUG_LEVEL0 #else #define DEFAULT_DEBUG_LEVEL DEBUG_NONE #endif /* DEFAULT_DEBUG_LEVEL */ #endif /* DEFAULT_DEBUG_LEVEL */ static u_int32 DefaultLogOption = ( LOG_CONS | LOG_NOWAIT | LOG_ODELAY | LOG_PID ); static BOOL Initialized = FALSE; static BOOL LoggingInitialized = FALSE; static u_int32 SysDebugLevel = DEFAULT_DEBUG_LEVEL; static char *ProgramName = PROGRAM_NAME; static LoggingFacilityInfo LogInfo[MAX_LOGGING_FACILITIES]; static LogHandle hLogDebug; static LogHandle hLogErr; static LogHandle hLogLog; static LogHandle hLogTrace; static LogHandle hLogWarn; static LogHandle hLogInfo; static LoggingFacility SystemLogFacilities[] = { { " DEBUG", &hLogDebug, LOG_FILE, TRUE, LOG_DEBUG }, { " INFO", &hLogInfo, LOG_FILE, TRUE, LOG_INFO }, { " TRACE", &hLogTrace, LOG_FILE, TRUE, LOG_INFO }, { " LOG", &hLogLog, LOG_FILE, TRUE, LOG_NOTICE }, { "WARNING", &hLogWarn, LOG_FILE, TRUE, LOG_WARNING }, { " ERROR", &hLogErr, LOG_FILE, TRUE, LOG_ERR } }; /***************************************** * Function Prototypes * *****************************************/ static int InitDataStructs ( void ); static BOOL InitLogging ( void ); static pLoggingFacilityInfo GetLogInfoPtr ( LogHandle hLog ); static BOOL GetFreeLogInfo ( pLogHandle Dest ); static void CloseAllLoggingFacilities ( void ); static BOOL SyslogOpen ( pLoggingFacilityInfo pInfo ); /************************************************************* * GetCurrentTimeString - * * Writes the current date & time into *Buffer * *************************************************************/ BOOL GetCurrentTimeString ( char *Buffer ) { /* Note: The specs for ctime_r and asctime_r say that Buffer needs to be 26 characters long. Not sure if that includes a triling NULL - SCM */ time_t t; struct tm tm; ASSERT(Buffer != NULL); time(&t); localtime_r(&t, &tm); asctime_r( &tm , &(Buffer[0]) ); /* asctime_r puts a \n at the end, so we'll remove that */ Buffer[strlen(Buffer)-1] = '\0'; return TRUE; } /*********************************************************************** * InitDataStructs - * * Called durining initalization to set up the LogInfo array * ***********************************************************************/ static int InitDataStructs ( void ) { unsigned int i; for ( i = 0; i < (sizeof(LogInfo) / sizeof(LogInfo[0])); i++ ) { LogInfo[i].Initialized = FALSE; LogInfo[i].Descrip[0] = '\0'; LogInfo[i].LogOption = DefaultLogOption; } Initialized = TRUE; return TRUE; } /********************************************************************** * GetFreeLogInfo - * * Return the handle for the next available Log Facility structure * * After calling this function, the facility will be marked as in use * ***********************************************************************/ static BOOL GetFreeLogInfo ( pLogHandle Dest ) { u_int32 i; if ( ! Initialized ) { InitDataStructs(); } for ( i = 0; i < ( sizeof(LogInfo) / sizeof(LogInfo[0]) ); i++ ) { if ( LogInfo[i].Initialized == FALSE ) { /* Set this here so that we don't return the same identifier twice in the case where GetFreeLogInfo() is called twice in a row */ LogInfo[i].Initialized = TRUE; *Dest = i; return TRUE; } } #ifdef DEV fprintf(stderr, "No available thread logging structs.\n"); #endif return FALSE; } /********************************************************************** * GetLogInfoPtr - * * Given a handle, return a pointer to the appropriate LoggingFacilityInfo structure * ***********************************************************************/ static pLoggingFacilityInfo GetLogInfoPtr ( LogHandle hLog ) { if ( hLog >= (sizeof(LogInfo) / sizeof(LogInfo[0]) ) ) { #ifdef DEV fprintf(stderr, "Illegal LogHandle value: %#X\n", hLog); #endif return NULL; } if ( LogInfo[hLog].Initialized != TRUE ) { #ifdef DEV fprintf(stderr, "GetLogInfoPtr() called for a non-initialized handle\n"); #endif return NULL; } return &(LogInfo[hLog]); } /*********************************************************************** * NewLoggingFacility - * * Given an ID ( char string which will appear in the messages ), * open a logging facility and return a handle to it in * pLoggingStuff->phLog * ***********************************************************************/ BOOL NewLoggingFacility ( char *ID, pLoggingFacility pStuff ) { pLoggingFacilityInfo pInfo = NULL; LogHandle hLog; pLogHandle Result; /* See if there's room in the array. This'd be nice if it were dynamically allocated */ if ( ! GetFreeLogInfo(&hLog) ) { return FALSE; } /* Get a pointer to the syslog_data structure */ if ( (pInfo = GetLogInfoPtr(hLog)) == NULL ) { return FALSE; } Result = pStuff->phLog; /* Set this before the filename is checked because we may want to use the descrip and/or filename in the logs */ pInfo->UseSyslog = pStuff->UseSyslog; pInfo->LogOption = DefaultLogOption; pInfo->pid = 0; pInfo->LogLevel = pStuff->LogLevel; sprintf( pInfo->Descrip, "%s %s", pStuff->Label, ID ); /* ensure that the last character is a NULL */ pInfo->Descrip[sizeof(pInfo->Descrip)-1] = '\0'; /* Some sanity checking on filename... */ if ( (pStuff->Filename != NULL) && (strlen(pStuff->Filename) > 0) ) { FILE *fd; #if TRUNCATE_LOGS_ON_START /* * Truncating files on the start will present problems if the user creates * their own logging facilities after the program's been running for a while * But the non-syslog logging is intended for debug purposes only, anyway. * */ char FileMode[] = "w"; #else char FileMode[] = "a"; #endif /* TRUNCATE_LOGS_ON_START */ if ( ( fd = fopen((pStuff->Filename), FileMode ) ) == NULL ) { #ifdef DEV fprintf(stderr, "%s could not be opened\n", pStuff->Filename); #endif pInfo->Filename = NULL; } else { /* Tag the file */ char buf[100]; GetCurrentTimeString( &(buf[0]) ); #ifdef DEV #if TRUNCATE_LOGS_ON_START /* buf contains the date stamp */ fprintf(fd, "********* %s %s truncated *********\n", buf, pStuff->Filename); #else fprintf(fd, "********* %s \"%s\" logging to %s *********\n", buf, pInfo->Descrip, pStuff->Filename); #endif /* TRUNCATE_LOGS_ON_START */ #endif fflush(fd); fclose(fd); pInfo->Filename = pStuff->Filename; } } else { pInfo->Filename = NULL; } if ( pInfo->UseSyslog ) { /* open the logging facility */ if (! SyslogOpen( pInfo ) ) { return FALSE; } } /* Redundant; Initialized is set to 1 in GetFreeLogInfo */ pInfo->Initialized = TRUE; *Result = hLog; return TRUE; } /*********************************************************************** * CloseLoggingFacility - * * Closes the logging facility whose handle is hLog. * Sets up the data structure for reuse later if desired * ***********************************************************************/ BOOL CloseLoggingFacility ( LogHandle hLog ) { pLoggingFacilityInfo pInfo = NULL; if ( (pInfo = GetLogInfoPtr(hLog)) == NULL ) { return FALSE; } pInfo->Descrip[0] = '\0'; pInfo->LogOption = 0; pInfo->Filename = NULL; pInfo->pid = 0; if ( pInfo->UseSyslog ) { closelog( ); } pInfo->Initialized = FALSE; return TRUE; } /***************************************** * CloseAllLoggingFacilities - * * Closes down all the logging stuff we've set up *****************************************/ static void CloseAllLoggingFacilities ( void ) { u_int32 i = 0; for ( i = 0; i < (sizeof(LogInfo) / sizeof(LogInfo[0])); i++ ) { /* Makes assumption that these handles all are sequential. Bad Style */ if ( LogInfo[i].Initialized ) { CloseLoggingFacility(i); } } return; } /*********************************************************************** * PKCS_Log - * * The primitive logging function which logs a message on hLog * ***********************************************************************/ BOOL PKCS_Log ( pLogHandle phLog, char *Format, va_list ap ) { char Buffer[PATH_MAX]; pLoggingFacilityInfo pInfo; if ( Format == NULL ) { return FALSE; } if ( (pInfo = GetLogInfoPtr(*phLog)) == NULL ) { return FALSE; } if ( (pInfo->pid != getpid() ) && (pInfo->UseSyslog) ) { /* Looks like our PID changed since the last call. We have to re-open */ if (! SyslogOpen(pInfo) ) { return FALSE; } } if ( vsprintf(&(Buffer[0]), Format, ap) < 0 ) { /* Error reporting functions should be rather robust, don't you think? */ /* vsprintf reporting an error */ //fprintf(stderr, "PKCS_ErrLog - vsprintf error for format string %s\n", Format); return FALSE; } /* Get rid of trailing newlines. */ while ( strlen(Buffer) && (Buffer[strlen(Buffer)-1] == '\n') ) { Buffer[strlen(Buffer)-1] = '\0'; } // Development work only. No loging to anything other than syslog for // production level code /* 1/17/00 SCM - If we're not a daemon, we need to print something to stderr for warnings and errors regardless of development/production. This is for errors that occur during startup. I'll agree that we don't need to write to a log file in production mode, however. */ /* Production mode: Write to stderr if we're not a daemon, and the priority of the message is at least LOG_WARNING Development mode: Write to stderr if we're not a daemon */ if ( ! IsDaemon() ) { BOOL WriteNow; #ifdef DEV WriteNow = TRUE; #else WriteNow = (pInfo->LogLevel <= LOG_WARNING); #endif /* DEV */ if ( WriteNow ) { fprintf(stderr, "%s[%d.%d]: %s\n", pInfo->Descrip, getpid(), (int)pthread_self(), Buffer); } } /* Don't log to a separate log file in production mode */ #ifdef DEV if ( pInfo->Filename != NULL ) { FILE *fd; if ( (fd = fopen ( pInfo->Filename, "a+" ) ) == NULL ) { fprintf(stderr, "PKCS_Log: fopen failed for %s\n", pInfo->Filename); } else { char buf[32]; /* Specs say 26-character array */ GetCurrentTimeString( &(buf[0]) ); /* Date/Time stamp, descrip, Error message */ fprintf ( fd, "%s %s[%d.%d]: ", buf, pInfo->Descrip, getpid(), pthread_self() ); fprintf ( fd, "%s\n", Buffer); fflush ( fd ); fclose ( fd ); } } /* end if pInfo->Filename */ #endif /* DEV */ /* Always log to syslog, if we're using it */ if ( pInfo->UseSyslog ) { syslog(pInfo->LogLevel, "%s", Buffer); } return TRUE; } /**************************************************************************** * * Would like to have a generic function to which I pass the hLog where I'd * like to do the logging and have a #defined macro which passes it along... * * But the preprocessor and variable # args don't work & play well together * ****************************************************************************/ /***************************************** * DbgLog - * * Log messages using the debug facility *****************************************/ void DbgLog ( u_int32 DebugLevel, char *Format, ... ) { va_list ap; if ( DebugLevel > SysDebugLevel ) { return; } if ( ! LoggingInitialized ) { InitLogging(); } va_start( ap, Format ); PKCS_Log( &hLogDebug, Format, ap); va_end ( ap ) ; return; } /***************************************** * ErrLog - * * Log Messges using the error facility *****************************************/ void ErrLog ( char *Format, ... ) { va_list ap; if ( ! LoggingInitialized ) { InitLogging(); } va_start( ap, Format ); PKCS_Log( &hLogErr, Format, ap); va_end ( ap ) ; return; } /***************************************** * LogLog - * * Log messages using the log facility *****************************************/ void LogLog ( char *Format, ... ) { va_list ap; if ( ! LoggingInitialized ) { InitLogging(); } va_start( ap, Format ); PKCS_Log( &hLogLog, Format, ap); va_end ( ap ) ; return; } /***************************************** * WarnLog - * * Log messages using the warning facility *****************************************/ void WarnLog ( char *Format, ... ) { va_list ap; if ( ! LoggingInitialized ) { InitLogging(); } va_start( ap, Format ); PKCS_Log( &hLogWarn, Format, ap); va_end ( ap ) ; return; } /***************************************** * TraceLog - * * Log messages using the trace facility *****************************************/ void TraceLog ( char *Format, ... ) { va_list ap; if ( ! LoggingInitialized ) { InitLogging(); } va_start( ap, Format ); PKCS_Log( &hLogTrace, Format, ap); va_end ( ap ) ; return; } /***************************************** * InfoLog - * * Log messages using the info facility *****************************************/ void InfoLog ( char *Format, ... ) { va_list ap; if ( ! LoggingInitialized ) { InitLogging(); } va_start( ap, Format ); PKCS_Log( &hLogInfo, Format, ap); va_end ( ap ) ; return; } /*********************************************************************** * InitLogging - * * Sets up the various logging facilities. Must be called before * any of the logging functions can be used. ***********************************************************************/ static BOOL InitLogging ( void ) { unsigned int i; char *s = ProgramName; /* if ProgramName is NULL, we'll just print the level... */ if ( ProgramName == NULL ) { s = ""; } /* Set up logging for all the facilities in SystemLogFacilities[] */ for ( i = 0; i < ( sizeof(SystemLogFacilities) / (sizeof(SystemLogFacilities[0])) ); i++ ) { if (! NewLoggingFacility(s, &(SystemLogFacilities[i]) ) ) { #ifdef DEV fprintf(stderr, "InitLogging: NewLoggingFacility failed: %s\n", s); #endif return FALSE; } } /* end for i */ atexit(CloseAllLoggingFacilities); LoggingInitialized = TRUE; return TRUE; } /************************************************************* * SetDebugLevel - * * * Sets the level at which debug messages get logged to Val. * Returns the old value *************************************************************/ u_int32 SetDebugLevel ( u_int32 Val ) { u_int32 OldVal = SysDebugLevel; SysDebugLevel = Val; return OldVal; } /************************************************************* * GetDebugLevel * * Returns the level at which the program will log debug messages * *************************************************************/ u_int32 GetDebugLevel ( void ) { return SysDebugLevel; } #if 0 int main ( int argc, char *argv[], char *envp[] ) { ErrLog("This is an error test, attempt 1"); DbgLog(DEBUG_LEVEL0, "This is a DEBUG test level 0, attempt 1"); DbgLog(DEBUG_LEVEL1, "This is a DEBUG test level 1, attempt 1"); SetDebugLevel(DEBUG_NONE); DbgLog(DEBUG_LEVEL1, "This is a DEBUG test level 1, attempt 2"); DbgLog(DEBUG_LEVEL0, "This is a DEBUG test level 0, attempt 2"); ErrLog("This is an error test, attempt 2"); return 0; } #endif /* 0 */ static BOOL SyslogOpen ( pLoggingFacilityInfo pInfo ) { ASSERT(pInfo != NULL); if ( !( pInfo->UseSyslog ) ) { /* it's not really an error to call SyslogOpen for a facility that doesn't use it */ return TRUE; } if ( pInfo->pid != 0 ) { /* We've been initialized before, so close the previous instance */ closelog(); } /* Default to log all messages. */ setlogmask( LOG_UPTO(LOG_DEBUG)); /* Mark this as having been set by this process */ pInfo->pid = getpid(); return TRUE; } opencryptoki+dfsg/usr/sbin/pkcsslotd/socket_server.c0000644000175000017500000004453012630407154022101 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT Google Inc. 2013 */ #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "slotmgr.h" #include "pkcsslotd.h" #include "apictl.h" // Creates the daemon's listener socket, to which clients will connect and // retrieve slot information through. Returns the file descriptor of the // created socket. int CreateListenerSocket (void) { struct sockaddr_un address; struct group *grp; int socketfd; socketfd = socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); if (socketfd < 0) { ErrLog("Failed to create listener socket, errno 0x%X.", errno); return -1; } if (unlink(SOCKET_FILE_PATH) && errno != ENOENT) { ErrLog("Failed to unlink socket file, errno 0x%X.", errno); close(socketfd); return -1; } memset(&address, 0, sizeof(struct sockaddr_un)); address.sun_family = AF_UNIX; strcpy(address.sun_path, SOCKET_FILE_PATH); if (bind(socketfd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0) { ErrLog("Failed to bind to socket, errno 0x%X.", errno); close(socketfd); return -1; } // make socket file part of the pkcs11 group, and write accessable // for that group grp = getgrnam("pkcs11"); if (!grp) { ErrLog("Group PKCS#11 does not exist"); DetachSocketListener(socketfd); return -1; } if (chown(SOCKET_FILE_PATH, 0, grp->gr_gid)) { ErrLog("Could not change file group on socket, errno 0x%X.", errno); DetachSocketListener(socketfd); return -1; } if (chmod(SOCKET_FILE_PATH, S_IRUSR|S_IRGRP|S_IWUSR|S_IWGRP|S_IXUSR|S_IXGRP)) { ErrLog("Could not change file permissions on socket, errno 0x%X.", errno); DetachSocketListener(socketfd); return -1; } if(listen(socketfd, 20) != 0) { ErrLog("Failed to listen to socket, errno 0x%X.", errno); DetachSocketListener(socketfd); return -1; } return socketfd; } int InitSocketData (Slot_Mgr_Socket_t *socketData) { int processed = 0; PopulateCKInfo(&(socketData->ck_info)); socketData->num_slots = NumberSlotsInDB; PopulateSlotInfo(socketData->slot_info, &processed); /* check that we read in correct amount of slots */ if (processed != NumberSlotsInDB) { ErrLog("Failed to populate slot info.\n"); return FALSE; } else return TRUE; } int SocketConnectionHandler (int socketfd, int timeout_secs) { int returnVal; fd_set set; struct timeval timeout; FD_ZERO(&set); FD_SET(socketfd, &set); timeout.tv_sec = timeout_secs; timeout.tv_usec = 0; returnVal = select(socketfd + 1, &set, NULL, NULL, &timeout); if (returnVal == -1) { ErrLog("select failed on socket connection, errno 0x%X.", errno); return FALSE; } else if (returnVal == 0) { // select call timed out, return return FALSE; } else { struct sockaddr_un address; socklen_t address_length = sizeof(address); int connectionfd = accept(socketfd, (struct sockaddr *) &address, &address_length); if (connectionfd < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { /* These errors are allowed since * socket is non-blocking */ ErrLog("Failed to accept socket connection, errno 0x%X.", errno); } return FALSE; } if (write(connectionfd, &socketData, sizeof(socketData)) != sizeof(socketData)) { ErrLog("Failed to write socket data, errno 0x%X.", errno); close(connectionfd); return FALSE; } close(connectionfd); return TRUE; } } void DetachSocketListener(int socketfd) { close(socketfd); unlink(SOCKET_FILE_PATH); } opencryptoki+dfsg/usr/sbin/pkcsslotd/Makefile.am0000644000175000017500000000162112630407154021105 0ustar xnoxxnoxsbin_PROGRAMS=pkcsslotd BUILT_SOURCES = parser.h AM_YFLAGS = -v -d EXTRA_DIST=opencryptoki.conf pkcsslotd_LDFLAGS = -lpthread # Not all versions of automake observe sbinname_CFLAGS pkcsslotd_CFLAGS = -DPROGRAM_NAME=\"$(@)\" \ -I../. -I../../include/pkcs11 -I../../include/pkcs11/stdll # Not all versions of automake observe sbinname_CFLAGS AM_CFLAGS = -DPROGRAM_NAME=\"$(@)\" \ -I../. -I../../include/pkcs11 -I../../include/pkcs11/stdll pkcsslotd_SOURCES = slotmgr.c shmem.c signal.c mutex.c err.c log.c daemon.c \ garbage_linux.c pkcsslotd_util.c socket_server.c \ parser.y lexer.l install-data-local : test -f $(DESTDIR)$(sysconfdir)/opencryptoki || $(MKDIR_P) $(DESTDIR)$(sysconfdir)/opencryptoki || true test -f $(DESTDIR)$(sysconfdir)/opencryptoki/opencryptoki.conf || $(INSTALL) -m 644 $(srcdir)/opencryptoki.conf $(DESTDIR)$(sysconfdir)/opencryptoki/opencryptoki.conf || true opencryptoki+dfsg/usr/sbin/pkcsslotd/lexer.l0000644000175000017500000003722012630407154020351 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2002 */ %{ /* Parser for /etc/opencryptoki.conf */ #include #include #include "parser.h" int line_num = 1; %} %option noyywrap %% [\t ]+ /* ignore spaces */ ; = return EQUAL; \{ return BEGIN_DEF; \n\{ { line_num++; return BEGIN_DEF; } \} return END_DEF; \n|#.*\n { line_num++; return EOL; } [0-9]+ { /* number */ yylval.num = strtoul(yytext, NULL, 10); return INTEGER; } version return OCKVERSION; slot return SLOT; [^\"= \t\n]+ { yylval.str = strdup(yytext); return STRING; } \"[^\"\n]*\" { yylval.str = strdup(yytext+1); if (yylval.str) yylval.str[strlen(yylval.str)-1]='\0'; return STRING; } . yyerror(yytext); %% opencryptoki+dfsg/usr/sbin/pkcsslotd/garbage_linux.h0000755000175000017500000004303112630407154022035 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/sbin/pkcsslotd/garbage_linux.h,v 1.3 2006/03/09 17:21:01 mhalcrow Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef GARBAGE_LINUX_H #define GARBAGE_LINUX_H typedef struct { int pid; /* process id */ char cmd[16], /* command line string vector for /proc//cmdline */ state; /* single-char code for process state [R, S, D, Z, or T] */ int ppid, /* pid of parent process */ pgrp, /* process group id */ session, /* session id */ tty, /* full device number of controlling terminal */ tpgid; /* terminal process group id */ unsigned long flags, /* kernel flags for the process */ min_flt, /* number of minor page faults since process start */ cmin_flt, /* cumulative min_flt of process and child processes */ maj_flt, /* number of major page faults since process start */ cmaj_flt, /* cumulative maj_flt of process and child processes */ utime, /* user-mode CPU time accumulated by process */ stime; /* kernel-mode CPU time accumulated by process */ long cutime, /* cumulative utime of process and reaped children */ cstime, /* cumulative stime of process and reaped children */ priority, /* kernel scheduling priority */ nice, /* standard unix nice level of process */ timeout, /* ? */ it_real_value; /* ? */ unsigned long start_time, /* start time of process -- seconds since 1-1-70 */ vsize; /* number of pages of virtual memory ... */ long rss; /* resident set size from /proc//stat (pages) */ unsigned long rss_rlim, /* resident set size limit? */ start_code, /* address of beginning of code segment */ end_code, /* address of end of code segment */ start_stack, /* address of the bottom of stack for the process */ kstk_esp, /* kernel stack pointer */ kstk_eip; /* kernel instruction pointer */ char /* Linux 2.1.7x and up have more signals. This handles 88. */ /* long long (instead of char xxxxxx[24]) handles 64 */ signal[24], /* mask of pending signals */ blocked[24], /* mask of blocked signals */ sigignore[24], /* mask of ignored signals */ sigcatch[24]; /* mask of caught signals */ unsigned long wchan, /* address of kernel wait channel proc is sleeping in */ nswap, /* ? */ cnswap; /* cumulative nswap ? */ int exit_signal, processor; } proc_t; #endif opencryptoki+dfsg/usr/sbin/pkcsslotd/pkcsslotd_util.c0000755000175000017500000004324412630407154022272 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT Google Inc. 2013 */ #include #include #include #include "slotmgr.h" #include "log.h" #include "pkcsslotd.h" void PopulateCKInfo(CK_INFO_PTR_64 ckinf) { CK_VERSION_PTR ckver; char *package_version_tmp; char *tok_str; CK_BYTE lib_major; CK_BYTE lib_minor; ckver = &(ckinf->cryptokiVersion); ckver->major = CRYPTOKI_API_MAJOR_V; ckver->minor = CRYPTOKI_API_MINOR_V; memset(ckinf->manufacturerID, ' ', sizeof(ckinf->manufacturerID)); memset(ckinf->libraryDescription, ' ', sizeof(ckinf->libraryDescription)); memcpy(ckinf->manufacturerID, MFG, strlen(MFG)); memcpy(ckinf->libraryDescription, LIB, strlen(LIB)); ckver = &(ckinf->libraryVersion); ckver->major = LIB_MAJOR_V; ckver->minor = LIB_MINOR_V; #ifdef PACKAGE_VERSION package_version_tmp = malloc(strlen(PACKAGE_VERSION)+1); if (package_version_tmp) { strcpy(package_version_tmp, PACKAGE_VERSION); tok_str = strtok(package_version_tmp, "."); if (tok_str) { lib_major = (CK_BYTE)atoi(tok_str); tok_str = strtok(NULL, "."); if (tok_str) { lib_minor = (CK_BYTE)atoi(tok_str); ckver->major = lib_major; ckver->minor = lib_minor; } } free(package_version_tmp); } #endif } void PopulateSlotInfo(Slot_Info_t_64 *slot_info, int *processed) { CK_SLOT_ID id; int slot_count = 0; /* * populate the Slot entries... */ for (id=0; id < NUMBER_SLOTS_MANAGED; id++) { if (sinfo[id].present == FALSE) /* skip empty slots and just note the slot number */ slot_info[id].slot_number = id; else { slot_info[id].slot_number = sinfo[id].slot_number; slot_info[id].present = sinfo[id].present; slot_info[id].pk_slot.flags = sinfo[id].pk_slot.flags; memcpy(slot_info[id].dll_location, sinfo[id].dll_location, strlen(sinfo[id].dll_location)); memcpy(slot_info[id].confname, sinfo[id].confname, strlen(sinfo[id].confname)); /* pkcs#11v2.20 says these should be padded with * spaces and NOT null terminated. */ memset(slot_info[id].pk_slot.slotDescription, ' ', sizeof(slot_info[id].pk_slot.slotDescription)); memset(slot_info[id].pk_slot.manufacturerID, ' ', sizeof(slot_info[id].pk_slot.manufacturerID)); memcpy(slot_info[id].pk_slot.slotDescription, sinfo[id].pk_slot.slotDescription, sizeof(sinfo[id].pk_slot.slotDescription)); memcpy(slot_info[id].pk_slot.manufacturerID, sinfo[id].pk_slot.manufacturerID, sizeof(sinfo[id].pk_slot.manufacturerID)); memcpy(&slot_info[id].pk_slot.hardwareVersion, &sinfo[id].pk_slot.hardwareVersion, sizeof(sinfo[id].pk_slot.hardwareVersion)); memcpy(&slot_info[id].pk_slot.firmwareVersion, &sinfo[id].pk_slot.firmwareVersion, sizeof(sinfo[id].pk_slot.firmwareVersion)); slot_count++; } } *processed = slot_count; } opencryptoki+dfsg/usr/sbin/pkcsslotd/signal.c0000755000175000017500000004627612630407154020514 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include "log.h" #include "slotmgr.h" #include "pkcsslotd.h" #include "err.h" extern BOOL IsValidProcessEntry ( pid_t_64 pid, time_t_64 RegTime ); static int SigsToIntercept[] = { SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU, SIGUSR1, SIGUSR2, SIGPROF }; /* SIGCONT - Don't want to exit on SIGCONT; it'll in fact mask other signals - kill -HUP actually sends SIGCONT before SIGHUP */ /* SIGCHLD - Don't want to exit. Should never receive, but we do, apparently when something tries to cancel the GC Thread */ static int SigsToIgnore[] = { SIGCHLD, }; /************************************************** * slotdGenericSignalHandler * * Main signal handler for the daemon. Doesn't * allow the daemon to be killed unless we're * not in use ***************************************************/ void slotdGenericSignalHandler( int Signal ) { int procindex; BOOL OkToExit = TRUE; /******************************************************** * DbgLog calls (possibly) printf, syslog_r, etc. * The behavior of these functions is "undefined" * when called from a signal handler according to * the sigaction man page. * * Thus, they're only called in development * versions of the code. ********************************************************/ #ifdef DEV DbgLog(DL2, "slotdGenericSignalHandler got %s (%d; %#x)", SignalConst(Signal), Signal, Signal); #endif /* DEV */ #if !defined(NOGARBAGE) StopGCThread(shmp); CheckForGarbage(shmp); #endif for ( procindex = 0; (procindex < NUMBER_PROCESSES_ALLOWED); procindex++ ) { Slot_Mgr_Proc_t_64 *pProc = &(shmp->proc_table[procindex]); if ( shmp == NULL ) { break; } if ( ( pProc->inuse ) #if !(NOGARBAGE) && ( IsValidProcessEntry( pProc->proc_id, pProc->reg_time)) #endif ) { /* Someone's still using us... Log it */ OkToExit = FALSE; #ifdef DEV WarnLog("Process %d is still registered", pProc->proc_id); #endif } } if ( !OkToExit ) { DbgLog(DL1,"Continuing execution"); #if !defined(NOGARBAGE) StartGCThread(shmp); #endif return; } InfoLog("Exiting on %s (%d; %#x)", SignalConst(Signal), Signal, Signal); DetachSocketListener(socketfd); DestroyMutexes(); DetachFromSharedMemory(); DestroySharedMemory(); exit(0); } /*************************************************** * SetupSignalHandlers - * * Installs slotdGenericSignalHandler for the listed signals * ***************************************************/ int SetupSignalHandlers ( void ) { unsigned int i; struct sigaction new_action; new_action.sa_handler = slotdGenericSignalHandler; sigemptyset(&(new_action.sa_mask)); sigaddset(&(new_action.sa_mask), SIGCHLD); /* sigaddset(&(new_action.sa_mask), SA_NOCLDWAIT); */ /* sigaddset(&(new_action.sa_mask), SA_NOCLDSTOP); */ new_action.sa_flags = (RESTART_SYS_CALLS ? SA_RESTART : 0); for ( i = 0; i < (sizeof(SigsToIntercept) / sizeof(SigsToIntercept[0])); i++ ) { if ( sigaction ( SigsToIntercept[i], &new_action, NULL ) != 0 ) { //DbgLog("SetupSignalHandlers - sigaction failed for %s (%d; %#x)", SignalConst(SigsToIntercept[i]), SigsToIntercept[i], SigsToIntercept[i]); return FALSE; } } new_action.sa_handler = SIG_IGN; sigemptyset(&(new_action.sa_mask)); for ( i = 0; i < (sizeof ( SigsToIgnore ) / sizeof (SigsToIgnore[0]) ); i++ ) { if ( sigaction ( SigsToIgnore[i], &new_action, NULL ) != 0 ) { //DbgLog ( "Failed to ignore signal."); return FALSE; } } return TRUE; } /*********************************************************************** * GCBlockSignals - * * Garbage collector calls this to prevent signals from getting * sent to the GC thread. * ***********************************************************************/ BOOL GCBlockSignals (void) { unsigned int i; int ret; sigset_t SigSet; sigemptyset(&SigSet); for ( i = 0; i < (sizeof(SigsToIntercept) / sizeof(SigsToIntercept[0]) ); i++ ) { sigaddset(&SigSet, SigsToIntercept[i]); } ret = pthread_sigmask(SIG_SETMASK, &SigSet, NULL); return ret; } opencryptoki+dfsg/usr/sbin/pkcsslotd/err.h0000755000175000017500000004372512630407154020030 0ustar xnoxxnox/* * $Header: /cvsroot/opencryptoki/opencryptoki/usr/sbin/pkcsslotd/err.h,v 1.3 2006/04/05 20:07:48 kyoder Exp $ */ /* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #ifndef _SLOTD_ERR_H #define _SLOTD_ERR_H #ifdef DEV #ifndef ASSERT #define ASSERT(_expr) _ASSERT((_expr),(__FILE__),(__LINE__)) #define _ASSERT(_expr, _fname, _line) \ if (!(_expr)) { \ ErrLog("****** ****** ***** ***** ***** ***** ***** ***** ***** ****** ******"); \ ErrLog("****** ASSERTION FAILED '%s'; %s, line %d", (#_expr), (_fname), (_line)); \ ErrLog("****** ****** ***** ***** ***** ***** ***** ***** ***** ****** ******"); \ ErrLog("Exiting."); \ abort(); \ } #endif /* ASSERT */ #ifndef ASSERT_FUNC #define ASSERT_FUNC(_expr, _func) _ASSERT_FUNC((_expr), (_func), (__FILE__), (__LINE__)) #define _ASSERT_FUNC(_expr, _func, _fname, _line) \ if (!(_expr)) { \ ErrLog("****** ****** ***** ***** ***** ***** ***** ***** ***** ****** ******"); \ ErrLog("****** ASSERTION FAILED '%s'; %s, line %d", (#_expr), (_fname), (_line)); \ ErrLog("Additional information from '%s':\n", (#_func)); \ { _func; } \ ErrLog("End of additional information from '%s'\n", (#_func) ); \ ErrLog("****** ****** ***** ***** ***** ***** ***** ***** ***** ****** ******"); \ ErrLog("Exiting."); \ abort(); \ } #endif /* ASSERT_FUNC */ #else #ifndef ASSERT #define ASSERT(_expr) #endif /* ASSERT */ #ifndef ASSERT_FUNC #define ASSERT_FUNC(_expr, _func_to_call) #endif /* ASSERT_FUNC */ #endif /* DEV */ #define SEV_EXPECTED 0x01 #define SEV_ALLOWED 0x02 #define SEV_ERROR 0x03 #define SEV_FATAL 0x04 typedef struct _ConstInfo { unsigned const int Code; unsigned const char Name[128]; /* UCHAR Descrip[256]; */ } ConstInfo, *pConstInfo; #define CONSTINFO(_X) { (_X), (#_X) } const unsigned char *ConstName ( pConstInfo pInfoArray, unsigned int InfoArraySize, unsigned int ConstValue ); #ifdef _DAE_H const unsigned char *DAEConst ( unsigned int Val ); #endif /* _DAE_H */ #ifndef _H_ERRNO #define _H_ERRNO #endif #ifdef _H_ERRNO extern const unsigned char *SysConst ( unsigned int Val ); #define SysError( _x ) SysConst((_x)) #endif /* _H_ERRNO */ extern const unsigned char *SignalConst ( unsigned int Val ); #ifdef _H_ODMI const unsigned char *ODMConst ( unsigned int Val ); #endif /* _H_ODMI */ #ifdef _PKCS11TYPES_H_ const unsigned char *PkcsReturn ( unsigned int Val ); const unsigned char *PkcsFlags ( unsigned int Val ); const unsigned char *PkcsMechanism ( unsigned int Val ); const unsigned char *PkcsObject ( unsigned int Val ); const unsigned char *PkcsKey ( unsigned int Val ); const unsigned char *PkcsAttribute ( unsigned int Val ); #endif /* _PKCS11TYPES_H_ */ const unsigned char *ResponseSeverity( unsigned int Val ); #endif /* _SLOTD_ERR_H */ opencryptoki+dfsg/usr/sbin/pkcsslotd/err.c0000755000175000017500000010057612630407154020021 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include "log.h" #include "slotmgr.h" #include "err.h" static ConstInfo SysErrorInfo[] = { CONSTINFO(EPERM), CONSTINFO(ENOENT), CONSTINFO(ESRCH), CONSTINFO(EINTR), CONSTINFO(EIO), CONSTINFO(ENXIO), CONSTINFO(E2BIG), CONSTINFO(ENOEXEC), CONSTINFO(EBADF), CONSTINFO(ECHILD), CONSTINFO(EAGAIN), CONSTINFO(ENOMEM), CONSTINFO(EACCES), CONSTINFO(EFAULT), CONSTINFO(ENOTBLK), CONSTINFO(EBUSY), CONSTINFO(EEXIST), CONSTINFO(EXDEV), CONSTINFO(ENODEV), CONSTINFO(ENOTDIR), CONSTINFO(EISDIR), CONSTINFO(EINVAL), CONSTINFO(ENFILE), CONSTINFO(EMFILE), CONSTINFO(ENOTTY), CONSTINFO(ETXTBSY), CONSTINFO(EFBIG), CONSTINFO(ENOSPC), CONSTINFO(ESPIPE), CONSTINFO(EROFS), CONSTINFO(EMLINK), CONSTINFO(EPIPE), CONSTINFO(EDOM), CONSTINFO(ERANGE), CONSTINFO(ENOMSG), CONSTINFO(EIDRM), #ifdef ECHRNG CONSTINFO(ECHRNG), #endif #ifdef EL2NSYNC CONSTINFO(EL2NSYNC), #endif #ifdef EL3HLT CONSTINFO(EL3HLT), #endif #ifdef EL3RST CONSTINFO(EL3RST), #endif #ifdef ELNRNG CONSTINFO(ELNRNG), #endif #ifdef EUNATCH CONSTINFO(EUNATCH), #endif #ifdef ENOCSI CONSTINFO(ENOCSI), #endif #ifdef EL2HLT CONSTINFO(EL2HLT), #endif CONSTINFO(EDEADLK), CONSTINFO(ESTALE), CONSTINFO(EWOULDBLOCK), CONSTINFO(EINPROGRESS), CONSTINFO(EALREADY), CONSTINFO(ENOTSOCK), CONSTINFO(EDESTADDRREQ), CONSTINFO(EMSGSIZE), CONSTINFO(EPROTOTYPE), CONSTINFO(ENOPROTOOPT), CONSTINFO(EPROTONOSUPPORT), CONSTINFO(ESOCKTNOSUPPORT), CONSTINFO(EOPNOTSUPP), CONSTINFO(EPFNOSUPPORT), CONSTINFO(EAFNOSUPPORT), CONSTINFO(EADDRINUSE), CONSTINFO(EADDRNOTAVAIL), CONSTINFO(ENETDOWN), CONSTINFO(ENETUNREACH), CONSTINFO(ENETRESET), CONSTINFO(ECONNABORTED), CONSTINFO(ECONNRESET), CONSTINFO(ENOBUFS), CONSTINFO(EISCONN), CONSTINFO(ENOTCONN), CONSTINFO(ESHUTDOWN), CONSTINFO(ETIMEDOUT), CONSTINFO(ECONNREFUSED), CONSTINFO(EHOSTDOWN), CONSTINFO(EHOSTUNREACH), #ifdef ERESTART CONSTINFO(ERESTART), #endif CONSTINFO(EUSERS), CONSTINFO(ELOOP), CONSTINFO(ENAMETOOLONG), CONSTINFO(ENOTEMPTY), CONSTINFO(EDQUOT), CONSTINFO(EREMOTE), CONSTINFO(ENOSYS), CONSTINFO(ETOOMANYREFS), CONSTINFO(EILSEQ), CONSTINFO(ECANCELED), #ifdef ENOSR CONSTINFO(ENOSR), #endif #ifdef ETIME CONSTINFO(ETIME), #endif #ifdef EBADMSG CONSTINFO(EBADMSG), #endif #ifdef EPROTO CONSTINFO(EPROTO), #endif #ifdef ENODATA CONSTINFO(ENODATA), #endif #ifdef ENOSTR CONSTINFO(ENOSTR), #endif CONSTINFO(ENOTSUP), #ifdef EMULTIHOP CONSTINFO(EMULTIHOP), #endif #ifdef ENOLINK CONSTINFO(ENOLINK), #endif #ifdef EOVERFLOW CONSTINFO(EOVERFLOW), #endif }; static int SysErrorSize = ( sizeof(SysErrorInfo) / sizeof(SysErrorInfo[0])); static ConstInfo SignalInfo[] = { CONSTINFO(SIGHUP), CONSTINFO(SIGINT), CONSTINFO(SIGQUIT), CONSTINFO(SIGILL), CONSTINFO(SIGTRAP), CONSTINFO(SIGABRT), CONSTINFO(SIGFPE), CONSTINFO(SIGKILL), CONSTINFO(SIGBUS), CONSTINFO(SIGSEGV), CONSTINFO(SIGSYS), CONSTINFO(SIGPIPE), CONSTINFO(SIGALRM), CONSTINFO(SIGTERM), CONSTINFO(SIGURG), CONSTINFO(SIGSTOP), CONSTINFO(SIGTSTP), CONSTINFO(SIGCONT), CONSTINFO(SIGCHLD), CONSTINFO(SIGTTIN), CONSTINFO(SIGTTOU), CONSTINFO(SIGIO), CONSTINFO(SIGXCPU), CONSTINFO(SIGXFSZ), CONSTINFO(SIGWINCH), #ifdef SIGPWR CONSTINFO(SIGPWR), #endif CONSTINFO(SIGUSR1), CONSTINFO(SIGUSR2), CONSTINFO(SIGPROF), CONSTINFO(SIGVTALRM), CONSTINFO(SIGIOT), #ifdef SIGCLD CONSTINFO(SIGCLD), #endif #ifdef SIGPOLL CONSTINFO(SIGPOLL), #endif #if 0 CONSTINFO(SIG_DFL), CONSTINFO(SIG_IGN), CONSTINFO(SIG_HOLD), CONSTINFO(SIG_CATCH), CONSTINFO(SIG_ERR), #endif /* 0 */ }; static int SignalInfoSize = (sizeof(SignalInfo) / sizeof(SignalInfo[0])); static ConstInfo PkcsReturnInfo[] = { CONSTINFO(CKR_OK), CONSTINFO(CKR_CANCEL), CONSTINFO(CKR_HOST_MEMORY), CONSTINFO(CKR_SLOT_ID_INVALID), CONSTINFO(CKR_GENERAL_ERROR), CONSTINFO(CKR_FUNCTION_FAILED), CONSTINFO(CKR_ARGUMENTS_BAD), CONSTINFO(CKR_NO_EVENT), CONSTINFO(CKR_NEED_TO_CREATE_THREADS), CONSTINFO(CKR_CANT_LOCK), CONSTINFO(CKR_ATTRIBUTE_READ_ONLY), CONSTINFO(CKR_ATTRIBUTE_SENSITIVE), CONSTINFO(CKR_ATTRIBUTE_TYPE_INVALID), CONSTINFO(CKR_ATTRIBUTE_VALUE_INVALID), CONSTINFO(CKR_DATA_INVALID), CONSTINFO(CKR_DATA_LEN_RANGE), CONSTINFO(CKR_DEVICE_ERROR), CONSTINFO(CKR_DEVICE_MEMORY), CONSTINFO(CKR_DEVICE_REMOVED), CONSTINFO(CKR_ENCRYPTED_DATA_INVALID), CONSTINFO(CKR_ENCRYPTED_DATA_LEN_RANGE), CONSTINFO(CKR_FUNCTION_CANCELED), CONSTINFO(CKR_FUNCTION_NOT_PARALLEL), CONSTINFO(CKR_FUNCTION_NOT_SUPPORTED), CONSTINFO(CKR_KEY_HANDLE_INVALID), CONSTINFO(CKR_KEY_SIZE_RANGE), CONSTINFO(CKR_KEY_TYPE_INCONSISTENT), CONSTINFO(CKR_KEY_NOT_NEEDED), CONSTINFO(CKR_KEY_CHANGED), CONSTINFO(CKR_KEY_NEEDED), CONSTINFO(CKR_KEY_INDIGESTIBLE), CONSTINFO(CKR_KEY_FUNCTION_NOT_PERMITTED), CONSTINFO(CKR_KEY_NOT_WRAPPABLE), CONSTINFO(CKR_KEY_UNEXTRACTABLE), CONSTINFO(CKR_MECHANISM_INVALID), CONSTINFO(CKR_MECHANISM_PARAM_INVALID), CONSTINFO(CKR_OBJECT_HANDLE_INVALID), CONSTINFO(CKR_OPERATION_ACTIVE), CONSTINFO(CKR_OPERATION_NOT_INITIALIZED), CONSTINFO(CKR_PIN_INCORRECT), CONSTINFO(CKR_PIN_INVALID), CONSTINFO(CKR_PIN_LEN_RANGE), CONSTINFO(CKR_PIN_EXPIRED), CONSTINFO(CKR_PIN_LOCKED), CONSTINFO(CKR_SESSION_CLOSED), CONSTINFO(CKR_SESSION_COUNT), CONSTINFO(CKR_SESSION_HANDLE_INVALID), CONSTINFO(CKR_SESSION_PARALLEL_NOT_SUPPORTED), CONSTINFO(CKR_SESSION_READ_ONLY), CONSTINFO(CKR_SESSION_EXISTS), CONSTINFO(CKR_SESSION_READ_ONLY_EXISTS), CONSTINFO(CKR_SESSION_READ_WRITE_SO_EXISTS), CONSTINFO(CKR_SIGNATURE_INVALID), CONSTINFO(CKR_SIGNATURE_LEN_RANGE), CONSTINFO(CKR_TEMPLATE_INCOMPLETE), CONSTINFO(CKR_TEMPLATE_INCONSISTENT), CONSTINFO(CKR_TOKEN_NOT_PRESENT), CONSTINFO(CKR_TOKEN_NOT_RECOGNIZED), CONSTINFO(CKR_TOKEN_WRITE_PROTECTED), CONSTINFO(CKR_UNWRAPPING_KEY_HANDLE_INVALID), CONSTINFO(CKR_UNWRAPPING_KEY_SIZE_RANGE), CONSTINFO(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT), CONSTINFO(CKR_USER_ALREADY_LOGGED_IN), CONSTINFO(CKR_USER_NOT_LOGGED_IN), CONSTINFO(CKR_USER_PIN_NOT_INITIALIZED), CONSTINFO(CKR_USER_TYPE_INVALID), CONSTINFO(CKR_USER_ANOTHER_ALREADY_LOGGED_IN), CONSTINFO(CKR_USER_TOO_MANY_TYPES), CONSTINFO(CKR_WRAPPED_KEY_INVALID), CONSTINFO(CKR_WRAPPED_KEY_LEN_RANGE), CONSTINFO(CKR_WRAPPING_KEY_HANDLE_INVALID), CONSTINFO(CKR_WRAPPING_KEY_SIZE_RANGE), CONSTINFO(CKR_WRAPPING_KEY_TYPE_INCONSISTENT), CONSTINFO(CKR_RANDOM_SEED_NOT_SUPPORTED), CONSTINFO(CKR_RANDOM_NO_RNG), CONSTINFO(CKR_BUFFER_TOO_SMALL), CONSTINFO(CKR_SAVED_STATE_INVALID), CONSTINFO(CKR_INFORMATION_SENSITIVE), CONSTINFO(CKR_STATE_UNSAVEABLE), CONSTINFO(CKR_CRYPTOKI_NOT_INITIALIZED), CONSTINFO(CKR_CRYPTOKI_ALREADY_INITIALIZED), CONSTINFO(CKR_MUTEX_BAD), CONSTINFO(CKR_MUTEX_NOT_LOCKED), CONSTINFO(CKR_VENDOR_DEFINED), }; static int PkcsReturnSize = ( sizeof(PkcsReturnInfo) / sizeof(PkcsReturnInfo[0]) ); static ConstInfo PkcsFlagsInfo[] = { CONSTINFO( ( CKF_RNG | CKF_HW | CKF_LIBRARY_CANT_CREATE_OS_THREADS | CKF_TOKEN_PRESENT )), CONSTINFO( ( CKF_REMOVABLE_DEVICE | CKF_OS_LOCKING_OK | CKF_RW_SESSION | CKF_WRITE_PROTECTED )), CONSTINFO( ( CKF_SERIAL_SESSION | CKF_HW_SLOT | CKF_LOGIN_REQUIRED )), CONSTINFO( CKF_USER_PIN_INITIALIZED ), CONSTINFO( CKF_RESTORE_KEY_NOT_NEEDED ), CONSTINFO( CKF_CLOCK_ON_TOKEN), CONSTINFO( ( CKF_PROTECTED_AUTHENTICATION_PATH | CKF_ENCRYPT )), CONSTINFO( ( CKF_DUAL_CRYPTO_OPERATIONS | CKF_DECRYPT )), CONSTINFO(CKF_DIGEST), CONSTINFO(CKF_SIGN), CONSTINFO(CKF_SIGN_RECOVER), CONSTINFO(CKF_VERIFY), CONSTINFO(CKF_VERIFY_RECOVER), CONSTINFO(CKF_GENERATE), CONSTINFO( ( CKF_GENERATE_KEY_PAIR | CKF_USER_PIN_COUNT_LOW )), CONSTINFO( ( CKF_USER_PIN_FINAL_TRY| CKF_WRAP )), CONSTINFO( ( CKF_UNWRAP | CKF_USER_PIN_LOCKED )), CONSTINFO( ( CKF_DERIVE /*| CKF_USER_PIN_MANUFACT_VALUE*/ )), CONSTINFO(CKF_SO_PIN_DERIVED), CONSTINFO(CKF_SO_CARD), CONSTINFO(CKF_SO_PIN_COUNT_LOW), CONSTINFO(CKF_SO_PIN_FINAL_TRY), CONSTINFO(CKF_SO_PIN_LOCKED), /*CONSTINFO(CKF_SO_PIN_MANUFACT_VALUE),*/ CONSTINFO(CKF_EXTENSION), }; static int PkcsFlagsSize = ( sizeof(PkcsFlagsInfo) / sizeof(PkcsFlagsInfo[0])); static ConstInfo PkcsMechanismInfo[] = { CONSTINFO(CKM_RSA_PKCS_KEY_PAIR_GEN), CONSTINFO(CKM_RSA_PKCS), CONSTINFO(CKM_RSA_9796), CONSTINFO(CKM_RSA_X_509), CONSTINFO(CKM_MD2_RSA_PKCS), CONSTINFO(CKM_MD5_RSA_PKCS), CONSTINFO(CKM_SHA1_RSA_PKCS), CONSTINFO(CKM_DSA_KEY_PAIR_GEN), CONSTINFO(CKM_DSA), CONSTINFO(CKM_DSA_SHA1), CONSTINFO(CKM_DH_PKCS_KEY_PAIR_GEN), CONSTINFO(CKM_DH_PKCS_DERIVE), CONSTINFO(CKM_RC2_KEY_GEN), CONSTINFO(CKM_RC2_ECB), CONSTINFO(CKM_RC2_CBC), CONSTINFO(CKM_RC2_MAC), CONSTINFO(CKM_RC2_MAC_GENERAL), CONSTINFO(CKM_RC2_CBC_PAD), CONSTINFO(CKM_RC4_KEY_GEN), CONSTINFO(CKM_RC4), CONSTINFO(CKM_DES_KEY_GEN), CONSTINFO(CKM_DES_ECB), CONSTINFO(CKM_DES_CBC), CONSTINFO(CKM_DES_MAC), CONSTINFO(CKM_DES_MAC_GENERAL), CONSTINFO(CKM_DES_CBC_PAD), CONSTINFO(CKM_DES2_KEY_GEN), CONSTINFO(CKM_DES3_KEY_GEN), CONSTINFO(CKM_DES3_ECB), CONSTINFO(CKM_DES3_CBC), CONSTINFO(CKM_DES3_MAC), CONSTINFO(CKM_DES3_MAC_GENERAL), CONSTINFO(CKM_DES3_CBC_PAD), CONSTINFO(CKM_CDMF_KEY_GEN), CONSTINFO(CKM_CDMF_ECB), CONSTINFO(CKM_CDMF_CBC), CONSTINFO(CKM_CDMF_MAC), CONSTINFO(CKM_CDMF_MAC_GENERAL), CONSTINFO(CKM_CDMF_CBC_PAD), CONSTINFO(CKM_MD2), CONSTINFO(CKM_MD2_HMAC), CONSTINFO(CKM_MD2_HMAC_GENERAL), CONSTINFO(CKM_MD5), CONSTINFO(CKM_MD5_HMAC), CONSTINFO(CKM_MD5_HMAC_GENERAL), CONSTINFO(CKM_SHA_1), CONSTINFO(CKM_SHA_1_HMAC), CONSTINFO(CKM_SHA_1_HMAC_GENERAL), CONSTINFO(CKM_CAST_KEY_GEN), CONSTINFO(CKM_CAST_ECB), CONSTINFO(CKM_CAST_CBC), CONSTINFO(CKM_CAST_MAC), CONSTINFO(CKM_CAST_MAC_GENERAL), CONSTINFO(CKM_CAST_CBC_PAD), CONSTINFO(CKM_CAST3_KEY_GEN), CONSTINFO(CKM_CAST3_ECB), CONSTINFO(CKM_CAST3_CBC), CONSTINFO(CKM_CAST3_MAC), CONSTINFO(CKM_CAST3_MAC_GENERAL), CONSTINFO(CKM_CAST3_CBC_PAD), CONSTINFO(CKM_CAST5_KEY_GEN), CONSTINFO(CKM_CAST128_KEY_GEN), CONSTINFO(CKM_CAST5_ECB), CONSTINFO(CKM_CAST128_ECB), CONSTINFO(CKM_CAST5_CBC), CONSTINFO(CKM_CAST128_CBC), CONSTINFO(CKM_CAST5_MAC), CONSTINFO(CKM_CAST128_MAC), CONSTINFO(CKM_CAST5_MAC_GENERAL), CONSTINFO(CKM_CAST128_MAC_GENERAL), CONSTINFO(CKM_CAST5_CBC_PAD), CONSTINFO(CKM_CAST128_CBC_PAD), CONSTINFO(CKM_RC5_KEY_GEN), CONSTINFO(CKM_RC5_ECB), CONSTINFO(CKM_RC5_CBC), CONSTINFO(CKM_RC5_MAC), CONSTINFO(CKM_RC5_MAC_GENERAL), CONSTINFO(CKM_RC5_CBC_PAD), CONSTINFO(CKM_IDEA_KEY_GEN), CONSTINFO(CKM_IDEA_ECB), CONSTINFO(CKM_IDEA_CBC), CONSTINFO(CKM_IDEA_MAC), CONSTINFO(CKM_IDEA_MAC_GENERAL), CONSTINFO(CKM_IDEA_CBC_PAD), CONSTINFO(CKM_GENERIC_SECRET_KEY_GEN), CONSTINFO(CKM_CONCATENATE_BASE_AND_KEY), CONSTINFO(CKM_CONCATENATE_BASE_AND_DATA), CONSTINFO(CKM_CONCATENATE_DATA_AND_BASE), CONSTINFO(CKM_XOR_BASE_AND_DATA), CONSTINFO(CKM_EXTRACT_KEY_FROM_KEY), CONSTINFO(CKM_SSL3_PRE_MASTER_KEY_GEN), CONSTINFO(CKM_SSL3_MASTER_KEY_DERIVE), CONSTINFO(CKM_SSL3_KEY_AND_MAC_DERIVE), CONSTINFO(CKM_SSL3_MD5_MAC), CONSTINFO(CKM_SSL3_SHA1_MAC), CONSTINFO(CKM_MD5_KEY_DERIVATION), CONSTINFO(CKM_MD2_KEY_DERIVATION), CONSTINFO(CKM_SHA1_KEY_DERIVATION), CONSTINFO(CKM_PBE_MD2_DES_CBC), CONSTINFO(CKM_PBE_MD5_DES_CBC), CONSTINFO(CKM_PBE_MD5_CAST_CBC), CONSTINFO(CKM_PBE_MD5_CAST3_CBC), CONSTINFO(CKM_PBE_MD5_CAST5_CBC), CONSTINFO(CKM_PBE_MD5_CAST128_CBC), CONSTINFO(CKM_PBE_SHA1_CAST5_CBC), CONSTINFO(CKM_PBE_SHA1_CAST128_CBC), CONSTINFO(CKM_PBE_SHA1_RC4_128), CONSTINFO(CKM_PBE_SHA1_RC4_40), CONSTINFO(CKM_PBE_SHA1_DES3_EDE_CBC), CONSTINFO(CKM_PBE_SHA1_DES2_EDE_CBC), CONSTINFO(CKM_PBE_SHA1_RC2_128_CBC), CONSTINFO(CKM_PBE_SHA1_RC2_40_CBC), CONSTINFO(CKM_PBA_SHA1_WITH_SHA1_HMAC), CONSTINFO(CKM_KEY_WRAP_LYNKS), CONSTINFO(CKM_KEY_WRAP_SET_OAEP), CONSTINFO(CKM_SKIPJACK_KEY_GEN), CONSTINFO(CKM_SKIPJACK_ECB64), CONSTINFO(CKM_SKIPJACK_CBC64), CONSTINFO(CKM_SKIPJACK_OFB64), CONSTINFO(CKM_SKIPJACK_CFB64), CONSTINFO(CKM_SKIPJACK_CFB32), CONSTINFO(CKM_SKIPJACK_CFB16), CONSTINFO(CKM_SKIPJACK_CFB8), CONSTINFO(CKM_SKIPJACK_WRAP), CONSTINFO(CKM_SKIPJACK_PRIVATE_WRAP), CONSTINFO(CKM_SKIPJACK_RELAYX), CONSTINFO(CKM_KEA_KEY_PAIR_GEN), CONSTINFO(CKM_KEA_KEY_DERIVE), CONSTINFO(CKM_FORTEZZA_TIMESTAMP), CONSTINFO(CKM_BATON_KEY_GEN), CONSTINFO(CKM_BATON_ECB128), CONSTINFO(CKM_BATON_ECB96), CONSTINFO(CKM_BATON_CBC128), CONSTINFO(CKM_BATON_COUNTER), CONSTINFO(CKM_BATON_SHUFFLE), CONSTINFO(CKM_BATON_WRAP), CONSTINFO(CKM_ECDSA_KEY_PAIR_GEN), CONSTINFO(CKM_ECDSA), CONSTINFO(CKM_ECDSA_SHA1), CONSTINFO(CKM_JUNIPER_KEY_GEN), CONSTINFO(CKM_JUNIPER_ECB128), CONSTINFO(CKM_JUNIPER_CBC128), CONSTINFO(CKM_JUNIPER_COUNTER), CONSTINFO(CKM_JUNIPER_SHUFFLE), CONSTINFO(CKM_JUNIPER_WRAP), CONSTINFO(CKM_FASTHASH), CONSTINFO(CKM_VENDOR_DEFINED), }; static unsigned int PkcsMechanismSize = (sizeof(PkcsMechanismInfo) / sizeof(PkcsMechanismInfo[0])); static ConstInfo PkcsObjectInfo[] = { CONSTINFO(CKO_DATA), CONSTINFO(CKO_CERTIFICATE), CONSTINFO(CKO_PUBLIC_KEY), CONSTINFO(CKO_PRIVATE_KEY), CONSTINFO(CKO_SECRET_KEY), CONSTINFO(CKO_VENDOR_DEFINED), }; static unsigned int PkcsObjectSize = (sizeof(PkcsObjectInfo) / sizeof(PkcsObjectInfo[0])); static ConstInfo PkcsKeyInfo[] = { CONSTINFO(CKK_RSA), CONSTINFO(CKK_DSA), CONSTINFO(CKK_DH), CONSTINFO(CKK_ECDSA), CONSTINFO(CKK_KEA), CONSTINFO(CKK_GENERIC_SECRET), CONSTINFO(CKK_RC2), CONSTINFO(CKK_RC4), CONSTINFO(CKK_DES), CONSTINFO(CKK_DES2), CONSTINFO(CKK_DES3), CONSTINFO(CKK_CAST), CONSTINFO(CKK_CAST3), CONSTINFO( (CKK_CAST5 | CKK_CAST128 )), CONSTINFO(CKK_RC5), CONSTINFO(CKK_IDEA), CONSTINFO(CKK_SKIPJACK), CONSTINFO(CKK_BATON), CONSTINFO(CKK_JUNIPER), CONSTINFO(CKK_CDMF), CONSTINFO(CKK_VENDOR_DEFINED), }; static unsigned int PkcsKeySize = ( sizeof(PkcsKeyInfo) / sizeof(PkcsKeyInfo[0]) ); static ConstInfo PkcsAttributeInfo[] = { CONSTINFO(CKA_CLASS), CONSTINFO(CKA_TOKEN), CONSTINFO(CKA_PRIVATE), CONSTINFO(CKA_LABEL), CONSTINFO(CKA_APPLICATION), CONSTINFO(CKA_VALUE), CONSTINFO(CKA_CERTIFICATE_TYPE), CONSTINFO(CKA_ISSUER), CONSTINFO(CKA_SERIAL_NUMBER), CONSTINFO(CKA_KEY_TYPE), CONSTINFO(CKA_SUBJECT), CONSTINFO(CKA_ID), CONSTINFO(CKA_SENSITIVE), CONSTINFO(CKA_ENCRYPT), CONSTINFO(CKA_DECRYPT), CONSTINFO(CKA_WRAP), CONSTINFO(CKA_UNWRAP), CONSTINFO(CKA_SIGN), CONSTINFO(CKA_SIGN_RECOVER), CONSTINFO(CKA_VERIFY), CONSTINFO(CKA_VERIFY_RECOVER), CONSTINFO(CKA_DERIVE), CONSTINFO(CKA_START_DATE), CONSTINFO(CKA_END_DATE), CONSTINFO(CKA_MODULUS), CONSTINFO(CKA_MODULUS_BITS), CONSTINFO(CKA_PUBLIC_EXPONENT), CONSTINFO(CKA_PRIVATE_EXPONENT), CONSTINFO(CKA_PRIME_1), CONSTINFO(CKA_PRIME_2), CONSTINFO(CKA_EXPONENT_1), CONSTINFO(CKA_EXPONENT_2), CONSTINFO(CKA_COEFFICIENT), CONSTINFO(CKA_PRIME), CONSTINFO(CKA_SUBPRIME), CONSTINFO(CKA_BASE), CONSTINFO(CKA_VALUE_BITS), CONSTINFO(CKA_VALUE_LEN), CONSTINFO(CKA_EXTRACTABLE), CONSTINFO(CKA_LOCAL), CONSTINFO(CKA_NEVER_EXTRACTABLE), CONSTINFO(CKA_ALWAYS_SENSITIVE), CONSTINFO(CKA_MODIFIABLE), CONSTINFO(CKA_ECDSA_PARAMS), CONSTINFO(CKA_EC_POINT), CONSTINFO(CKA_VENDOR_DEFINED), }; static unsigned int PkcsAttributeSize = ( sizeof(PkcsAttributeInfo) / sizeof(PkcsAttributeInfo[0]) ); #if 0 static ConstInfo PkcsSessionStateInfo[] = { CONSTINFO(CKS_RO_PUBLIC_SESSION), CONSTINFO(CKS_RO_USER_FUNCTIONS), CONSTINFO(CKS_RW_PUBLIC_SESSION), CONSTINFO(CKS_RW_USER_FUNCTIONS), CONSTINFO(CKS_RW_SO_FUNCTIONS), }; #endif static ConstInfo PkcsResponseSeverityInfo[] = { { SEV_EXPECTED, "expected" }, { SEV_ALLOWED, "allowed" }, { SEV_ERROR, "an error" }, { SEV_FATAL, "fatal" }, }; static unsigned int PkcsResponseSeveritySize = ( sizeof(PkcsResponseSeverityInfo) / sizeof(PkcsResponseSeverityInfo[0]) ); const unsigned char *ConstName( pConstInfo pInfoArray, unsigned int InfoArraySize, unsigned int ConstValue ) { unsigned int i; unsigned const char *retval = NULL; for ( i = 0; i < InfoArraySize; i++ ) { if ( pInfoArray[i].Code == ConstValue ) { retval = &(pInfoArray[i].Name[0]); break; } /* end if */ } /* end for i */ if ( retval == NULL ) { if ( ConstValue == 0 ) { retval = (const unsigned char *) "NULL"; } else { retval = (const unsigned char *) "\"<*>CONSTANT NOT FOUND<*>\""; } } return retval; } const unsigned char *SignalConst ( unsigned int Val ) { return ConstName ( SignalInfo, SignalInfoSize, Val ); } const unsigned char *SysConst ( unsigned int Val ) { return ConstName ( SysErrorInfo, SysErrorSize, Val ); } const unsigned char *PkcsReturn ( unsigned int Val ) { return ConstName( PkcsReturnInfo, PkcsReturnSize, Val ); } const unsigned char *PkcsFlags ( unsigned int Val ) { return ConstName( PkcsFlagsInfo, PkcsFlagsSize, Val ); } const unsigned char *PkcsMechanism ( unsigned int Val) { return ConstName(PkcsMechanismInfo, PkcsMechanismSize, Val); } const unsigned char *PkcsObject ( unsigned int Val ) { return ConstName ( PkcsObjectInfo, PkcsObjectSize, Val ); } const unsigned char *PkcsKey ( unsigned int Val ) { return ConstName( PkcsKeyInfo, PkcsKeySize, Val); } const unsigned char *PkcsAttribute ( unsigned int Val ) { return ConstName ( PkcsAttributeInfo, PkcsAttributeSize, Val); } const unsigned char *ResponseSeverity( unsigned int Val ) { return ConstName ( PkcsResponseSeverityInfo, PkcsResponseSeveritySize, Val); } opencryptoki+dfsg/usr/sbin/pkcsslotd/daemon.c0000755000175000017500000004233612630407154020473 0ustar xnoxxnox/* Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /* (C) COPYRIGHT International Business Machines Corp. 2001 */ #include #include #include #include #include #include #include "log.h" #include "slotmgr.h" #include "pkcsslotd.h" #include "err.h" /* We export Daemon so that we can daemonize or not based on a command-line argument */ BOOL Daemon = (BOOL) BECOME_DAEMON; BOOL IveDaemonized = FALSE; static u_int32 PathSize = PATH_MAX + 1; static char *StartDir = NULL; BOOL IsDaemon ( void ) { return (BOOL) ( (Daemon) && (IveDaemonized) ); } BOOL SaveStartupDirectory ( char *Arg0 ) { unsigned int Err; char cwd[PATH_MAX+1]; char arg[PATH_MAX+1]; char *dname = NULL; ASSERT( Arg0 != NULL ); if ( getcwd ( cwd, PathSize ) == NULL ) { Err = errno; DbgLog(DL0,"SaveStartupDirectory: getcwd returned %s (%d)", SysConst(Err), Err); return FALSE; } /* Free previous copy */ if ( StartDir != NULL ) { free(StartDir); StartDir = NULL; } /* Allocate memory */ if ( (StartDir = calloc ( PathSize, sizeof(char) ) ) == NULL ) { Err = errno; DbgLog(DL0,"SaveStartupDirectory: Unable to allocate %d bytes of memory for storage of the CWD. %s (%d)\n", SysConst(Err), Err ); exit(1); } /* If Arg0 contains a /, then dirname(Arg0) is appended to cwd */ /* This will handle the case where you were in directory foo, and started the daemon * as bar/daemon */ /* FIXME: This will not work properly if the daemon was found by searching the PATH */ /* Make a local copy of the string because dirname() modifies it's arguments */ strcpy( arg, Arg0 ); dname = dirname ( arg ); /* note that dirname("daemon") and dirname("./daemon") will return "." */ if ( strcmp( dname, "." ) != 0 ) { /* there's a / in it... */ sprintf(StartDir, "%s/%s", cwd, dname); } else { sprintf(StartDir, "%s", cwd); } return TRUE; } BOOL GetStartDirectory ( char *Buffer, u_int32 BufSize ) { ASSERT(Buffer != NULL); if ( StartDir == NULL ) { DbgLog(DL0,"GetStartDirectory: Function called before SaveStartupDirectory()"); return FALSE; } /* what the hell is this? */ if ( BufSize < PathSize ) { return FALSE; } memcpy(Buffer, StartDir, strlen(StartDir) + 1 ); return TRUE; } opencryptoki+dfsg/bootstrap.sh0000755000175000017500000000012212630407153015645 0ustar xnoxxnox#!/bin/sh set -x aclocal libtoolize --force -c automake --add-missing -c autoconf opencryptoki+dfsg/AUTHORS0000644000175000017500000000062312630407153014347 0ustar xnoxxnox Base function Design and IBM Device support Steven Bade - sbade@us.ibm.com Jimmie Mayfield Dan Rabinovitz - dsrabino@us.ibm.com Shannon Macalpine Kent Yoder - yoder1@us.ibm.com Kapil Sood - kapil@corrent.com, soodkapil@yahoo.com Broadcom capabilitiy Anton Stiglic astiglic@okiok.com AEP capability Carlos Cid carlos.cid@sepsystems.com Corrent capability Kapil Sood kapil.sood@corrent.com opencryptoki+dfsg/misc/0000755000175000017500000000000012630407153014231 5ustar xnoxxnoxopencryptoki+dfsg/misc/test_mech_list.c0000644000175000017500000003665712630407153017424 0ustar xnoxxnox/* COPYRIGHT (c) International Business Machines Corp. 2005 Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /** * This is something like what you can expect openCryptoki to do when * it requests a mechanism list from your library. */ #include #include "mech_types.h" extern void generate_pkcs11_mech_list(struct mech_list *head); int main(int argc, char *argv[]) { struct mech_list head; struct mech_list *item; generate_pkcs11_mech_list(&head); item = head.next; while (item) { struct mech_list *next; next = item->next; printf("Mechanism type: [%.8x]\n", item->element.mech_type); free(item); item = next; } } opencryptoki+dfsg/misc/mech_list.c0000644000175000017500000004602112630407153016347 0ustar xnoxxnox/* COPYRIGHT (c) International Business Machines Corp. 2005 Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ /** * This is an example of how you might convert your library's internal * mechanism descriptors into PKCS#11-compatible descriptors while * generating a mechanism list for openCryptoki. */ #include "mech_types.h" #ifndef NULL #define NULL 0 #endif /** * Bogus internal data descriptors for various mechanisms. */ #define CUSTOM_MECH_TDES 1 #define CUSTOM_MECH_BLOWFISH 2 #define CUSTOM_MECH_RIPEMD160 3 #define CUSTOM_MECH_DSA 4 /** * An example of a library's way of representing a mechanism. */ struct custom_mech_descriptor { int mech_type; int min_key_size; int max_key_size; int is_hw_accelerated; int support_encrypt; int support_decrypt; int support_digest; int support_wrap; int support_unwrap; int support_sign; int support_verify; }; /** * Something like this should actually be filled in by querying the * driver for what is available; if the library supports software * fallback, then the CKF_HW flag should not be set so openCryptoki is * aware of what really is hardware accelerated and what is not. */ struct custom_mech_descriptor library_specific_mechs[] = { {CUSTOM_MECH_TDES, 24, 24, 1, 1, 1, 0, 1, 1, 0, 0}, {CUSTOM_MECH_BLOWFISH, 16, 16, 1, 1, 1, 0, 1, 1, 0, 0}, {CUSTOM_MECH_RIPEMD160, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {CUSTOM_MECH_DSA, 512, 4096, 1, 0, 0, 0, 0, 0, 1, 1} }; #define CUSTOM_MECH_ARRAY_SIZE 4 /** * Here is an example of how you might map your driver's type * descriptors to the PKCS#11 type descriptors */ struct mech_type_mapping { int internal_mech_type; CK_MECHANISM_TYPE pkcs11_mech_type; }; /** * The mapping from the internal driver type to the PKCS#11 type. */ struct mech_type_mapping mech_type_map[] = { {CUSTOM_MECH_TDES, CKM_DES3_CBC}, {CUSTOM_MECH_BLOWFISH, CKM_VENDOR_DEFINED}, {CUSTOM_MECH_RIPEMD160, CKM_RIPEMD160}, {CUSTOM_MECH_DSA, CKM_DSA} }; #define MECH_TYPE_MAP_SIZE 4 static CK_MECHANISM_TYPE pkcs11_mech_type_for_internal_type(int internal_type) { int i = 0; CK_MECHANISM_TYPE pkcs11_type = CKM_VENDOR_DEFINED; while (i < MECH_TYPE_MAP_SIZE) { if (mech_type_map[i].internal_mech_type == internal_type) { pkcs11_type = mech_type_map[i].pkcs11_mech_type; break; } i++; } return pkcs11_type; } /** * Example method that converts a library's internal mechanism * descriptor into a PKCS#11 mechanism descriptor. Yours may look very * different from this one... */ static void convert_internal_element_to_pkcs11_method_element( MECH_LIST_ELEMENT *element, struct custom_mech_descriptor *internal_mech) { element->mech_type = pkcs11_mech_type_for_internal_type(internal_mech->mech_type); element->mech_info.ulMinKeySize = internal_mech->min_key_size; element->mech_info.ulMaxKeySize = internal_mech->max_key_size; element->mech_info.flags = 0; /* Partial example list of flags that could be set */ if (internal_mech->is_hw_accelerated) { element->mech_info.flags |= CKF_HW; } if (internal_mech->support_encrypt) { element->mech_info.flags |= CKF_ENCRYPT; } if (internal_mech->support_decrypt) { element->mech_info.flags |= CKF_DECRYPT; } if (internal_mech->support_digest) { element->mech_info.flags |= CKF_DIGEST; } if (internal_mech->support_wrap) { element->mech_info.flags |= CKF_WRAP; } if (internal_mech->support_unwrap) { element->mech_info.flags |= CKF_UNWRAP; } if (internal_mech->support_sign) { element->mech_info.flags |= CKF_SIGN; } if (internal_mech->support_verify) { element->mech_info.flags |= CKF_VERIFY; } /* ... */ } /** * Generates a list of supported mechanisms. This is the function that * openCryptoki will be calling directly with a pointer to a * placeholder mech_list struct. * * @param head Pointer to placeholder mech_list struct; this function * fills in the list by tagging on newly malloc'd * mech_list structs off of this struct. */ void generate_pkcs11_mech_list(struct mech_list *head) { struct mech_list *item; int i = 0; item = head; while (i < CUSTOM_MECH_ARRAY_SIZE) { item->next = malloc(sizeof(struct mech_list)); item = item->next; convert_internal_element_to_pkcs11_method_element( &item->element, &library_specific_mechs[i]); i++; } item->next = NULL; return; } opencryptoki+dfsg/misc/mech_types.h0000644000175000017500000006762212630407153016557 0ustar xnoxxnox/* COPYRIGHT (c) International Business Machines Corp. 2005 Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. */ #ifndef _MECH_LIST_TYPES_H #define _MECH_LIST_TYPES_H /** * These defines are copied over from the pkcs11types.h file found in * the openCryptoki package. */ /* 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; /* CK_MECHANISM_TYPE is a value that identifies a mechanism * type */ 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 /* The following are new for v2.11: */ #define CKM_RIPEMD128_RSA_PKCS 0x00000007 #define CKM_RIPEMD160_RSA_PKCS 0x00000008 #define CKM_RSA_PKCS_OAEP 0x00000009 #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 /* The following 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 #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 #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 /* The following are new for v2.11 */ #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 /* 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 /* The following 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 #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 #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.11 */ #define CKM_PKCS5_PBKD2 0x000003B0 #define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 #define CKM_KEY_WRAP_LYNKS 0x00000400 #define CKM_KEY_WRAP_SET_OAEP 0x00000401 /* 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 /* The following 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 /* The following 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 #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 #define CK_PTR * typedef void CK_PTR CK_VOID_PTR; typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; /* CK_MECHANISM is a structure that specifies a particular * mechanism */ typedef struct CK_MECHANISM { CK_MECHANISM_TYPE mechanism; CK_VOID_PTR pParameter; 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 */ /* 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 /* The following are new for v2.11 */ #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 2.01 */ typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; #define CKR_MECHANISM_INVALID 0x00000070 #define CKR_MECHANISM_PARAM_INVALID 0x00000071 /* From common/host_defs.h in openCryptoki */ typedef struct _MECH_LIST_ELEMENT { CK_MECHANISM_TYPE mech_type; CK_MECHANISM_INFO mech_info; } MECH_LIST_ELEMENT; struct mech_list; struct mech_list { struct mech_list *next; MECH_LIST_ELEMENT element; }; #endif opencryptoki+dfsg/misc/migrate_from_2.1_to_2.2.sh0000755000175000017500000000130012630407153020700 0ustar xnoxxnox#!/bin/sh # This script should be run after installing openCryptoki version 2.2.x on a # machine where openCryptoki version 2.1.x has already been installed. # Make sure that no copies of pkcsslotd are running ps -ef | grep pkcsslotd | grep sbin &> /dev/null RES=$? if [ $RES = 0 ]; then killall pkcsslotd fi # Copy files from /etc/pkcs11/ to /var/lib/opencryptoki/ if [ -e "/etc/pkcs11" ]; then mkdir -p /var/lib/opencryptoki cp -aR /etc/pkcs11/* /var/lib/opencryptoki/ cp -a /etc/pkcs11/.slotpid /var/lib/opencryptoki/ fi # Run startup script /usr/sbin/pkcs11_startup # Restart pkcsslotd if it was running before this script was run if [ $RES = 0 ]; then /usr/sbin/pkcsslotd fiopencryptoki+dfsg/misc/opencryptoki.gdb0000644000175000017500000001173212630407153017441 0ustar xnoxxnox# # openCryptoki debugging helper script # # Kent Yoder # April 29, 2011 # # Functions: # # ock_dump_obj_template # ock_dump_object_map # ock_dump_sess_btree # ock_dump_sess_obj_btree # ock_dump_priv_tok_obj_btree # ock_dump_publ_tok_obj_btree # set $OBJECT_MAP = 1 set $OBJECT = 2 set $SESSION = 3 # # ock_dump_obj_template # # Dump an OBJECT's template of attributes # define ock_dump_obj_template set $obj = ($arg0) set $node = $obj->template->attribute_list while ($node) print *(CK_ATTRIBUTE *)($node->data) set $node = $node->next end end define __ock_print_node_type if $arg1 == $OBJECT_MAP print *((OBJECT_MAP *)($arg0)->value) end if $arg1 == $OBJECT print *((OBJECT *)($arg0)->value) end if $arg1 == $SESSION print *((SESSION *)($arg0)->value) end end define __ock_print_node set $n = ($arg0) set $loc = ($arg1) while ($loc > 1) if ($loc & 1) set $n = $n->right else set $n = $n->left end set $loc = $loc >> 1 printf " " end if ($n->flags & 1) printf "`- %d: (deleted node)\n", $arg1 else printf "`- %d: ", $arg1 __ock_print_node_type $n $arg2 end end define __ock_dump_tree set $size = ($arg0).size + 1 set $i = 1 printf "tree: size %d, free nodes: %d\n", $arg0.size, ($arg0).free_nodes while ($i < $size) __ock_print_node ($arg0).top $i ($arg1) set $i = $i + 1 end end define ock_dump_object_map __ock_dump_tree object_map_btree $OBJECT_MAP end define ock_dump_sess_btree __ock_dump_tree sess_btree $SESSION end define ock_dump_sess_obj_btree __ock_dump_tree sess_obj_btree $OBJECT end define ock_dump_priv_tok_obj_btree __ock_dump_tree priv_token_obj_btree $OBJECT end define ock_dump_publ_tok_obj_btree __ock_dump_tree publ_token_obj_btree $OBJECT end define dump_ec_key_token set $tok = ($arg0) printf "----------------------- HEADER SECTION -----------------------\n" printf "Token ID: 0x%02X\n", $tok printf "Token Version Number: 0x%02X\n", $tok[1] printf "Length in bytes of token structure: 0x%02X%02X\n", $tok[2], $tok[3] printf "----------------------- PRIVATE SECTION -----------------------\n" set $priv = $tok[8] printf "Section ID: 0x%02X\n", $priv printf "\tX'20': ECC private key\n" printf "Section version number: 0x%02X\n", $tok[9] printf "Section len: 0x%02X%02X\n", $tok[10], $tok[11] printf "Wrapping method: 0x%02X\n", $tok[12] printf "\tX'00': Section is unencrypted (clear), X'01': AESKW, X'02: CBC\n" printf "Hash method used for wrapping: 0x%02X\n", $tok[13] printf "\tX'01': SHA-224, X'02': SHA-256\n" printf "Key usage: 0x%02X\n", $tok[16] printf "\tX'C0': Key agreement, X'80': Both signature gen & key agreement\n" printf "\tX'00': Signature generation only, X'02': Translate allowed\n" printf "Curve type: 0x%02X\n", $tok[17] printf "\tX'00': Prime curve, X'01': Brainpool curve\n" printf "Key format and security flag: 0x%02X\n", $tok[18] printf "\tEncrypted internal ECC: X'08', " printf "Unencrypted external ECC: X'40', " printf "Encrypted external ECC: X'42'\n" printf "Length of p in bits: 0x%02X%02X\n", $tok[20], $tok[21] printf "\tX'00A0': Brainpool P-160\n" printf "\tX'00C0': Prime P-192, Brainpol P-192\n" printf "\tX'00E0': Brainpool P-224, Prime P-224\n" printf "\tX'0100': Brainpool P-256, Prime P-256\n" printf "\tX'0140': Brainpool P-320\n" printf "\tX'0180': Prime P-384, Brainpool P-384\n" printf "\tX'0200': Brainpool P-512\n" printf "\tX'0209': Prime P-521\n" printf "IBM associated data length in bytes: 0x%02X%02X\n", $tok[22], $tok[23] printf "Master key verification pattern:\n\t" set $i = 0 while ($i < 8) printf "%02X", $tok[24+$i] set $i = $i+1 end printf "\n" printf "Associated data length: 0x%02X%02X\n", $tok[80], $tok[81] printf "Length of formatted section in bytes: 0x%02X%02X\n", $tok[82], $tok[83] printf "-------- Begin formatted section (include d) data --------\n" set $dlen = $tok[83] set $assclen = $tok[81] set $i = 0 while ($i < $dlen) printf "%02X", $tok[84+$assclen+$i] set $i = $i+1 end printf "\n-------- End formatted section data --------\n" printf "----------------------- PUBLIC SECTION -----------------------\n" set $privlen = $tok[11] set $puboffset = $privlen+8 printf "Section ID: 0x%02X\n", $tok[$puboffset] printf "\tX'21': ECC public key\n" printf "Section version number: 0x%02X\n", $tok[$puboffset+1] printf "Section length: 0x%02X%02X\n", $tok[$puboffset+2], $tok[$puboffset+3] printf "Curve type: 0x%02X\n", $tok[$puboffset+8] printf "\tX'00': Prime curve, X'01': Brainpool curve\n" printf "Length of p in bits: 0x%02X%02X\n", $tok[$puboffset+10], $tok[$puboffset+11] printf "Length of public key q in bytes: 0x%02X%02X\n", $tok[$puboffset+12], $tok[$puboffset+13] printf "-------- Begin q data --------\n" set $qlen = $tok[$puboffset+13] set $i = 0 while ($i < $qlen) printf "%02X", $tok[$puboffset+14+$i] set $i = $i+1 end printf "\n-------- End q data --------\n" end document dump_ec_key_token Print the Elliptic Curve key token generated by CSNDPKG. end opencryptoki+dfsg/misc/Makefile.am0000644000175000017500000000074312630407153016271 0ustar xnoxxnoxEXTRA_DIST = pkcsslotd.in pkcsslotd.service.in if ENABLE_DAEMON if ENABLE_SYSTEMD servicedir = $(unitdir) service_DATA = pkcsslotd.service CLEANFILES = pkcsslotd.service pkcsslotd.service: pkcsslotd.service.in @SED@ -e s!\@sbindir\@!"@sbindir@"!g < $< > $@-t mv $@-t $@ else initddir = $(sysconfdir)/rc.d/init.d initd_SCRIPTS = pkcsslotd CLEANFILES = pkcsslotd pkcsslotd: pkcsslotd.in @SED@ -e s!\@sbindir\@!"@sbindir@"!g < $< > $@-t @CHMOD@ a+x $@-t mv $@-t $@ endif endif opencryptoki+dfsg/misc/pkcsslotd.service.in0000644000175000017500000000036212630407153020227 0ustar xnoxxnox[Unit] Description=Daemon which manages cryptographic hardware tokens for the openCryptoki package After=syslog.target [Service] Type=forking PIDFile=/var/run/pkcsslotd.pid ExecStart=@sbindir@/pkcsslotd [Install] WantedBy=multi-user.target opencryptoki+dfsg/misc/pkcsslotd.in0000644000175000017500000000234512630407153016573 0ustar xnoxxnox#!/bin/bash # # pkcsslotd Starts pkcsslotd # # Authors: Kent E. Yoder # Serge E. Hallyn # Daniel H. Jones # # chkconfig: - 50 50 # description: pkcsslotd is a daemon which manages cryptographic hardware \ # tokens for the openCryptoki package. . /etc/init.d/functions PIDFILE=/var/run/pkcsslotd.pid LOCKFILE=/var/lock/subsys/pkcsslotd SLOTDBIN=@sbindir@/pkcsslotd CONFSTART=@sbindir@/pkcs11_startup start() { [ -x $SLOTDBIN ] || exit 5 [ -x $CONFSTART ] || exit 5 echo -n $"Starting pkcsslotd: " # Generate the configuration information $CONFSTART daemon $SLOTDBIN RETVAL=$? echo [ $RETVAL -eq 0 ] && touch $LOCKFILE return $RETVAL } stop() { echo -n $"Shutting down pkcsslotd:" killproc pkcsslotd RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f $LOCKFILE return $RETVAL } restart() { stop start } RETVAL=0 umask 077 case "$1" in start) start ;; stop) stop ;; status) status pkcsslotd $SLOTDBIN ;; restart|reload|force-reload) restart ;; condrestart) [ -f $LOCKFILE ] && restart || : ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|reload|force-reload}" exit 2 esac exit $? opencryptoki+dfsg/misc/rsa_parser.pl0000644000175000017500000013072612630407153016740 0ustar xnoxxnox#!/usr/bin/perl # This script parses the RSA test vectors found in $in_file # and formats them for openCryptoki tests # # Fionnuala Gunter # August 18, 2011 # # # To run: # download ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.tx # ./rsa_parser.pl > rsa.h # # #TODO: For some reason, there are extra blank lines printed... # # constants $max_tv = 300; # maximum number of test vectors to add to file $sub_max = 3; # maximum number of messages/signatures per key pair $count = 0; # current number of test vectors added to file $in_file = "pkcs1v15sign-vectors.txt"; # test vector source # tmp $string; # input $example = "# Example \d+: A \d+-bit RSA key pair"; $key = '# Private key'; $modulus = '# Modulus: '; $publicexponent = '# Public exponent: '; $privateexponent = '# Exponent: '; $prime1_ = '# Prime 1: '; $prime2_ = '# Prime 2: '; $exponent1 = '# Prime exponent 1: '; $exponent2 = '# Prime exponent 2: '; $coefficient = '# Coefficient: '; $msgblock = "# PKCS#1 v1.5 signing of 20 random messages "; $msgsighead = "# PKCS#1 v1.5 Signature Example $num_msg "; $msghead = '# Message to be signed:'; $sighead = '# Signature:'; # output $begin_struct = "//ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt\n". "struct RSA_PUBLISHED_TEST_VECTOR ". "rsa_sha1_pkcs_sigver_published_tv[] = {\n"; $end_struct = "};\n"; $begin_ele = "\t{"; $end_ele = "\t},\n"; $begin_mod = "\t\t.mod = "; $begin_pubexp = "\t\t.pub_exp = "; $begin_privexp = "\t\t.priv_exp = "; $begin_prime1 = "\t\t.prime1 = "; $begin_prime2 = "\t\t.prime2 = "; $begin_exp1 = "\t\t.exp1 = "; $begin_exp2 = "\t\t.exp2 = "; $begin_coef = "\t\t.coef = "; $begin_msg = "\t\t.msg = "; $begin_sig = "\t\t.sig = "; $begin_modlen = "\t\t.mod_len = "; $begin_pubexplen = "\t\t.pubexp_len = "; $begin_privexplen = "\t\t.privexp_len = "; $begin_prime1len = "\t\t.prime1_len = "; $begin_prime2len = "\t\t.prime2_len = "; $begin_exp1len = "\t\t.exp1_len = "; $begin_exp2len = "\t\t.exp2_len = "; $begin_coeflen = "\t\t.coef_len = "; $begin_msglen = "\t\t.msg_len = "; $begin_siglen = "\t\t.sig_len = "; # giant block of generated tests that I copy-pasted here. # this could be replaced with some functions that generate the data below # TODO: CKM_CDMF_KEY_GEN doesn't seem to be supported by ICA, CCA or SoftTok, # so those tests can be removed $defheader = "#include \"pkcs11types.h\" #define MAX_MODULUS_SIZE 256 #define MAX_EXPONENT_SIZE 256 #define MAX_MESSAGE_SIZE 512 #define MAX_SIGNATURE_SIZE 512 #define MAX_PRIME_SIZE 128 #define MAX_COEFFICIENT_SIZE 128 #define PKCS11_MAX_KEY_LEN 512 struct RSA_GENERATED_TEST_VECTOR { CK_ULONG modbits; CK_ULONG publ_exp_len; CK_BYTE publ_exp[4]; CK_ULONG inputlen; CK_MECHANISM keytype; CK_ULONG keylen; }; static struct RSA_GENERATED_TEST_VECTOR rsa_keywrap_generated_tv[] = { { // 0 .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 1 .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 2 .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 3 .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 4 .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 5 .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 6 .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 64, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 7 .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 8 .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 9 .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 10 .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 11 .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 12 .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 13 .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 64, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 14 .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 15 .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 16 .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 17 .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 18 .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 19 .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 20 .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 64, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 21 .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0} }, { // 22 .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 23 .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 24 .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 25 .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 26 .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 27 .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 64, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 28 .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 29 .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 30 .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 31 .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0} }, { // 32 .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 33 .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 34 .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 64, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 35 .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 36 .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 37 .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 38 .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 39 .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 40 .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 41 .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 96, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 42 .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 43 .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 44 .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 45 .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 46 .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 47 .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 48 .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 96, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 49 .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 50 .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 51 .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 52 .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 53 .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 54 .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 55 .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 128, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 56 .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 57 .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 58 .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 59 .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 60 .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 61 .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 62 .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 128, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 63 .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 64 .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 65 .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 66 .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 67 .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 68 .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 69 .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 256, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 70 .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 71 .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 72 .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 73 .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 74 .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 75 .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 76 .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 256, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 77 .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, },{ // 78 .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 79 .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 80 .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 81 .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 82 .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 83 .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 256, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 84 .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 85 .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 86 .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 87 .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 88 .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 89 .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 90 .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .keylen = 512, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 91 .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 92 .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 93 .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 94 .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 95 .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 96 .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, },{ // 97 .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .keylen = 512, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, }, { // 98 .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 1, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, },{ // 99 .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_CDMF_KEY_GEN, 0, 0}, }, { // 100 .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 8, .keytype = {CKM_DES_KEY_GEN, 0, 0}, }, { // 101 .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 24, .keytype = {CKM_DES3_KEY_GEN, 0, 0}, }, { // 102 .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 16, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 103 .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 32, .keytype = {CKM_AES_KEY_GEN, 0, 0}, }, { // 104 .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .keylen = 512, .keytype = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0}, } }; static struct RSA_GENERATED_TEST_VECTOR rsa_generated_tv[] = { { // tv[0] .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1, }, { //tv[1] .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 53, }, { //tv[2] .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { //tv[3] .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 53, }, { //tv[4] .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x03, 0x00, 0x01 }, .inputlen = 1, }, { //tv[5] .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x03, 0x00, 0x01 }, .inputlen = 53, }, { //tv[6] .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1, }, { //tv[7] .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 85, }, { //tv[8] .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { //tv[9] .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 85, }, { //tv[10] .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1, }, { //tv[11] .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 85, }, { //tv[12] .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1, }, { //tv[13] .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 117, }, { //tv[14] .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { //tv[15] .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 117, }, { //tv[16] .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1, }, { //tv[17] .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 117, }, { //tv[18] .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1, }, { //tv[19] .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 245, }, { //tv[20] .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { //tv[21] .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 245, }, { //tv[22] .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1, }, { //tv[23] .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 245, }, { //tv[24] .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1, }, { //tv[25] .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 501, }, { //tv[26] .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { //tv[27] .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 501, }, { //tv[28] .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1, }, { //tv[29] .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 501, }, }; static struct RSA_GENERATED_TEST_VECTOR rsa_x509_generated_tv[] = { { // tv[0] .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1, }, { // tv[1] .modbits = 512, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 64, }, { // tv[2] .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { // tv[3] .modbits = 512, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 64, }, { // tv[4] .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1, }, { // tv[5] .modbits = 512, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 64, }, { // tv[6] .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1, }, { // tv[7] .modbits = 768, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 96, }, { // tv[8] .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { // tv[9] .modbits = 768, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 96, }, { // tv[10] .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1, }, { // tv[11] .modbits = 768, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 96, }, { // tv[12] .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1 }, { // tv[13] .modbits = 1024, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 128, }, { // tv[14] .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { // tv[15] .modbits = 1024, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 128, }, { // tv[16] .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1 }, { // tv[17] .modbits = 1024, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 128, }, { // tv[18] .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1 }, { // tv[19] .modbits = 2048, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 256, }, { // tv[20] .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { // tv[21] .modbits = 2048, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 256, }, { // tv[22] .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1 }, { // tv[23] .modbits = 2048, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 256, }, { // tv[24] .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 1 }, { // tv[25] .modbits = 4096, .publ_exp_len = 1, .publ_exp = { 0x03 }, .inputlen = 512, }, { // tv[26] .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 1, }, { // tv[27] .modbits = 4096, .publ_exp_len = 2, .publ_exp = { 0x00, 0x11 }, .inputlen = 512, }, { // tv[28] .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 1 }, { // tv[29] .modbits = 4096, .publ_exp_len = 3, .publ_exp = { 0x01, 0x00, 0x01 }, .inputlen = 512, } }; struct GENERATED_TEST_SUITE_INFO { const char *name; unsigned int tvcount; struct RSA_GENERATED_TEST_VECTOR *tv; CK_MECHANISM mech; }; #define NUM_OF_GENERATED_KEYWRAP_TESTSUITES 2 struct GENERATED_TEST_SUITE_INFO generated_keywrap_test_suites[] = { { .name = \"RSA PKCS\", .tvcount = 105, .tv = rsa_keywrap_generated_tv, .mech = {CKM_RSA_PKCS, 0, 0}, }, { .name = \"RSA X.509\", .tvcount = 105, .tv = rsa_keywrap_generated_tv, .mech = {CKM_RSA_X_509, 0, 0}, } }; #define NUM_OF_GENERATED_SIGVER_TESTSUITES 5 struct GENERATED_TEST_SUITE_INFO generated_sigver_test_suites[] = { { .name = \"RSA PKCS\", .tvcount = 30, .tv = rsa_generated_tv, .mech = {CKM_RSA_PKCS, 0, 0}, }, { .name = \"RSA SHA1 PKCS\", .tvcount = 30, .tv = rsa_generated_tv, .mech = {CKM_SHA1_RSA_PKCS, 0, 0}, }, { .name = \"RSA MD2 PKCS\", .tvcount = 30, .tv = rsa_generated_tv, .mech = {CKM_MD2_RSA_PKCS, 0, 0}, }, { .name = \"RSA MD5 PKCS\", .tvcount = 30, .tv = rsa_generated_tv, .mech = {CKM_MD5_RSA_PKCS, 0 , 0}, }, { .name = \"RSA X.509\", .tvcount = 30, .tv = rsa_x509_generated_tv, .mech = {CKM_RSA_X_509, 0 , 0}, } }; #define NUM_OF_GENERATED_CRYPTO_TESTSUITES 2 struct GENERATED_TEST_SUITE_INFO generated_crypto_test_suites[] = { { .name = \"RSA PKCS\", .tvcount = 30, .tv = rsa_generated_tv, .mech = {CKM_RSA_PKCS, 0, 0}, }, { .name = \"RSA X.509\", .tvcount = 30, .tv = rsa_x509_generated_tv, .mech = {CKM_RSA_X_509, 0, 0}, } }; struct RSA_PUBLISHED_TEST_VECTOR { CK_BYTE mod[MAX_MODULUS_SIZE]; // n CK_ULONG mod_len; CK_BYTE prime1[MAX_PRIME_SIZE]; // p CK_ULONG prime1_len; CK_BYTE prime2[MAX_PRIME_SIZE]; // q CK_ULONG prime2_len; CK_BYTE exp1[MAX_EXPONENT_SIZE]; // d % (p-1) CK_ULONG exp1_len; CK_BYTE exp2[MAX_EXPONENT_SIZE]; // d % (q-1) CK_ULONG exp2_len; CK_BYTE coef[MAX_COEFFICIENT_SIZE]; // (q^-1) % p CK_ULONG coef_len; CK_BYTE pub_exp[MAX_EXPONENT_SIZE]; // e CK_ULONG pubexp_len; CK_BYTE priv_exp[MAX_EXPONENT_SIZE]; // d CK_ULONG privexp_len; CK_BYTE msg[MAX_MESSAGE_SIZE]; CK_ULONG msg_len; CK_BYTE sig[MAX_SIGNATURE_SIZE]; CK_ULONG sig_len; };\n"; # vars @mod; @pubexp; @privexp; @prime1; @prime2; @exp1; @exp2; @coef; @msg; @sig; $modlen = 0; $pubexplen = 0; $privexplen = 0; $prime1len = 0; $prime2len = 0; $exp1len = 0; $exp2len = 0; $coeflen = 0; $msglen = 0; $siglen = 0; # open test vector file # parse contents # print results open ($file, $in_file); print $defheader; print $begin_struct; my $subcount; while (<$file>) { # parse key pair if ($_ =~ $key){ parse_keys(); $subcount = 0; } # parse message if ($_ =~ $msghead){ #print "\n"; parse_msg(); } # parse signature and print struct element if ($_ =~ $sighead){ #print "\n"; parse_sig(); if ($subcount < $sub_max){ print_ele(); $count++; } if ($count > $max_tv){ last; } #$count++; $subcount++; } } print $end_struct; print "\n"; $footer = "struct PUBLISHED_TEST_SUITE_INFO { const char *name; unsigned int tvcount; struct RSA_PUBLISHED_TEST_VECTOR *tv; CK_MECHANISM mech; unsigned int result; }; #define NUM_OF_PUBLISHED_TESTSUITES 1 struct PUBLISHED_TEST_SUITE_INFO published_test_suites[] = { { .name = \"RSA SHA-1 PKCS v1.5\", .tvcount = $count, .tv = rsa_sha1_pkcs_sigver_published_tv, .mech = {CKM_SHA1_RSA_PKCS, 0, 0}, } };"; print $footer; close ($file); sub parse_keys(){ while (<$file>){ print "\n"; # skip # ----- if ($_ =~ m/^# -/){ next; } # skip " " elsif (length($_) == 1 || length($_) == 2 || (!$_)){ next; } # parse modulus elsif ($_ =~ $modulus){ parse_mod(); next; } # parse public exponent elsif ($_ =~ $publicexponent){ parse_pubexp(); next; } # parse private exponent elsif ($_ =~ $privateexponent){ parse_privexp(); next; } # parse prime1 elsif ($_ =~ $prime1_){ parse_prime1(); next; } # parse prime2 elsif ($_ =~ $prime2_){ parse_prime2(); next; } # parse exponent1 elsif ($_ =~ $exponent1){ parse_exp1(); next; } # parse exponent2 elsif ($_ =~ $exponent2){ parse_exp2(); next; } # parse coefficient elsif ($_ =~ $coefficient){ parse_coef(); last; } } } # parse modulus sub parse_mod(){ @mod = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@mod, $string); } } else { $modlen = @mod; last; } } } # parse public exponent sub parse_pubexp(){ @pubexp = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@pubexp, $string); } } else { $pubexplen = @pubexp; last; } } } # parse private exponent sub parse_privexp(){ @privexp = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@privexp, $string); } } else { $privexplen = @privexp; last; } } } # parse prime 1 sub parse_prime1(){ @prime1 = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@prime1, $string); } } else { $prime1len = @prime1; last; } } } # parse prime 2 sub parse_prime2(){ @prime2 = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@prime2, $string); } } else { $prime2len = @prime2; last; } } } # parse exponent 1 sub parse_exp1(){ @exp1 = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@exp1, $string); } } else { $exp1len = @exp1; last; } } } # parse exponent 2 sub parse_exp2(){ @exp2 = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@exp2, $string); } } else { $exp2len = @exp2; last; } } } # parse coefficient sub parse_coef(){ @coef = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@coef, $string); } } else { $coeflen = @coef; last; } } } # parse message sub parse_msg(){ @msg = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@msg, $string); } } else { $msglen = @msg; last; } } } # parse signature sub parse_sig(){ @sig = (); while (<$file>){ if ($_ =~ m{\S+}){ for (my $n = 0; ($n + 2) < length($_); $n+=3) { $string = "0x".substr($_, $n, 2); push(@sig, $string); } } else { $siglen = @sig; last; } } } # prints test vector sub print_ele(){ print $begin_ele; print "\t/\/\ $count\n"; # new print_mod(); print_pubexp(); print_privexp(); print_prime1(); print_prime2(); print_exp1(); print_exp2(); print_coef(); print_msg(); print_sig(); print $end_ele; } # prints modulus sub print_mod(){ print $begin_mod; print "\t { "; for (my $n = 0; $n < $modlen; $n++){ print $mod[$n]; if ($n + 1 < $modlen){ print ","; } if (($n + 1 < $modlen) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_modlen; print $modlen; print ",\n"; } # prints public exponent sub print_pubexp(){ print $begin_pubexp; print " { "; for (my $n = 0; $n < $pubexplen; $n++){ print $pubexp[$n]; if ($n + 1 < $pubexplen){ print ","; } } print " },\n"; print $begin_pubexplen; print $pubexplen; print ",\n"; } # prints private exponent sub print_privexp(){ print $begin_privexp; print " { "; for (my $n = 0; $n < $privexplen; $n++){ print $privexp[$n]; if ($n + 1 < $privexplen){ print ","; } if (($n + 1 < $privexplen) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_privexplen; print $privexplen; print ",\n"; } # prints prime 1 sub print_prime1(){ print $begin_prime1; print " { "; for (my $n = 0; $n < $prime1len; $n++){ print $prime1[$n]; if ($n + 1 < $prime1len){ print ","; } if (($n + 1 < $prime1len) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_prime1len; print $prime1len; print ",\n"; } # prints prime 2 sub print_prime2(){ print $begin_prime2; print " { "; for (my $n = 0; $n < $prime2len; $n++){ print $prime2[$n]; if ($n + 1 < $prime2len){ print ","; } if (($n + 1 < $prime2len) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_prime2len; print $prime2len; print ",\n"; } # prints exponent 1 sub print_exp1(){ print $begin_exp1; print " { "; for (my $n = 0; $n < $exp1len; $n++){ print $exp1[$n]; if ($n + 1 < $exp1len){ print ","; } if (($n + 1 < $exp1len) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_exp1len; print $exp1len; print ",\n"; } # prints exponent 2 sub print_exp2(){ print $begin_exp2; print " { "; for (my $n = 0; $n < $exp2len; $n++){ print $exp2[$n]; if ($n + 1 < $exp2len){ print ","; } if (($n + 1 < $exp2len) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_exp2len; print $exp2len; print ",\n"; } # prints coefficient sub print_coef(){ print $begin_coef; print " { "; for (my $n = 0; $n < $coeflen; $n++){ print $coef[$n]; if ($n + 1 < $coeflen){ print ","; } if (($n + 1 < $coeflen) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_coeflen; print $coeflen; print ",\n"; } # prints message sub print_msg(){ print $begin_msg; print " { "; for (my $n = 0; $n < $msglen; $n++){ print $msg[$n]; if ($n + 1 < $msglen){ print ","; } if (($n + 1 < $msglen) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_msglen; print $msglen; print ",\n"; } # prints signature sub print_sig(){ print $begin_sig; print " { "; for (my $n = 0; $n < $siglen; $n++){ print $sig[$n]; if ($n + 1 < $siglen){ print ","; } if (($n + 1 < $siglen) && !(($n + 1) % 8)){ print "\n\t\t\t\t"; } } print " },\n"; print $begin_siglen; print $siglen; print ",\n"; } opencryptoki+dfsg/LICENSE0000644000175000017500000003553112630407153014312 0ustar xnoxxnox Common Public License Version 0.5 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. opencryptoki+dfsg/README0000644000175000017500000001624012630407153014161 0ustar xnoxxnoxopencryptoki README Package version 3.4.1 Please see NEWS for additional version 3 information. OVERVIEW openCryptoki version 3.1 implements the PKCS#11 specification version 2.11. This package includes several cryptographic tokens; CCA, ICA, TPM , SWToken, ICSF, and EP11. REQUIREMENTS: - IBM ICA requires libica library version 2.3.0 or higher for accessing ICA hardware crypto on IBM zSeries. - IBM CCA requires IBM XCrypto CEX3C card and the CEX3C host libraries and tools version 4.1. - TPM requires a TPM, TPM tools, and TCG software stack. - SWToken The software token uses OpenSSL version 0.9.7 or higher. - ICSF The Integrated Cryptographic Service Facility (ICSF) token requires openldap and opeldap client software version 2.4.23 or higher. Lex and Yacc are also required to build this token. - EP11 The EP11 token is a token that uses the IBM Crypto Express adapters (starting with Crypto Express 4S adapters) configured with Enterprise PKCS#11 (EP11) firmware. BUILD PROCESS The simplest way to compile this package is to enter the source code main directory and do the following: 1. Run the bootstrap.sh script by typing: % sh bootstrap.sh 2. Configure the source code by typing: % sh ./configure If you're planning to install the package into your home directory or to a location other than `/usr/local' then add the flag `--prefix=PATH' to `configure'. For example, if your home directory is `/home/luser' you can configure the package to install itself there by invoking: % sh ./configure --prefix=/home/luser If your stdll headers and libraries are not under any standard path, you will need to pass the paths to your files to the configure script. For instance: $ CPPFLAGS="-L/path/lib" LDFLAGS="-I/path/include" ./configure See ./configure --help for info on various options. The default behavior is to build a default token implicitly. For the s390 platform, the default token is ica_s390. For other platforms, the default token is the software token. Other tokens may be enabled using the corresponding --enable- configuration option provided the appropriate libraries are available. While running, `configure' prints some messages telling which features is it checking for. 3. Compile the package by typing: % make 4. Type `make install' to install the programs and any data files and documentation. During installation, the following files go to the following directories: /prefix/sbin/pkcsconf /prefix/sbin/pkcsslotd /prefix/sbin/pkcsicsf /prefix/libdir/libopencryptoki.so /prefix/libdir/libopencryptoki.so.0 /prefix/libdir/opencryptoki/libopencryptoki.so /prefix/libdir/opencryptoki/libopencryptoki.so.0 /prefix/libdir/opencryptoki/libopencryptoki.so.0.0.0 /prefix/var/lib/opencryptoki /prefix/etc/opencryptoki/opencryptoki.conf Token objects, which may be optionally built, go to the following locations: /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so.0 /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so.0.0.0 /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so.0 /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so.0.0.0 /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so.0 /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so.0.0.0 where `prefix' is either `/usr/local' or the PATH that you specified in the `--prefix' flag. `libdir' is the name of the library directory; for 32-bit libraries it is usually `lib' and for 64-bit libraries it is usually `lib64'. To maintain backwards compatibility, some additional symlinks are generated (note that these are deprecated, and applications should migrate to use the LSB-compliant names and locations for libraries and executables): /prefix/lib/opencryptoki/PKCS11_API.so - Symlink to /prefix/lib/opencryptoki/libopencryptoki.so /prefix/lib/opencryptoki/stdll/PKCS11_ICA.so - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_ica.so /prefix/lib/opencryptoki/stdll/PKCS11_SW.so - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_sw.so /prefix/lib/pkcs11/PKCS11_API.so - Symlink to /prefix/lib/opencryptoki/libopencryptoki.so /prefix/lib/pkcs11 - Directory created if non-existent /prefix/lib/pkcs11/methods - Symlink to /prefix/sbin /prefix/lib/pkcs11/stdll - Symlink to /prefix/lib/opencryptoki/stdll /prefix/etc/pkcs11 - Symlink to /prefix/var/lib/opencryptoki If any of these directories do not presently exist, they will be created on demand. Note that if ``prefix'' is ``/usr'', then /prefix/var and /prefix/etc resolve to /var and /etc. On the ``make install'' stage, if content exists in the old /prefix/etc/pkcs11 directory, it will be migrated to the new /prefix/var/lib/opencryptoki location. If you are installing in your home directory make sure that `/home/luser/bin' is in your path. If you're using the bash shell add this line at the end of your .cshrc file: PATH="/home/luser/bin:${PATH}" export PATH If you are using csh or tcsh, then use this line instead: setenv PATH /home/luser/bin:${PATH} By prepending your home directory to the rest of the PATH you can override systemwide installed software with your own custom installation. CONFIGURATION See: http://www-128.ibm.com/developerworks/security/library/s-pkcs/index.html openCryptoki defaults to be usable by anyone who is in the group ``pkcs11''. You may need to add the pkcs11 group before using. % groupadd pkcs11 Add root to the pkcs11 group. % usermod -G pkcs11 root Prior to version 3, opencryptoki used pk_config_data as its configuration file. This file was created upon running pkcs11_startup. In version 3, pkcs11_startup and pk_config_data have been removed and replaced with a customizeable config file named, opencryptoki.conf. It contains an entry for each token currently supported by opencryptoki. However, only those tokens, whose hardware and software requirements are available on the local system, will show up as present and available upon running the pkcsconf -t command. Before using, each token must be first initialized. You can select the token with the -c command line option; refer to the documentation linked to above for further instructions. Initialize a particular token by running pkcsconf: % pkcsconf -I -c In this version of openCrypoki, the default SO PIN is 87654321. This should be changed to a different PIN value before use. You can change the SO PIN by running pkcsconf: % pkcsconf -P -c You can initialize and change the user PIN by typing: % pkcsconf -u -c You can later change the user PIN again by typing: % pkcsconf -p -c opencryptoki+dfsg/Makefile.am0000644000175000017500000000024512630407153015333 0ustar xnoxxnoxif ENABLE_TESTCASES TESTDIR = testcases endif if ENABLE_LIBRARY MISCDIR = misc endif if ENABLE_DAEMON MISCDIR = misc endif SUBDIRS = usr man $(MISCDIR) $(TESTDIR) opencryptoki+dfsg/configure.in0000644000175000017500000004215612630407153015617 0ustar xnoxxnoxdnl Process this file with autoconf to produce a configure script. AC_INIT([openCryptoki],[3.4.1],[opencryptoki-tech@lists.sourceforge.net]) dnl Needed for $target! AC_CANONICAL_SYSTEM AM_INIT_AUTOMAKE([foreign 1.6]) dnl Checks for header files. AC_DISABLE_STATIC LT_INIT AC_HEADER_STDC AC_CHECK_HEADERS([fcntl.h limits.h strings.h sys/file.h syslog.h unistd.h]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_UID_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_STRUCT_TM dnl Checks for library functions. AC_FUNC_ALLOCA AC_FUNC_MEMCMP AC_FUNC_STRFTIME AC_FUNC_VPRINTF AC_CHECK_FUNCS([getcwd]) dnl Used in various scripts AC_PATH_PROG([ID], [id], [/us/bin/id]) AC_PATH_PROG([USERMOD], [usermod], [/usr/sbin/usermod]) AC_PATH_PROG([GROUPADD], [groupadd], [/usr/sbin/groupadd]) AC_PATH_PROG([CAT], [cat], [/bin/cat]) AC_PATH_PROG([CHMOD], [chmod], [/bin/chmod]) AC_PATH_PROG([CHGRP], [chgrp], [/bin/chgrp]) AC_PROG_SED AC_PROG_MKDIR_P AM_PROG_LEX AC_PROG_YACC dnl Define custom variables lockdir=$localstatedir/lock/opencryptoki AC_SUBST(lockdir) logdir=$localstatedir/log/opencryptoki AC_SUBST(logdir) dnl --- dnl --- Check all --enable/--disable-features dnl --- dnl --- Debugging support AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug],[enable debugging build @<:@default=no@:>@]), [], [enable_debug=no]) dnl --- build testcases AC_ARG_ENABLE([testcases], AS_HELP_STRING([--enable-testcases],[build the test cases @<:@default=no@:>@]), [], [enable_testcases=no]) dnl --- Check if building daemon AC_ARG_ENABLE([daemon], AS_HELP_STRING([--enable-daemon],[build pkcsslotd daemon @<:@default=yes@:>@]), [], [enable_daemon=yes]) dnl --- Check if building library AC_ARG_ENABLE([library], AS_HELP_STRING([--enable-library],[build opencryptoki libraries @<:@default=yes@:>@]), [], [enable_library=yes]) dnl --- Enable/disable tokens dnl --- those have an additional 'check' state, which essentially means dnl --- that it will enable it by default it dependencies are met dnl --- ICA token AC_ARG_ENABLE([icatok], AS_HELP_STRING([--enable-icatok],[build ica token @<:@default=enabled if libica is present@:>@]), [], [enable_icatok=check]) dnl --- CCA token AC_ARG_ENABLE([ccatok], AS_HELP_STRING([--enable-ccatok],[build cca token (IBM Common Cryptographic Architecture) @<:@default=enabled in s390 arch@:>@]), [], [enable_ccatok=check]) dnl --- software token AC_ARG_ENABLE([swtok], AS_HELP_STRING([--enable-swtok],[build software token @<:@default=enabled@:>@]), [], [enable_swtok=yes]) dnl --- EP11 token AC_ARG_ENABLE([ep11tok], AS_HELP_STRING([--enable-ep11tok],[build ep11 token @<:@default=enabled@:>@]), [], [enable_ep11tok=check]) dnl --- TPM token AC_ARG_ENABLE([tpmtok], AS_HELP_STRING([--enable-tpmtok],[build tpm token (Trusted Platform Module) @<:@default=enabled if TrouSerS is present@:>@]), [], [enable_tpmtok=check]) dnl -- icsf token (Integrated Cryptographic Service Facility remote token) AC_ARG_ENABLE([icsftok], AS_HELP_STRING([--enable-iscftok],[build icsf token (Integrated Cryptographic Service Facility) @<:@default=enabled if OpenLDAP library is present@:>@]), [], [enable_icsftok=check]) dnl --- token-specific stuff dnl --- pkcsep11_migrate AC_ARG_ENABLE([pkcsep11_migrate], AS_HELP_STRING([--enable-pkcsep11_migrate],[build pkcsep11_migrate (EP11 token key migration tool) @<:@default=enabled if EP11 library is present@:>@]), [], [enable_pkcsep11_migrate=check]) dnl --- dnl --- Check for external software dnl --- Define what to check based on enabled features dnl --- Openssl development files AC_ARG_WITH([openssl], AS_HELP_STRING([--with-openssl@<:@=DIR@:>@],[OpenSSL development files location]), [], [with_openssl=check]) dnl --- Openldap development files AC_ARG_WITH([openldap], AS_HELP_STRING([--with-openldap@<:@=DIR@:>@],[OpenLDAP development files location]), [], [with_openldap=check]) dnl --- Libica development files AC_ARG_WITH([libica], AS_HELP_STRING([--with-libica@<:@=DIR@:>@],[libica development files location]), [], [with_libica=check]) dnl --- zcrypt development files AC_ARG_WITH([zcrypt], AS_HELP_STRING([--with-zcrypt@<:@=DIR@:>@],[zcrypt development files location]), [], [with_zcrypt=check]) dnl --- TSS (TrouSerS) development files AC_ARG_WITH([tss], AS_HELP_STRING([--with-tss@<:@=DIR@:>@],[TrouSerS development files location]), [], [with_tss=check]) dnl --- xcryptolinz development files (IBM CCA development files) AC_ARG_WITH([xcryptolinz], AS_HELP_STRING([--with-xcryptolinz@<:@=DIR@:>@],[CCA library (xcryptolinz) location]), [], [with_xcryptolinz=check]) dnl --- systemd system unit files location AC_ARG_WITH([systemd], AS_HELP_STRING([--with-systemd@<:@=DIR@:>@],[systemd system unit files location]), [], [with_systemd=no]) dnl --- dnl --- dnl --- Now that we have all the options, let's check for a valid build dnl --- case $target in *s390x*) ;; *s390*) CFLAGS="$CFLAGS -m31" ;; *ppc64* | *x86_64*) ;; *ppc* | i*86*) CFLAGS="$CFLAGS -m32" ;; esac dnl --- enable_debug if test "x$enable_debug" = "xyes"; then CFLAGS="$CFLAGS -gdwarf-2 -g3 -O0 -DDEBUG" fi dnl --- first, check what external software is present or specified dnl --- with --with-package=DIR dnl --- with_openssl OPENSSL_CFLAGS= OPENSSL_LIBS= if test "x$with_openssl" != "xno"; then if test "x$with_openssl" != "xyes" -a "x$with_openssl" != "xcheck"; then OPENSSL_CFLAGS="-I$with_openssl" OPENSSL_LIBS="-L$with_openssl" fi old_cflags="$CFLAGS" old_libs="$LIBS" CFLAGS="$CFLAGS $OPENSSL_CFLAGS" LIBS="$LIBS $OPENSSL_LIBS" AC_CHECK_HEADER([openssl/ssl.h], [], [ if test "x$with_openssl" != "xcheck"; then AC_MSG_ERROR([Build with OpenSSL requested but OpenSSL headers couldn't be found]) fi with_openssl=no ]) if test "x$with_openssl" != "xno"; then AC_CHECK_LIB([crypto], [RSA_generate_key], [ OPENSSL_LIBS="$OPENSSL_LIBS -lcrypto" with_openssl=yes ], [ if test "x$with_openssl" != "xcheck"; then AC_MSG_ERROR([Build with OpenSSL requested but OpenSSL libraries couldn't be found]) fi with_openssl=no ]) fi if test "x$with_openssl" = "xno"; then CFLAGS="$old_cflags" LIBS="$old_libs" fi fi AC_SUBST([OPENSSL_CFLAGS]) AC_SUBST([OPENSSL_LIBS]) dnl --- with_openldap OPENLDAP_CFLAGS= OPENLDAP_LIBS= if test "x$with_openldap" != "xno"; then if test "x$with_openldap" != "xyes" -a "x$with_openldap" != "xcheck"; then OPENLDAP_CFLAGS="-I$with_openldap" OPENLDAP_LIBS="-L$with_openldap" fi old_cflags="$CFLAGS" old_libs="$LIBS" CFLAGS="$CFLAGS $OPENLDAP_CFLAGS" LIBS="$LIBS $OPENLDAP_LIBS" AC_CHECK_HEADER([ldap.h], [], [ if test "x$with_openldap" != "xcheck"; then AC_MSG_ERROR([Build with OpenLDAP requested but OpenLDAP headers couldn't be found]) fi with_openldap=no ]) if test "x$with_openldap" != "xno"; then AC_CHECK_LIB([ldap], [ldap_extended_operation_s], [ OPENLDAP_LIBS="$OPENLDAP_LIBS -lldap" with_openldap=yes ], [ if test "x$with_openldap" != "xcheck"; then AC_MSG_ERROR([Build with OpenLDAP requested but OpenLDAP libraries couldn't be found]) fi with_openldap=no ]) fi if test "x$with_openldap" = "xno"; then CFLAGS="$old_cflags" LIBS="$old_libs" fi fi AC_SUBST([OPENLDAP_CFLAGS]) AC_SUBST([OPENLDAP_LIBS]) dnl --- with_libica LIBICA_CFLAGS= LIBICA_LIBS= if test "x$with_libica" != "xno"; then if test "x$with_libica" != "xyes" -a "x$with_libica" != "xcheck"; then LIBICA_CFLAGS="-I$with_libica" LIBICA_LIBS="-L$with_libica" fi old_cflags="$CFLAGS" old_libs="$LIBS" CFLAGS="$CFLAGS $LIBICA_CFLAGS" LIBS="$LIBS $LIBICA_LIBS" AC_CHECK_HEADER([ica_api.h], [], [ if test "x$with_libica" != "xcheck"; then AC_MSG_ERROR([Build with Libica requested but Libica headers couldn't be found]) fi with_libica=no ]) if test "x$with_libica" != "xno"; then AC_CHECK_LIB([ica], [ica_open_adapter], [with_libica=yes], [ if test "x$with_libica" != "xcheck"; then AC_MSG_ERROR([Build with Libica requested but Libica libraries (v 2.x or higher) couldn't be found]) fi with_libica=no ]) fi if test "x$with_libica" = "xno"; then CFLAGS="$old_cflags" LIBS="$old_libs" fi fi AC_SUBST([LIBICA_CFLAGS]) AC_SUBST([LIBICA_LIBS]) dnl --- with_zcrypt ZCRYPT_CFLAGS= ZCRYPT_LIBS= if test "x$with_zcrypt" != "xno"; then if test "x$with_zcrypt" != "xyes" -a "x$with_zcrypt" != "xcheck"; then ZCRYPT_CFLAGS="-I$with_zcrypt" ZCRYPT_LIBS="-L$with_zcrypt" fi old_cflags="$CFLAGS" old_libs="$LIBS" CFLAGS="$CFLAGS $ZCRYPT_CFLAGS" LIBS="$LIBS $ZCRYPT_LIBS" AC_CHECK_HEADER([asm/zcrypt.h], [], [ if test "x$with_zcrypt" != "xcheck"; then AC_MSG_ERROR([Build with zcrypt requested but zcrypt headers couldn't be found]) fi with_zcrypt=no ]) if test "x$with_zcrypt" != "xno"; then with_zcrypt=yes fi if test "x$with_zcrypt" = "xno"; then CFLAGS="$old_cflags" LIBS="$old_libs" fi fi AC_SUBST([ZCRYPT_CFLAGS]) AC_SUBST([ZCRYPT_LIBS]) dnl --- with_tss TSS_CFLAGS= TSS_LIBS= if test "x$with_tss" != "xno"; then if test "x$with_tss" != "xyes" -a "x$with_tss" != "xcheck"; then TSS_CFLAGS="-I$with_tss" TSS_LIBS="-L$with_tss" fi old_cflags="$CFLAGS" old_libs="$LIBS" CFLAGS="$CFLAGS $TSS_CFLAGS" LIBS="$LIBS $TSS_LIBS" AC_CHECK_HEADER([tss/platform.h], [], [ if test "x$with_tss" != "xcheck"; then AC_MSG_ERROR([Build with TSS requested but TSS headers couldn't be found]) fi with_tss=no ]) if test "x$with_tss" != "xno"; then AC_CHECK_LIB([tspi], [Tspi_Context_Create], [with_tss=yes], [ if test "x$with_tss" != "xcheck"; then AC_MSG_ERROR([Build with TSS requested but TSS libraries couldn't be found]) fi with_tss=no ]) fi if test "x$with_tss" = "xno"; then CFLAGS="$old_cflags" LIBS="$old_libs" fi fi AC_SUBST([TSS_CFLAGS]) AC_SUBST([TSS_LIBS]) dnl --- with_xcryptolinz XCRYPTOLINZ_CFLAGS= XCRYPTOLINZ_LIBS= if test "x$with_xcryptolinz" != "xno"; then if test "x$with_xcryptolinz" != "xyes" -a "x$with_xcryptolinz" != "xcheck"; then XCRYPTOLINZ_CFLAGS="-I$with_xcryptolinz" XCRYPTOLINZ_LIBS="-L$with_xcryptolinz" fi old_cflags="$CFLAGS" old_libs="$LIBS" CFLAGS="$CFLAGS $XCRYPTOLINZ_CFLAGS" LIBS="$LIBS $XCRYPTOLINZ_LIBS" dnl - The above may not be necessary since opencryptoki brings this header file anyway. AC_CHECK_HEADER([csulincl.h], [], [ if test "x$with_xcryptolinz" != "xcheck"; then AC_MSG_ERROR([Build with xcryptolinz requested but xcryptolinz headers couldn't be found]) fi with_xcryptolinz=no ]) if test "x$with_xcryptolinz" != "xno"; then AC_CHECK_LIB([csulsapi], [CSNBKTC], [with_xcryptolinz=yes], [ if test "x$with_xcryptolinz" != "xcheck"; then AC_MSG_ERROR([Build with xcryptolinz requested but xcryptolinz libraries couldn't be found]) fi with_xcryptolinz=no ]) fi if test "x$with_xcryptolinz" = "xno"; then CFLAGS="$old_cflags" LIBS="$old_libs" fi fi AC_SUBST([XCRYPTOLINZ_CFLAGS]) AC_SUBST([XCRYPTOLINZ_LIBS]) dnl --- dnl --- Now check enabled features, while making sure every required dnl --- package is available dnl --- dnl --- enable_testcases if test "x$enable_testcases" = "xyes"; then AC_CHECK_PROG([HAVE_EXPECT], [expect], [yes], [no]) if test "x$HAVE_EXPECT" = "xno"; then AC_MSG_ERROR([*** testcases requires 'expect' interpreter, which wasn't found]) enable_testcases=no fi fi AM_CONDITIONAL([ENABLE_TESTCASES], [test "x$enable_testcases" = "xyes"]) dnl --- enable_daemon AM_CONDITIONAL([ENABLE_DAEMON], [test "x$enable_daemon" = "xyes"]) dnl --- enable_library AM_CONDITIONAL([ENABLE_LIBRARY], [test "x$enable_library" = "xyes"]) dnl --- enable systemd and set unit dir if test "x$with_systemd" != "xno"; then if test "x$with_systemd" != "xyes" -a "x$with_systemd" != "xcheck"; then unitdir=$with_systemd enable_systemd=yes else if test "x$with_systemd" = "xyes"; then unitdir=${ac_default_prefix}/lib/systemd/system enable_systemd=yes else enable_systemd=no fi fi else enable_systemd=no fi AM_CONDITIONAL([ENABLE_SYSTEMD], [test "x$enable_systemd" = "xyes"]) AC_SUBST(unitdir) dnl --- enable_icatok if test "x$enable_icatok" = "xyes"; then if test "x$with_libica" != "xyes"; then AC_MSG_ERROR([ica token build requested but libica development files not found]) enable_icatok=no fi fi if test "x$enable_icatok" = "xyes"; then if test "x$with_openssl" != "xyes"; then AC_MSG_ERROR([ica token build requested but OpenSSL development files not found]) enable_icatok=no fi fi if test "x$enable_icatok" != "xno" -a "x$with_libica" != "xno" -a "x$with_openssl" != "xno"; then enable_icatok=yes else enable_icatok=no fi AM_CONDITIONAL([ENABLE_ICATOK], [test "x$enable_icatok" = "xyes"]) dnl --- enable_ccatok if test "x$enable_ccatok" != "xno"; then enable_ccatok=yes else enable_ccatok=no fi AM_CONDITIONAL([ENABLE_CCATOK], [test "x$enable_ccatok" = "xyes"]) dnl --- enable_swtok if test "x$enable_swtok" = "xyes"; then if test "x$with_openssl" != "xyes"; then AC_MSG_ERROR([software token build requested but OpenSSL development files not found]) enable_swtok=no fi fi if test "x$enable_swtok" != "xno" -a "x$with_openssl" != "xno"; then enable_swtok=yes else enable_swtok=no fi AM_CONDITIONAL([ENABLE_SWTOK], [test "x$enable_swtok" = "xyes"]) dnl --- enable_ep11tok if test "x$enable_ep11tok" = "xyes"; then if test "x$with_zcrypt" != "xyes"; then AC_MSG_ERROR([ep11 token build requested but ep11 development files not found]) enable_ep11=no fi fi if test "x$enable_ep11tok" != "xno" -a "x$with_zcrypt" != "xno"; then enable_ep11tok=yes else enable_ep11tok=no fi AM_CONDITIONAL([ENABLE_EP11TOK], [test "x$enable_ep11tok" = "xyes"]) dnl --- enable_icsftok if test "x$enable_icsftok" = "xyes"; then if test "x$with_openldap" != "xyes"; then AC_MSG_ERROR([ICSF token build requested but OpenLDAP development files not found]) enable_icsftok=no fi if test "x$with_openssl" != "xyes"; then AC_MSG_ERROR([ICSF token build requested but OpenSSL development files not found]) enable_icsftok=no fi fi if test "x$enable_icsftok" != "xno" -a "x$with_openldap" != "xno" -a "x$with_openssl" != "xno"; then enable_icsftok=yes else enable_icsftok=no fi AM_CONDITIONAL([ENABLE_ICSFTOK], [test "x$enable_icsftok" = "xyes"]) dnl --- enable_tpmtok if test "x$enable_tpmtok" = "xyes"; then if test "x$with_tss" != "xyes"; then AC_MSG_ERROR([tpm token build requested but TSS development files not found]) enable_tpmtok=no fi fi if test "x$enable_tpmtok" != "xno" -a "x$with_tss" != "xno"; then enable_tpmtok=yes else enable_tpmtok=no fi AM_CONDITIONAL([ENABLE_TPMTOK], [test "x$enable_tpmtok" = "xyes"]) dnl --- enable_pkcsep11_migrate if test "x$enable_pkcsep11_migrate" = "xyes"; then if test "x$with_zcrypt" != "xyes"; then AC_MSG_ERROR([pkcsep11_migrate build requested but no ep11 libraries found]) enable_pkcsep11_migrate=no fi fi if test "x$enable_pkcsep11_migrate" != "xno" -a "x$with_zcrypt" != "xno"; then enable_pkcsep11_migrate=yes else enable_pkcsep11_migrate=no fi AM_CONDITIONAL([ENABLE_PKCSEP11_MIGRATE], [test "x$enable_pkcsep11_migrate" = "xyes"]) CFLAGS="$CFLAGS -DPKCS64 -D_XOPEN_SOURCE=500 -Wall -Wno-pointer-sign" CFLAGS+=' -DCONFIG_PATH=\"$(localstatedir)/lib/opencryptoki\" -DSBIN_PATH=\"$(sbindir)\" -DLIB_PATH=\"$(libdir)\" -DLOCKDIR_PATH=\"$(lockdir)\" -DOCK_CONFDIR=\"$(sysconfdir)/opencryptoki\" -DOCK_LOGDIR=\"$(logdir)\"' # At this point, CFLAGS is set to something sensible AC_PROG_CC AC_CONFIG_FILES([Makefile usr/Makefile \ usr/include/Makefile \ usr/include/pkcs11/Makefile \ usr/lib/Makefile \ usr/lib/pkcs11/Makefile \ usr/lib/pkcs11/api/Makefile \ usr/lib/pkcs11/api/shrd_mem.c \ usr/lib/pkcs11/ica_s390_stdll/Makefile \ usr/sbin/Makefile \ usr/sbin/pkcsslotd/Makefile \ usr/sbin/pkcsconf/Makefile \ usr/sbin/pkcsicsf/Makefile \ usr/sbin/pkcscca/Makefile \ usr/sbin/pkcsep11_migrate/Makefile \ usr/lib/pkcs11/soft_stdll/Makefile \ usr/lib/pkcs11/ep11_stdll/Makefile \ usr/lib/pkcs11/tpm_stdll/Makefile \ usr/lib/pkcs11/cca_stdll/Makefile \ usr/lib/pkcs11/icsf_stdll/Makefile \ misc/Makefile \ testcases/Makefile \ testcases/common/Makefile \ testcases/crypto/Makefile \ testcases/pkcs11/Makefile \ testcases/login/Makefile \ testcases/misc_tests/Makefile \ man/Makefile \ man/man1/Makefile \ man/man1/pkcsconf.1 \ man/man1/pkcsicsf.1 \ man/man1/pkcscca.1 \ man/man1/pkcsep11_migrate.1 \ man/man5/Makefile \ man/man5/opencryptoki.conf.5 \ man/man7/Makefile \ man/man7/opencryptoki.7 \ man/man8/Makefile \ man/man8/pkcsslotd.8]) AC_OUTPUT echo "Enabled features:" echo " Debug build: $enable_debug" echo " Testcases: $enable_testcases" echo " Daemon build: $enable_daemon" echo " Library build: $enable_library" echo " Systemd service: $enable_systemd" echo echo "Enabled token types:" echo " ICA token: $enable_icatok" echo " CCA token: $enable_ccatok" echo " Software token: $enable_swtok" echo " EP11 token: $enable_ep11tok" echo " TPM token: $enable_tpmtok" echo " ICSF token: $enable_icsftok" echo echo "Token-specific features:" echo " pkcsep11migrate build: $enable_pkcsep11_migrate" echo echo "CFLAGS=$CFLAGS" echo opencryptoki+dfsg/man/0000755000175000017500000000000012630407153014051 5ustar xnoxxnoxopencryptoki+dfsg/man/man5/0000755000175000017500000000000012630407153014711 5ustar xnoxxnoxopencryptoki+dfsg/man/man5/opencryptoki.conf.5.in0000644000175000017500000000425312630407153021062 0ustar xnoxxnox.TH OPENCRYPTOKI.CONF 5 "September 2012" "@PACKAGE_VERSION@" "openCryptoki" .SH NAME opencryptoki.conf \- Configuration file for pkcsslotd. .SH DESCRIPTION pkcsslotd uses a configuration file at "@sysconfdir@"/opencryptoki/opencryptoki.conf This is a text file that contains information used to configure pkcs#11 slots. At startup, the pkcsslotd daemon parses this file to determine which slots will be made available. .SH SYNTAX This file is made up of slot descriptions. Each slot description is composed of a slot number, brackets and key-value pairs. slot number { key = value ... } More than one key-value pair may be used within a slot description. A key-value pair is composed of, .B keyword = value. The following keywords are valid: .TP .BR description A Description of the slot. PKCS#11v2.20 defined this as a 64-byte max character-string. .TP .BR stdll This keyword is used to define the name of the stdll or token library that will be used for this slot. The stdll is an available token library in opencryptoki. .TP .BR manufacturer This keyword is used to name the ID of the slot manufacturer. PKCS#11v2.20 defines this as a 32 byte long string. .TP .BR hwversion Version number of the slot's hardware, if any. The version number is composed of a major version number (the integer portion of the version) and a minor version number (the hundredths portion of the version). For example, version 1.2, major = 1, minor = 2 .TP .BR firmwareversion Version number of the slot's firmware, if any. The version number is composed of a major version number (the integer portion of the version) and a minor version number (the hundredths portion of the version). .TP .BR confname If the slot is associated with a token that has its own configuration file, this option identifies the name of that configuration file. For example, confname=ep11tok.conf .SH Notes The pound sign ('#') is used to indicate a comment. Both the comment character and any text after it, up to the end of the line, are ignored. The comment character cannot be used inside the brackets of slot descriptions, as this will cause a syntax error. .SH "SEE ALSO" .PD 0 .TP \fBopencryptoki\fP(7), .TP \fBpkcsslotd\fP(8), .PD opencryptoki+dfsg/man/man5/Makefile.am0000644000175000017500000000012212630407153016740 0ustar xnoxxnoxman5_MANS=opencryptoki.conf.5 EXTRA_DIST = $(man5_MANS) CLEANFILES = $(man5_MANS) opencryptoki+dfsg/man/man1/0000755000175000017500000000000012630407153014705 5ustar xnoxxnoxopencryptoki+dfsg/man/man1/pkcsconf.1.in0000644000175000017500000000262412630407153017206 0ustar xnoxxnox.TH PKCSCONF 1 "May 2007" "@PACKAGE_VERSION@" "openCryptoki" .SH NAME pkcsconf \- configuration utility for the pkcsslotd daemon .SH SYNOPSIS \fBpkcsconf\fP [\fB-itsmlIupPh\fP] [\fB-c\fP \fIslotnumber\fP \fB-U\fP \fIuserPIN\fP \fB-S\fP \fISOPin\fP \fB-n\fP \fInewpin\fP] .SH DESCRIPTION The \fBpkcsconf\fP utility displays and configures the state of the pkcsslotd daemon and the tokens managed by the daemon. .SH "COMMAND SUMMARY" .IP "\fB-i\fP" 10 display PKCS11 info .IP "\fB-t\fP" 10 display token info .IP "\fB-s\fP" 10 display slot info .IP "\fB-m\fP" 10 display mechanism list .IP "\fB-l\fP" 10 display slot description .IP "\fB-I\fP" 10 initialize token .IP "\fB-u\fP" 10 initialize user PIN .IP "\fB-p\fP" 10 set the user PIN .IP "\fB-P\fP" 10 set the SO PIN .IP "\fB-c\fP \fISLOT\fP" 10 specify the token slot for the operation .IP "\fB-U\fP \fIUSERPIN\fP" 10 the current user pin (for use when changing the user pin; -u and -p options); if not specified, user will be prompted .IP "\fB-S\fP \fISOPIN\fP" 10 the current Security Officer (SO) pin (for use when changing the SO pin; -P option); if not specified, user will be prompted .IP "\fB-n\fP \fINEWPIN\fP" 10 the new pin (for use when changing either the user pin or the SO pin; -u, -p and -P options); if not specified, user will be prompted .IP "\fB-h\fP" 10 show usage information .SH SEE ALSO .PD 0 .TP \fBopencryptoki\fP(7), .TP \fBpkcsslotd\fP(8). .PD opencryptoki+dfsg/man/man1/pkcsep11_migrate.1.in0000644000175000017500000000362012630407153020534 0ustar xnoxxnox.TH PKCSEP11_MIGRATE 1 "Jan 2014" "@PACKAGE_VERSION@" "openCryptoki" .SH NAME pkcsep11_migrate \- utility to re-encrypt EP11 token keys to prepare a change of master keys in the EP11 adapter .SH SYNOPSIS \fBpkcep11_migrate\fP [\fB-h\fP] [\fB-slot\fP \fIslot-number\fP \fB-adapter\fP \fIadapter-ID\fP \fB-domain\fP \fIdomain-ID\fP ] .SH DESCRIPTION In case of a Master key change within an EP11 adapter all key objects that are wrapped with this master key must be re-wrapped or re-encrypted. The \fBpkcsep11_migrate\fP utility takes all EP11 token related key objects that are wrapped with the EP11 adapter master key, decrypts each key object with the current master key and encrypt it with the new master key. Notes: .br 1. The new master key must be set and committed on the EP11 adapter via Trusted Key Entry console (TKE) before using this utility. .br 2. While using this tool no process using the EP11 token should be running. .br 3. Before using this tool make a back-up of the token objects in ep11tok/TOK_OBJ/. .br 4. After successfully execution of the migrate utility and before (re)starting programs using the EP11 token the new master key must be activated using the TKE. .SH "COMMAND SUMMARY" .IP "\fB-slot\fP \fIslot-number\fP" 10 specifies the token slot of the EP11 token .IP "\fB-adapter\fP \fIadapter-ID\fP" 10 specifies an EP11 adapter ID. (Refer to lszcrypt to get a list of installed crypto adapters. The adapter ID will be the number xx in 'card\fBxx\fP' from the output.) This value can be provided either in hexadecimal (e.g. 0x0A) or decimal (10) notation. .IP "\fB-domain\fP \fIdomain-ID\fP" 10 specifies the usage domain for the EP11 adapter. (see /sys/bus/ap/ap_domain.) This value can be provided either in hexadecimal (e.g. 0x0B) or decimal (11) notation. .IP "\fB-h\fP" 10 show usage information .SH SEE ALSO .PD 0 .TP \fBpkcsconf\fP(1), .TP \fBopencryptoki\fP(7), .TP \fBpkcsslotd\fP(8). .PD opencryptoki+dfsg/man/man1/pkcsicsf.1.in0000644000175000017500000000515012630407153017202 0ustar xnoxxnox.TH PKCSICSF 1 "April 2013" "@PACKAGE_VERSION@" "openCryptoki" .SH NAME pkcsicsf \- configuration utility for the ICSF token .SH SYNOPSIS \fBpkcsicsf\fP [\fB-h\fP] [\fB-l|-a\fP \fItoken name\fP] [\fB-b\fP \fIBINDDN\fP] [\fB-c\fP \fIclient-cert-file\fP] [\fB-C\fP \fICA-cert-file\fP] [\fB-k\fP \fIprivatekey\fP] [\fB-m\fP \fImechanism\fP] [\fB-u\fP \fIURI\fP] .SH DESCRIPTION The \fBpkcsicsf\fP utility lists available ICSF tokens and allows user to add one specific ICSF token to opencryptoki. The ICSF token must be added first to opencryptoki. This creates an entry in the opencryptoki.conf file for the ICSF token. It also creates a \fItoken_name.conf\fP configuration file in the same directory as the opencryptoki.conf file, containing ICSF specific information. This information is read by the ICSF token. The ICSF token must bind and authenticate to an LDAP server. The supported authentication mechanisms are simple and sasl. One of these mechanisms must be entered when listing the available ICSF tokens or when adding an ICSF token. Opencryptoki currently supports adding only one ICSF token. The system admin can either allow the ldap calls to utilize exisiting ldap configs, such as ldap.conf or .ldaprc for bind and authentication information or set the bind and authentication information within opencryptoki by using this utility and its options. The information will then be placed in the \fItoken_name.conf\fP file to be used in the ldap calls. When using simple authentication, the user will be prompted for the racf password when listing or adding a token. .SH "OPTIONS" .IP "\fB-a\fP \fItoken name\fp" 10 add the specified ICSF token to opencryptoki. .IP "\fB-b\fP \fIBINDND\fp" 10 the distinguish name to bind when using simple authentication .IP "\fB-c\fP \fIclient-cert-file" 10 the client certificate file when using SASL authentication .IP "\fB-C\fP \fICA-cert-file\fp" 10 the CA certificate file when using SASL authentication .IP "\fB-h\fP" 10 show usage information .IP "\fB-k\fP \fIprivatekey\fP" 10 the client private key file when using SASL authentication .IP "\fB-m\fP \fImechanism\fp" 10 the authentication mechanism to use when binding to the LDAP server (this should be either \fBsimple\fP or \fBsasl\fP) .IP "\fB-l\fP" 10 list available ICSF tokens .IP "\fB-h\fP" 10 show usage information .SH "FILES" .IP "/etc/opencryptoki/opencryptoki.conf" the opencryptoki config file containing token configuration information .IP "/etc/opencryptoki/\fItoken_name.conf\fP" contains ICSF configuration information for the ICSF token .SH SEE ALSO .PD 0 .TP \fBopencryptoki\fP(7), .TP \fBpkcsslotd\fP(8). .TP \fBpkcsconf\fP(8). .PD opencryptoki+dfsg/man/man1/Makefile.am0000644000175000017500000000016112630407153016737 0ustar xnoxxnoxman1_MANS=pkcsconf.1 pkcsicsf.1 pkcsep11_migrate.1 pkcscca.1 EXTRA_DIST = $(man1_MANS) CLEANFILES = $(man1_MANS) opencryptoki+dfsg/man/man1/pkcscca.1.in0000644000175000017500000000414412630407153017006 0ustar xnoxxnox.TH PKCSCCA 1 "September 2014" "@PACKAGE_VERSION@" "openCryptoki" .SH NAME pkcscca \- configuration utility for the CCA token .SH SYNOPSIS .SS "VERSION MIGRATION" \fBpkcscca\fP [\fB-m v2objectsv3\fP] [\fIOPTIONS\fP] .SS "KEY MIGRATION" \fBpkcscca\fP [\fB-m keys\fP] [\fB-s SLOTID\fP] [\fB-k aes|apka|asym|sym\fP] [\fIOPTIONS\fP] .SH DESCRIPTION The \fBpkcscca\fP utility assists in administering the CCA token. In verion 2 of opencryptoki, CCA private token objects were encrypted in CCA hardware. In version 3 these objects are encrypted in software. The \fBv2objectsv3\fP migration option migrates these v2 objects by decrypting them in CCA hardware using a secure key and then re-encrypting them in software using a software key. Afterwards, v2 objects can be accessed in version 3. There may be situations where CCA master keys must be changed. All CCA secret and private keys are wrapped with a master key. After a CCA master key is changed, keys wrapped with the old master key need to be re-wrapped with the current master key. The \fBkeys\fP migration option migrates these wrapped keys by unwrapping them with the old master key and wrapping them with the current master key. .SH "GENERAL OPTIONS" .IP "\fB-d|--datastore\fP \fIdirectory\fp" 10 the directory where the CCA token information is kept. This directory will be used to locate the private token objects to be migrated. i.e. /var/lib/opencryptoki/ccatok .IP "\fB-v|--verbose\fP" 5 Provide more detailed output .SH "VERSION MIGRATION" .IP "\fB-m v2objectsv3\fP" 5 Migrates CCA private token objects from CCA encryption (used in v2) to software encryption (used in v3). .SH "KEY MIGRATION" .IP "\fB-m keys\fP" 5 Unwraps private keys with an old CCA master key and wraps them with a new CCA master key. .IP "\fB-k aes|apka|asym|sym\fP" 5 Migrate keys wrapped with the selected master key type. .IP "\fB-s|--slotid\fP \fISLOTID\fP" 5 The PKCS slot number. .SH "FILES" .IP "/var/lib/opencryptoki/ccatok/TOK_OBJ/OBJ.IDX" contains current list of public and private token objects for the CCA token. .SH SEE ALSO .PD 0 .TP \fBREADME.cca_stdll\fP (in system's doc directory) .PD opencryptoki+dfsg/man/man7/0000755000175000017500000000000012630407153014713 5ustar xnoxxnoxopencryptoki+dfsg/man/man7/opencryptoki.7.in0000644000175000017500000000236712630407153020146 0ustar xnoxxnox.TH OPENCRYPTOKI 7 "May 2007" "@PACKAGE_VERSION@" "openCryptoki" .SH NAME openCryptoki \- A PKCS#11 implementation. .SH DESCRIPTION \fBopenCryptoki\fP is an implementation of the PKCS#11 API standard. It provides an interface to the functions of underlying cryptographic tokens, which may be implemented via software or hardware. The PKCS#11 specification has been released by RSA Labs. More information on PKCS#11 can be found on the RSA labs website: http://www.rsa.com/rsalabs. To use openCryptoki, run the \fIpkcsslotd\fP daemon. The daemon will read the \fIopencryptoki.conf\fP file to collect information about the tokens and their slots. Use the \fIpkcsconf\fP utility to further configure openCryptoki once the daemon is running. .SH "SECURITY NOTE" All non-root users that require access to PKCS#11 tokens using openCryptoki must be assigned to the \fIpkcs11\fP group to be able to communicate with the \fIpkcsslotd\fP daemon. Only fully trusted users should be granted membership in the group. Group members can block other openCryptoki users from accessing PKCS#11 tokens, and execute arbitrary code with the privileges of other openCryptoki users. .SH "SEE ALSO" .PD 0 .TP \fBpkcsslotd\fP(8), .TP \fBpkcsconf\fP(1), .TP \fBopencryptoki.conf\fP(5). .PD opencryptoki+dfsg/man/man7/Makefile.am0000644000175000017500000000011512630407153016744 0ustar xnoxxnoxman7_MANS=opencryptoki.7 EXTRA_DIST = $(man7_MANS) CLEANFILES = $(man7_MANS) opencryptoki+dfsg/man/man8/0000755000175000017500000000000012630407153014714 5ustar xnoxxnoxopencryptoki+dfsg/man/man8/pkcsslotd.8.in0000644000175000017500000000225312630407153017422 0ustar xnoxxnox.TH PKCSSLOTD 8 "May 2007" "@PACKAGE_VERSION@" "openCryptoki" .SH NAME pkcsslotd - shared memory manager for opencryptoki .SH DESCRIPTION The \fBpkcsslotd\fP daemon manages PKCS#11 objects between PKCS#11-enabled applications. When 2 or more processes are accessing the same cryptographic token, the daemon is notified and updates each application when the token's objects change. .SH NOTES Only one instance of the pkcsslotd daemon should be running on any given host. If a prior instance of pkcsslotd did not shut down cleanly, then it may leave an allocated shared memory segment on the system. The allocated memory segment can be identified by its key and can be safely removed once the daemon is stopped with the ipcrm command, such as: \fIipcrm -M 0x6202AB38\fP The daemon creates the shared memory segment with group ownership by the \fIpkcs11\fP group. All non-root users that should be able to use openCryptoki need to be members of the group. Only trusted users should be assigned to the group, see the "SECURITY NOTE" in the \fBopencryptoki\fP(7) manual page for details. .SH "SEE ALSO" .PD 0 .TP \fBopencryptoki\fP(7), .TP \fBopencryptoki.conf\fP(5), .TP \fBpkcsconf\fP(1), .PD opencryptoki+dfsg/man/man8/Makefile.am0000644000175000017500000000011212630407153016742 0ustar xnoxxnoxman8_MANS=pkcsslotd.8 EXTRA_DIST = $(man8_MANS) CLEANFILES = $(man8_MANS) opencryptoki+dfsg/man/Makefile.am0000644000175000017500000000003712630407153016105 0ustar xnoxxnoxSUBDIRS = man1 man5 man7 man8 opencryptoki+dfsg/INSTALL0000644000175000017500000001477412630407153014344 0ustar xnoxxnoxBasic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `sh ./bootstrap.sh', then type `./configure' to configure the package for your system. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the pkcs11 API in `/usr/lib/pkcs11/', any STDLLs that were built in `/usr/lib/pkcs11/stdll', the config programs in `/usr/lib/pkcs11/methods', and the slot daemon in `/usr/sbin/'. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. Optional Features ================= For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. opencryptoki+dfsg/ChangeLog0000644000175000017500000001616712630407153015063 0ustar xnoxxnox* opencryptoki 3.4.1 - fix 32-bit compiler error for ep11 - fix buffer overflow for cca token - fix a testcase * opencryptoki 3.4 - CCA master key migration added to the pkcscca tool. When the masterkey on the CCA adapter changes, this allows the token key objects containing keys wrapped with the card's former masterkey to be wrapped under the card's new masterkey. And thus "migrated". - AES GCM support added to ica token. - Ability to generate generic secret keys for CKM_GENERIC_SECRET_KEY_GEN added to opencryptoki. - The soft, cca, ep11, and icsf tokens support HMAC single and multipart for SHA1, SHA256, SHA384, and SHA512. - CCA token, a secure key token, can now import AES, DES3 and Genric Secret keys. - Add -Wall and fix various compiler warnings. - Coverity scan cleanup. - Additional test vectors and various testcase improvements made. - Various bugfixes * opencryptoki 3.3 - Dynamic tracing introduced via the new environment variable, OPENCRYPTOKI_TRACE_LEVEL=. The opencryptoki base as well as all tokens changed to use the new tracing. - Allow root to run pkcs11 commands without being in pkcs11 group. - EncryptUpdate, DecryptUpdate, DigestUpdate, SignUpdate, VerifyUpdate now allow zero length data. - Refactored ICA token's SHA . - Various testcase improvements. - Various bugfixes. * opencryptoki 3.2 - New pkcscca tool. Currently it assists in migrating cca private token objects from opencryptoki version 2 to the clear key encryption method used in opencryptoki version 3. Includes a manpage for pkcscca tool. Changes to README.cca_stdll to assist in using the CCA token and migrating the private token objects. - Support for CKM_RSA_PKCS_OAEP and CKM_RSA_PKCS_PSS algorithms. - Various bugfixes. - New testcases for various crypto algorithms. * opencryptoki-3.1 - New ep11 token to support IBM Crypto Express adpaters (starting with Crypto Express 4S adapters) configured with Enterprise PKCS#11(EP11) firmware. - New pkcsep11_migrate utility (and manpage) to migrate token objects when card's masterkey changes. - Various bugfixes. * opencryptoki-3.0 - Aggregated source files in common, tpm, and cca directories. - Re-factored shared memory functions in the stdlls. - New opencryptoki.conf file to replace pk_config_data and pkcs11_starup. The opencryptoki.conf contains slot entry information for tokens. - New manpage for opencryptoki.conf - Removed pkcs_slot and pkcs11_startup shell scripts. - New ICSF token to do remote crypto. - New pkcsicsf utility to setup the ICSF token. - New manpage for pkcsicsf utility. - ICA token supports CKM_DES_OFB64, CKM_DES_CFB8, CKM_DES_CFB6 mechanisms using 3DES keys. - ICA token supports CKM_DES3_MAC and CKM_DES3_MAC_GENERAL mechanisms. - ICA token supports CKM_AES_OFB, CKM_AES_CFB8, CKM_AES_CFB64, CKM_AES_CFB128, CKM_AES_MAC, and CKM_AES_MAC_GENERAL mechanisms. - Some code cleanup in pkcsslotd. - pkcsslotd daemon uses a socket rather than shared memory to pass slot information to the opencryptoki library. - New testcases added for various crypto algorithms and pkcs#11 api calls. - Add README to docs directory for how to setup ICSF token. * opencryptoki-2.4.3.1 (May 17, 2013) - Allow imported rsa private keys in cca to also decrypt. * opencryptoki-2.4.3 (April 29, 2013) - CKM_SHA256_RSA_PKCS,CKM_SHA384_RSA_PKCS,CKM_SHA512_RSA_PKCS support for ICA token. - Allow import of RSA public and private keys into CCA token. - Systemd support added. - Various bugfixes and additional testcases. * opencryptoki-2.4.2 (April 27, 2012) - Re-factored spinlocks, such that each token has its own spinlock in its own directory relative to /var/locks/opencryptoki. * opencryptoki-2.4.1 (February 21, 2012) - SHA256 support added for CCA token - Several crypto algorithm testcases refactored to include published test vectors. - Testcase directory restructured for future improvements. - Allow tpm stdll to get SRK passwd and mode from new env variables. See [1] for info on how to use this feature and please report any bugs. - Renamed spinlocks for shared memory to /var/lock dir and did some cleanup of unused locking schemes. - Various bugfixes and cleanup. [1] http://opencryptoki.git.sourceforge.net/git/gitweb.cgi?p=opencryptoki/opencryptoki;a=blob;f=doc/README.tpm_stdll;h=dda0d2263cfbb3df8c65ebc64b8006e3242f6321;hb=HEAD#l58 * opencryptoki-2.4 - Support for Elliptic Curve Support in CCA token. - Support for AES CTR in ICA token. - Session handling refactored from using a reference to memory to using a handle that references a binray tree node. - Cleanup logging. Debug messages now go to a file referenced in OPENCRYPTOKI_DEBUG_FILE env variable. - Various bugfixes and cleanup. * opencryptoki-2.3.3 (Jan 13 2011) - Moderate fixes and clean-ups to key unwrapping mechanisms - several pkcsconf fixes, some minor changes - Important fix to CCA library name in pkcs11_startup - PKCS padding length fix for symmetric ciphers - Better RSA public exponent validations in all supported tokens - Huge testsuite refactor - Several other minor fixes and cleanups * opencryptoki-2.3.2 (Jul 29 2010) - Significant clean-ups to the building and packaging systems and many small fixes by Klaus Heinrich Kiwi - Various minor fixes to slot daemon and init script by Dan Horák - Some RSA PKCS#1 v1.5 padding clean-ups by Ramon de Carvalho Valle - Human-readable flags output to pkcsconf, some minor soft-token fixes by Kent Yoder - Improved overall session/object look-up performance. Note that this change might crash buggy callers with badly-written session/object handle tracking - Klaus Heinrich Kiwi * openCryptoki-2.3.1 - Moved ICA token to use libica-2.0, supporting newer hardware and 4K RSA modulus. Libica-2.x is now *required* to build the ICA token. - Moved CCA token to use CCA-4.0, supporting AES, SHA-2 and 4K RSA keys in newer hardware. Although not required for building, CCA-4.0 is *required* for running the CCA token. * openCryptoki-2.2.5 - Fixed bug in comparison of PINs in pkcsconf. - Added code to set the encryption and signature schemes of keys imported into the TPM token. - Added tpm token message to warn when only owner can read the pub SRK. - Fixed return code of function failed when it should be buffer too small in various mech_des.c mech_des3.c and mech_aes.c files. - Moved doc/*.txt to manpage format and integrated them into the build/install - Updated testcases to query env vars for PINs and call a set of common routines for common operations - Added SHA256 support for all tokens - Fixed object cleanup when max number of token objects is hit - Fixed fd exhaustion bug with spin lock fd - Updated TPM stdll for TSS policy handling changes. Trousers 0.2.9+ now required with openCryptoki 2.2.5 - Updated TPM stdll to use TSS_TSPATTRIB_KEYINFO_RSA_MODULUS when retrieving the public modulus - pkcs11_startup fix for use with s/w fallback support in libica on s390 - Added the CCA secure key token and migration utility - Replaced bcopy/bzero with memcpy/memset throughout the code - Removed unused variables throughout the code * openCryptoki-2.2.4 opencryptoki+dfsg/NEWS0000644000175000017500000000523312630407153014000 0ustar xnoxxnoxVERSION 3.2 ADDITIONS: - A new tool to assist in administering the CCA token in opencryptoki. Currently it only assists in migrating CCA token's private token objects from version 2 to version 3. Prior to opencryptoki version 3, the CCA token encrypted its private token objects with a secure key in hardware. In version 3, it encrypts its private token objects with a clear key in software. Version 2 private token objects will require migration to version 3, if they wished to be used in version 3. VERSION 3.1 ADDITIONS: - New ep11 token. Please see doc/README.ep11_stdll for additional information about the ep11 token. - New pkcsep11_migrate utility to assist in migrating token objects stored on disk, when the hardware's masterkey changes. VERSION 3 CHANGES: - New ICSF token. Please see doc/README.icsf_stdll for additional information and how to set up the ICSF token. - New pkcsicsf utility that is used to set up the ICSF token. See its man page and doc/README.icsf_stdll for additional info. - No longer required to run pkcs11_startup. pkcs11_startup and pkcs_slotd were shell scripts that created the config file, pk_config_data, which was read by pkcsslotd to get available slot information. The pk_config_data configuration file has been replaced with /etc/opencryptoki/opencryptoki.conf. In version 3, the pkcsslotd daemon reads opencryptoki.conf to get slot information. The opencryptoki.conf by default contains slot information for each token currently supported by opencryptoki with the exception of the ICSF token, which requires some initial setup. Please see man page for opencryptoki.conf for further information. Since pk_config_data is no longer required, pkcs11_startup and pkcs_slotd have been removed. - The pkcsslotd daemon uses a socket rather than shared memory to transfer slot information to the opencryptoki library. Some shared memory usage still exists in pkcsslotd. Perhaps in time, the remaining need for shared memory in pkcsslotd can also be removed. - Ensure that the pkcs11 group has been created and that root has been added to the group. The pkcs11_startup script used to check and do this, but is now obsolete. NOTICEABLE CHANGES MADE PRIOR to VERSION 3: - Opencryptoki creates several new directories and lock files in /var/lock/opencryptoki directory. Each token creates and uses a lockfile to protect data in shared memory. - RSA keys may be imported into the CCA token. - Opencryptoki contains systemd support. Note: Ensure the opencryptoki lockfiles have been entered into tmpfiles.d to keep them persistant across reboots. opencryptoki+dfsg/COPYRIGHTS0000644000175000017500000000336612630407153014724 0ustar xnoxxnoxBase openCryptoki Code and IBM submissions (C) COPYRIGHT International Business Machines Corp. 2001, 2006 For Code originating from AEP Systems Ltd. * Copyright (c) 1999-2002 AEP Systems Ltd. * Bray Business Park, Southern Cross Route, Bray, Co. Wicklow, Ireland. * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of AEP Systems Ltd. nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.