pax_global_header00006660000000000000000000000064132436075410014517gustar00rootroot0000000000000052 comment=8aab1bf053ebd3d0a393d0ba1abc8b73976f0ce2 openssl-ibmca-1.4.1/000077500000000000000000000000001324360754100142565ustar00rootroot00000000000000openssl-ibmca-1.4.1/.gitignore000066400000000000000000000002121324360754100162410ustar00rootroot00000000000000build-aux autom4te.cache .deps .libs *.m4 *.lo *.la *.o *.tar.gz Makefile Makefile.in config.status config.log configure libtool cscope.* openssl-ibmca-1.4.1/AUTHORS000066400000000000000000000000441324360754100153240ustar00rootroot00000000000000Mike Halcrow openssl-ibmca-1.4.1/CONTRIBUTING.md000066400000000000000000000052271324360754100165150ustar00rootroot00000000000000# How to contribute Patches are more than welcome, even to fix a bug or to add a new feature. Below are a few guidelines we ask of contributors to follow. ## Getting started * Submit a [ticket](https://github.com/opencryptoki/openssl-ibmca/issues) for your issue, assuming one does not already exist. * Clearly describe the issue, including steps to reproduce when it is a bug. * Make sure you fill in the earliest version that you know has the issue. * Include information from your environment (OS, openssl-ibmca version, libica version, and any other related packages version). * Fork the repository on GitHub. ## Making changes These are not mandatory, but try to follow the steps bellow as good practices to contribute to (any open source) project: * Create a topic/issue branch from the `master` branch. ``` $ git checkout master Switched to branch 'master' Your branch is up-to-date with 'origin/master'. $ git checkout -t -b new_branch Branch new_branch set up to track local branch master. Switched to a new branch 'new_branch' $ ``` * Please avoid working directly on the `master` branch. * If the changes are too big, please separate it into smaller, logical, commits. This will improve commit history and code review. * Follow the [coding style](docs/coding_style.md) guidelines. * Check for unnecessary whitespace with `git diff --check` before committing. * Make sure your commit messages are in the proper format and sign your patch. * Use GitHub [auto-closing]( https://help.github.com/articles/closing-issues-via-commit-messages/) keywords in the commit message, make the commit message body as descriptive as necessary limited to 80 columns, and signoff your patch. Ex: ``` Add CONTRIBUTING guidelines The CONTRIBUTING.md file describes the guidelines that every Contributor must follow to get their code integrated into OpenSSL-ibmca. This will improve Contributors/Maintainers work. Fixes #6 Signed-off-by: YOUR_NAME ``` ## Submitting Changes * [Signoff](https://git-scm.com/docs/git-commit#git-commit---signoff) your commits, as mentioned above. * There are two ways to submit patches: * If you prefer the old school way of sending patches to a mailing-list, then feel free to send your patch to the [technical discussion mailing-list]( https://sourceforge.net/projects/opencryptoki/lists/opencryptoki-tech). We will keep you posted as the code review goes by. * If you like GitHub and all the tools it has (like the Maintainers do), then submit a [Pull Request]( https://help.github.com/articles/creating-a-pull-request/). * Wait for your patch review and the Maintainers feedback about your changes. openssl-ibmca-1.4.1/ChangeLog000066400000000000000000000026461324360754100160400ustar00rootroot00000000000000* openssl-ibmca 1.4.1 - Fix structure size for aes-256-ecb/cbc/cfb/ofb - Update man page - Switch to ibmca.so filename to allow standalone use - Switch off Libica fallback mode if available - Make sure ibmca_init only runs once - Provide simple macro for DEBUG_PRINTF possibility - Cleanup and slight rework of function set_supported_meths * openssl-ibmca 1.4.0 - Re-license to Apache License v2.0 - Fix aes_gcm initialization. - Update man page. - Add macros for OpenSSL 0.9.8 compat. - Remove AC_FUNC_MALLOC from configure.ac - Add compat macro for OpenSSL 1.0.1e-fips. - Setting 'foreign' strictness for automake. - Add AES-GCM support. - Rework EVP_aes macros. - Remove dependency of old local OpenSSL headers. - Fix engine initialization to set function pointers only once. - Update .gitignore file. - Remove blank COPYING and NEWS files. - Remove INSTALL and move its content to README.md - Update README.md file to make use of markdown. - Rename README file to README.md to use markdown - Add CONTRIBUTING guidelines. - Adding coding style documentation. - Enable EVP_MD_FLAG_FIPS flag for SHA-*. - Initialize rsa_keygen in RSA_METHOD for openssl < 1.1.0 - Fix SHA512 EVP digest struct to use EVP_MD_FLAG_PKEY_METHOD_SIGNATURE when using OpenSSL 1.0 - Fix wrong parenthesis - convert libica loading to dlopen() and friends - Add support to DSO on new API of OpenSSL-1.1.0 * openssl-ibmca 1.3.1 - Support OpenSSL-1.1 and older versions openssl-ibmca-1.4.1/LICENSE000066400000000000000000000220311324360754100152610ustar00rootroot00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 2. You must cause any modified files to carry prominent notices stating that You changed the files; and 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) 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. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS openssl-ibmca-1.4.1/Makefile.am000066400000000000000000000001401324360754100163050ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src EXTRA_DIST = openssl-ibmca.spec bootstrap.sh cleanup.sh openssl-ibmca-1.4.1/README.md000066400000000000000000000060601324360754100155370ustar00rootroot00000000000000# OpenSSL-ibmca OpenSSL engine that uses the libica library under s390x to accelerate cryptographic operations. ## Requirements The build requirements are: * openssl-devel >= 0.9.8 * libica-devel >= 3.1.1 * autoconf * automake * libtool The runtime requirements are: * openssl >= 0.9.8 * libica >= 3.1.1 ## Installing ``` $ ./configure [--enable-debug] $ make $ sudo make install ``` This will configure, build and install the package in a default location, which is `/usr/local/lib`. It means that the ibmca.so will be installed in `/usr/local/lib/ibmca.so` by default. If you want to install it anywhere else, run "configure" passing the new location via prefix argument, for example: ``` $ ./configure --prefix=/usr --libdir=/usr/lib64/openssl/engines ``` ## Enabling IBMCA Included in this package there is a sample `openssl.cnf` file (`openssl.cnf.sample`), which can be used to turn on use of the IBMCA engine in apps where OpenSSL config support is compiled in. In order to enable IBMCA, use the following instructions to apply the configurations from `openssl.cnf.sample` to the `openssl.cnf` file installed in the host by the OpenSSL package. **WARNING:** you may want to save the original `openssl.cnf` file before changing it. In `openssl.cnf.sample`, the *dynamic_path* variable is set to the default location, which is `/usr/local/lib/ibmca.so` by default. However, if the ibmca.so library has been installed anywhere else, then update the *dynamic_path* variable. Locate where the `openssl.cnf` file has been installed in the host and append the content of the `openssl.cnf.sample` file to it. ``` $ rpm -ql openssl | grep openssl.cnf $ cat openssl.cnf.sample >> /path/to/openssl.cnf ``` In `openssl.cnf` file, move the *openssl_conf* variable from the bottom to the top of the file, such as in the example below: ``` HOME = . RANDFILE = $ENV::HOME/.rnd openssl_conf = openssl_def ``` Finally, check if the IBMCA is now enabled. The command below should return the IBMCA engine and all the supported cryptographic methods. ``` $ openssl engine -c (dynamic) Dynamic engine loading support (ibmca) Ibmca hardware engine support [RAND, DES-ECB, DES-CBC, DES-OFB, DES-CFB, DES-EDE3, DES-EDE3-CBC, DES-EDE3-OFB, DES-EDE3-CFB, AES-128-ECB, AES-192-ECB, AES-256-ECB, AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-OFB, AES-192-OFB, AES-256-OFB, AES-128-CFB, AES-192-CFB, AES-256-CFB, id-aes128-GCM, id-aes192-GCM, id-aes256-GCM, SHA1, SHA256, SHA512] $ ``` ## Support To report a bug please submit a [ticket](https://github.com/opencryptoki/openssl-ibmca/issues) including the following information in the issue description: * bug description * distro release * openssl-ibmca package version * libica package version * steps to reproduce the bug Regarding technical or usage questions, send email to [opencryptoki-tech]( https://sourceforge.net/p/opencryptoki/mailman/opencryptoki-tech) or [opencryptoki-users]( https://sourceforge.net/p/opencryptoki/mailman/opencryptoki-users) mailing list respectively. ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md). openssl-ibmca-1.4.1/bootstrap.sh000077500000000000000000000011761324360754100166370ustar00rootroot00000000000000#!/bin/sh # # Copyright [2005-2017] International Business Machines Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # autoreconf -iv openssl-ibmca-1.4.1/cleanup.sh000077500000000000000000000016021324360754100162430ustar00rootroot00000000000000#!/bin/sh # # Copyright [2005-2017] International Business Machines Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # set -x if [ -f Makefile ] ; then make -k clean fi rm -rf build-aux rm -rf autom4te.cache rm m4/* aclocal.m4 rm configure rm config.* rm libtool find . -name Makefile -exec rm {} \; find . -name Makefile.in -exec rm {} \; find . -depth -name .deps -exec rm -rf {} \; openssl-ibmca-1.4.1/configure.ac000066400000000000000000000034661324360754100165550ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # See autoconf and autoscan online documentation for details. AC_INIT([openssl-ibmca], [1.4.1], [opencryptoki-users@lists.sf.net]) AC_CONFIG_SRCDIR([src/e_ibmca.c]) # sanity check AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign]) # Cmdline arguments. AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], [turn on debugging flags (default is off)])], [enable_debug="yes"],) if test "x$enable_debug" == "xyes"; then CFLAGS="$CFLAGS -O0 -g -DDEBUG -Wall" AC_MSG_RESULT([*** Enabling debugging at user request ***]) else CFLAGS="$CFLAGS -O2 -Wall" fi # Checks for programs. AC_DISABLE_STATIC AC_PROG_CC LT_INIT # Checks for libraries. AC_CHECK_LIB([crypto], [RAND_add], [], AC_MSG_ERROR([*** openssl >= 0.9.8 is required ***])) AC_CHECK_LIB([ica], [ica_get_functionlist], [], AC_MSG_ERROR([*** libica >= 2.4.0 is required ***])) # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h fcntl.h malloc.h netdb.h netinet/in.h stddef.h stdlib.h \ string.h strings.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h unistd.h]) AC_CHECK_HEADER([ica_api.h], [], AC_MSG_ERROR([*** libica-devel >= 2.4.0 is required ***])) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL AC_C_INLINE AC_TYPE_SIZE_T AC_TYPE_SSIZE_T # Checks for library functions. AC_CHECK_FUNCS([gethostbyaddr gethostbyname memset strcasecmp strncasecmp strstr malloc]) AC_CHECK_DECLS([ICA_FLAG_DHW,ica_get_functionlist,ica_open_adapter,DES_ECB], [], AC_MSG_ERROR([*** libica >= 2.4.0 and libica-devel >= 2.4.0 are required ***]), [#include ]) AC_CONFIG_FILES([ Makefile src/Makefile src/doc/Makefile]) AC_OUTPUT echo "CFLAGS=$CFLAGS" openssl-ibmca-1.4.1/docs/000077500000000000000000000000001324360754100152065ustar00rootroot00000000000000openssl-ibmca-1.4.1/docs/coding_style.md000066400000000000000000000074201324360754100202160ustar00rootroot00000000000000# Coding Style This document describes the preferred coding style for the openssl-ibmca project. It is based on the OpenCryptoki coding style. Coding style is always of personal taste, but defining one coding style makes the maintenance of the project easier and gives a standard face for the source code. The inspiration and formatting of this document came from the Linux Kernel coding style document, but make no assumption as the coding style differ from each other on some aspects. ## 1. Indentation Tabs are 4 space characters, differently from many projects that define it as 8 characters. The main idea behind this is that 4 characters should give you a clear idea about where a block of control starts and ends. ## 2. Line length To keep the code readable and maintainable, the limit on the length of lines is 80 columns and this is a strongly preferred limit. ## 3. Placing Braces and Spaces Here we follow Kernighan and Ritchie teachings. An opening brace is put last on the line, and put the closing brace first, e.g.: ``` if (x == 0) { do_y(); } ``` This applies to all non-function statement blocks: if, switch, for, while, do. Another example: ``` switch (value) { case 1: return "one"; case 2: return "two"; case 3: return "three"; default: return NULL; } ``` However, there is one special case, functions: their opening brace stays at the beginning of the next line, e.g.: ``` int func(int x) { do_something(); } ``` Follow other examples: ``` do { do_something(); } while (condition); ``` ``` if (x == 1) { do_one(); } else if (x > 1) { do_two(); } else { do_three(); } ``` It is not necessary to use braces when there is only a single statement, e.g.: ``` if (x == 1) do_something(); ``` and ``` if (x == 1) do_something(); else do_something_else(); ``` This does not apply when only one branch in a conditional statement is a single statement. In this, case use braces in all branches, e.g.: ``` if (x == 1) { do_something(); do_something_more(); } else { do_something_else(); } ``` ### 3.1. Spaces Always use a space after these keywords: *if, switch, case, for, do, while*. ``` if (condition) { ... } ``` The following keywords should not have a space between them and their parentheses: *sizeof, typeof*. ``` s = sizeof(struct alg); ``` **Do not** add spaces around (inside) parenthesized expressions, e.g.: ``` if ( x == 1 ) { ... } ``` When declaring a pointer or a function that returns a pointer type, the ``*`` must be put adjacent to the data name or function name, e.g.: ``` int *ptr; void ptrcopy(int *dest, char *src); int *get_address(int *ptr); ``` Use: * one space on each side of the following operators: ``` = + - < > * / % | & ^ <= >= == != ? : ``` * no space after unary operators: ``` & * + - ~ ! ``` * no space before postfix/after prefix increment and decrement operators: ``` ++ -- ``` * no space around the ``.`` and ``->`` structure member operators. **Do not** leave trailing whitespace at the end of lines. ## 4. Naming Avoid using CamelCase. It is preferred to name variables and functions by including an underscore between words, e.g.: ``` int person_counter; ``` ## 5. Commenting Comments in the code make everyone's life easier, but don't be too verbose. Focus on **what** your function does and less on **how** it does. The preferred style for long multi-line comments is: ``` /* * This is a multi-line comment. * * A column of asterisks on the left side, * with beginning and ending almost-blank lines. */ ``` openssl-ibmca-1.4.1/m4/000077500000000000000000000000001324360754100145765ustar00rootroot00000000000000openssl-ibmca-1.4.1/m4/.dont_remove000066400000000000000000000002221324360754100171140ustar00rootroot00000000000000REQUIRED FILE, PLEASE DON'T REMOVE IT. The current configure.ac requires the m4 directory, but git don't save empty directories in the repository openssl-ibmca-1.4.1/openssl-ibmca.spec000066400000000000000000000040151324360754100176660ustar00rootroot00000000000000%global enginesdir %(pkg-config --variable=enginesdir libcrypto) Name: openssl-ibmca Version: 1.4.1 Release: 1%{?dist} Summary: An IBMCA OpenSSL dynamic engine License: ASL 2.0 URL: https://github.com/opencryptoki/openssl-ibmca Source0: https://github.com/opencryptoki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz Requires: openssl >= 0.9.8 libica >= 3.1.1 BuildRequires: openssl-devel >= 0.9.8 libica-devel >= 3.1.1 BuildRequires: autoconf automake libtool ExclusiveArch: s390 s390x %description This package contains a shared object OpenSSL dynamic engine which interfaces to libica, a library enabling the IBM s390/x CPACF crypto instructions. %prep %setup -q -n %{name}-%{version} ./bootstrap.sh %build %configure --libdir=%{enginesdir} %make_build %install %make_install rm -f $RPM_BUILD_ROOT%{enginesdir}/ibmca.la pushd src sed -e 's|/usr/local/lib|%{_libdir}/openssl/engines|' openssl.cnf.sample > openssl.cnf.sample.%{_arch} popd %files %license LICENSE %doc ChangeLog README.md src/openssl.cnf.sample.%{_arch} %{enginesdir}/ibmca.so %{_mandir}/man5/ibmca.5* %changelog * Wed Feb 21 2018 Eduardo Barretto 1.4.1 - Updated to 1.4.1 * Thu Jan 25 2018 Eduardo Barretto - Update engine filename - Spec cleanup * Thu Oct 26 2017 Patrick Steuer - Fix build warning about comma and newlines - Remove INSTALL file from doc - Fix README name on doc * Fri Sep 8 2017 Paulo Vital 1.4.0 - Update new License - Update Source and URL pointing to GitHub - Added support to AES-GCM - Fix bugs/issues * Fri Feb 17 2017 Paulo Vital 1.3.1 - Support OpenSSL-1.1 and older versions * Tue Dec 1 2015 Claudio Carvalho 1.3.0 - openssl-ibmca-1.3.0 release * Mon May 2 2011 Kent Yoder 1.2.0 - updates for s390 MSA4 features, engine version 1.2 * Fri Mar 17 2006 Michael A. Halcrow 1.0.0 - initial version openssl-ibmca-1.4.1/src/000077500000000000000000000000001324360754100150455ustar00rootroot00000000000000openssl-ibmca-1.4.1/src/Makefile.am000066400000000000000000000004271324360754100171040ustar00rootroot00000000000000lib_LTLIBRARIES=ibmca.la ibmca_la_SOURCES=e_ibmca.c e_ibmca_err.c ibmca_la_LIBADD=-ldl ibmca_la_LDFLAGS=-module -version-info 0:2:0 -shared -no-undefined -avoid-version dist_ibmca_la_SOURCES=e_ibmca_err.h EXTRA_DIST = openssl.cnf.sample ACLOCAL_AMFLAGS = -I m4 SUBDIRS = doc openssl-ibmca-1.4.1/src/doc/000077500000000000000000000000001324360754100156125ustar00rootroot00000000000000openssl-ibmca-1.4.1/src/doc/Makefile.am000066400000000000000000000000641324360754100176460ustar00rootroot00000000000000man5_MANS = ibmca.man dist_man5_MANS = $(man5_MANS) openssl-ibmca-1.4.1/src/doc/ibmca.man000066400000000000000000000035511324360754100173660ustar00rootroot00000000000000.\" Process this file with .\" groff -man -Tascii ibmca.5 .TH IBMCA 5 2017-08-24 IBM "IBMCA user manual" .SH NAME IBMCA \- IBMCA is an OpenSSL engine that uses the libica library under s390x to accelerate cryptographic operations. .SH DESCRIPTION IBMCA accelerates cryptographic operations of applications that use OpenSSL. The engine can be configured by the OpenSSL configuration file. .SS openssl.cnf The OpenSSL configuration file can have an IBMCA section. This section includes only OpenSSL configuration options for the IBMCA engine. .SS Control Commands Applications that load an OpenSSL engine can optionally send control commands to the engine. Control Commands are key value pairs. The value can be a string, a numeric integer or be null. See the engine(3) manpage for a mechanism to discover control commands. .SH OPTIONS .SS openssl.cnf Options for the IBMCA section in openssl.cnf: .PP dynamic_path = .I /path/to/ibmca.so .RS Set the path to the IBMCA shared object file allowing OpenSSL to find the file. .RE .PP engine_id = .I name .RS Set the name of the engine. The default name is "ibmca". .RE .IP "init = 0 | 1" OpenSSL will try to initialize the engine if this option is set to 1. If set to 0, OpenSSL will not try to initialize the engine. .PP default_algorithms = ALL | .I mechanisms .RS Redirect all cryptographic operations through the engine or disable types of mechanisms that the engine supports. If ALL is not used, the default_algorithms consists of a comma separated list of .I mechanisms : .B CIPHERS | DIGESTS | RSA | DH | DSA. .PP Only all CIPHERS and/or DIGESTS can be de/activated. Algorithms like AES can not be de/activated independently. .SS Control Command IBMCA does support one optional control command: .PP SO_PATH: .I /path/to/libica.so .RS Replaces the current libica library by an libica library located at SO_PATH. .RE .SH SEE ALSO .B engine(3) openssl-ibmca-1.4.1/src/e_ibmca.c000066400000000000000000003223341324360754100165770ustar00rootroot00000000000000/* * Copyright [2005-2017] International Business Machines Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /* * Digest and Cipher support added by Robert H Burroughs (burrough@us.ibm.com). * * DES/3DES/AES-CFB/OFB support added by Kent Yoder (yoder1@us.ibm.com) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef OPENSSL_NO_HW #ifndef OPENSSL_NO_HW_IBMCA #if OPENSSL_VERSION_NUMBER < 0x10100000L #define OLDER_OPENSSL #endif /* * Here is a DEBUG_PRINTF makro which expands to nothing * at production level and is active only when the * ibmca build is configured with --enable-debug */ #ifdef DEBUG #define DEBUG_PRINTF(...) printf(__VA_ARGS__) #else #define DEBUG_PRINTF(...) do{} while(0) #endif #include #include "e_ibmca_err.h" #define IBMCA_LIB_NAME "ibmca engine" #define LIBICA_SHARED_LIB "libica.so" #define AP_PATH "/sys/devices/ap" /* COMPAT MACROS */ #ifdef OLDER_OPENSSL #define EVP_CIPHER_CTX_get_cipher_data(ctx) ((ctx)->cipher_data) #define EVP_CIPHER_CTX_original_iv(ctx) ((ctx)->oiv) #define EVP_CIPHER_CTX_iv_noconst(ctx) ((ctx)->iv) #define EVP_CIPHER_CTX_encrypting(ctx) ((ctx)->encrypt) #define EVP_CIPHER_CTX_buf_noconst(ctx) ((ctx)->buf) #else #define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN #define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG #define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG #endif #if !defined(NID_aes_128_gcm) || \ !defined(NID_aes_192_gcm) || \ !defined(NID_aes_256_gcm) #ifndef OPENSSL_NO_AES_GCM #define OPENSSL_NO_AES_GCM #endif #endif #ifndef EVP_AEAD_TLS1_AAD_LEN #define EVP_AEAD_TLS1_AAD_LEN 13 #endif #ifndef EVP_MD_FLAG_PKEY_METHOD_SIGNATURE #define EVP_MD_FLAG_PKEY_METHOD_SIGNATURE 0 #endif typedef struct ibmca_des_context { unsigned char key[sizeof(ica_des_key_triple_t)]; } ICA_DES_CTX; typedef struct ibmca_aes_128_context { unsigned char key[sizeof(ica_aes_key_len_128_t)]; } ICA_AES_128_CTX; typedef struct ibmca_aes_192_context { unsigned char key[sizeof(ica_aes_key_len_192_t)]; } ICA_AES_192_CTX; typedef struct ibmca_aes_256_context { unsigned char key[sizeof(ica_aes_key_len_256_t)]; } ICA_AES_256_CTX; typedef struct ibmca_aes_gcm_context { unsigned char key[32]; int key_set; int iv_set; unsigned char tag[16]; unsigned char subkey[16]; unsigned char icb[16]; unsigned char ucb[16]; unsigned long long ptlen; unsigned long long aadlen; unsigned char *iv; int ivlen; int taglen; int iv_gen; int tls_aadlen; } ICA_AES_GCM_CTX; #ifndef OPENSSL_NO_SHA1 #define SHA_BLOCK_SIZE 64 typedef struct ibmca_sha1_ctx { sha_context_t c; unsigned char tail[SHA_BLOCK_SIZE]; unsigned int tail_len; } IBMCA_SHA_CTX; #endif #ifndef OPENSSL_NO_SHA256 #define SHA256_BLOCK_SIZE 64 typedef struct ibmca_sha256_ctx { sha256_context_t c; unsigned char tail[SHA256_BLOCK_SIZE]; unsigned int tail_len; } IBMCA_SHA256_CTX; #endif #ifndef OPENSSL_NO_SHA512 #define SHA512_BLOCK_SIZE 128 typedef struct ibmca_sha512_ctx { sha512_context_t c; unsigned char tail[SHA512_BLOCK_SIZE]; unsigned int tail_len; } IBMCA_SHA512_CTX; #endif static const char *LIBICA_NAME = "ica"; #if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb) #define NID_aes_128_cfb NID_aes_128_cfb128 #endif #if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb) #define NID_aes_128_ofb NID_aes_128_ofb128 #endif #if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb) #define NID_aes_192_cfb NID_aes_192_cfb128 #endif #if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb) #define NID_aes_192_ofb NID_aes_192_ofb128 #endif #if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb) #define NID_aes_256_cfb NID_aes_256_cfb128 #endif #if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb) #define NID_aes_256_ofb NID_aes_256_ofb128 #endif #if defined(NID_des_ofb64) && ! defined (NID_des_ofb) #define NID_des_ofb NID_des_ofb64 #endif #if defined(NID_des_ede3_ofb64) && ! defined (NID_des_ede3_ofb) #define NID_des_ede3_ofb NID_des_ede3_ofb64 #endif #if defined(NID_des_cfb64) && ! defined (NID_des_cfb) #define NID_des_cfb NID_des_cfb64 #endif #if defined(NID_des_ede3_cfb64) && ! defined (NID_des_ede3_cfb) #define NID_des_ede3_cfb NID_des_ede3_cfb64 #endif /* * ibmca_crypto_algos lists the supported crypto algos by ibmca. * This list is matched against all algo support by libica. Only if * the algo is in this list it is activated in ibmca. * The defines can be found in the libica header file. */ static int ibmca_crypto_algos[] = { SHA1, SHA256, SHA512, P_RNG, RSA_ME, RSA_CRT, DES_ECB, DES_CBC, DES_OFB, DES_CFB, DES3_ECB, DES3_CBC, DES3_OFB, DES3_CFB, DES3_CTR, AES_ECB, AES_CBC, AES_OFB, AES_CFB, AES_GCM_KMA, 0 }; #define MAX_CIPHER_NIDS sizeof(ibmca_crypto_algos) /* * This struct maps one NID to one crypto algo. * So we can tell OpenSSL thsi NID maps to this function. */ struct crypto_pair { int nids[MAX_CIPHER_NIDS]; const void *crypto_meths[MAX_CIPHER_NIDS]; }; /* We can not say how much crypto algos are * supported by libica. We can only say the * size is not greater as the supported * crypto algos by ibmca. * The actual number of supported crypto algos * is saved to the size_****_nid variabes */ static size_t size_cipher_list = 0; static size_t size_digest_list = 0; static struct crypto_pair ibmca_cipher_lists; static struct crypto_pair ibmca_digest_lists; static int ibmca_destroy(ENGINE * e); static int ibmca_init(ENGINE * e); static int ibmca_finish(ENGINE * e); static int ibmca_ctrl(ENGINE * e, int cmd, long i, void *p, void (*f) ()); static ica_adapter_handle_t ibmca_handle = 0; /* BIGNUM stuff */ static int ibmca_mod_exp(BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx); static int ibmca_mod_exp_crt(BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * q, const BIGNUM * dmp1, const BIGNUM * dmq1, const BIGNUM * iqmp, BN_CTX * ctx); #ifndef OPENSSL_NO_RSA /* RSA stuff */ static int ibmca_rsa_mod_exp(BIGNUM * r0, const BIGNUM * I, RSA * rsa, BN_CTX *ctx); static int ibmca_rsa_init(RSA *rsa); #endif /* This function is aliased to mod_exp (with the mont stuff dropped). */ static int ibmca_mod_exp_mont(BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx); #ifndef OPENSSL_NO_DSA /* DSA stuff */ #ifdef OLDER_OPENSSL static int ibmca_dsa_mod_exp(DSA * dsa, BIGNUM * rr, BIGNUM * a1, BIGNUM * p1, BIGNUM * a2, BIGNUM * p2, BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * in_mont); static int ibmca_mod_exp_dsa(DSA * dsa, BIGNUM * r, BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx); #else static int ibmca_dsa_mod_exp(DSA * dsa, BIGNUM * rr, const BIGNUM * a1, const BIGNUM * p1, const BIGNUM * a2, const BIGNUM * p2, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * in_mont); static int ibmca_mod_exp_dsa(DSA * dsa, BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx); #endif #endif #ifndef OPENSSL_NO_DH /* DH stuff */ /* This function is alised to mod_exp (with the DH and mont dropped). */ static int ibmca_mod_exp_dh(const DH * dh, BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx); #endif /* RAND stuff */ static int ibmca_rand_bytes(unsigned char *buf, int num); static int ibmca_rand_status(void); /* DES, TDES, AES declarations */ static int ibmca_usable_ciphers(const int **nids); static int ibmca_engine_ciphers(ENGINE * e, const EVP_CIPHER ** cipher, const int **nids, int nid); static int ibmca_init_key(EVP_CIPHER_CTX * ctx, const unsigned char *key, const unsigned char *iv, int enc); static int ibmca_des_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, const unsigned char *in, size_t inlen); static int ibmca_tdes_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, const unsigned char *in, size_t inlen); static int ibmca_aes_128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inlen); static int ibmca_aes_192_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inlen); static int ibmca_aes_256_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inlen); static int ibmca_cipher_cleanup(EVP_CIPHER_CTX * ctx); #ifndef OPENSSL_NO_AES_GCM static int ibmca_aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); static int ibmca_aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len); static int ibmca_gcm_aad(ICA_AES_GCM_CTX *ctx, const unsigned char *aad, size_t len, int enc, int keylen); static int ibmca_aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len); static int ibmca_aes_gcm(ICA_AES_GCM_CTX *ctx, const unsigned char *in, unsigned char *out, size_t len, int enc, int keylen); static int ibmca_aes_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); static int ibmca_aes_gcm_setiv(EVP_CIPHER_CTX *c); static int ibmca_gcm_tag(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, int taglen); #endif /* Sha1 stuff */ static int ibmca_usable_digests(const int **nids); static int ibmca_engine_digests(ENGINE * e, const EVP_MD ** digest, const int **nids, int nid); #ifndef OPENSSL_NO_SHA1 static int ibmca_sha1_init(EVP_MD_CTX * ctx); static int ibmca_sha1_update(EVP_MD_CTX * ctx, const void *data, unsigned long count); static int ibmca_sha1_final(EVP_MD_CTX * ctx, unsigned char *md); static int ibmca_sha1_cleanup(EVP_MD_CTX * ctx); #endif #ifndef OPENSSL_NO_SHA256 static int ibmca_sha256_init(EVP_MD_CTX * ctx); static int ibmca_sha256_update(EVP_MD_CTX * ctx, const void *data, unsigned long count); static int ibmca_sha256_final(EVP_MD_CTX * ctx, unsigned char *md); static int ibmca_sha256_cleanup(EVP_MD_CTX * ctx); #endif #ifndef OPENSSL_NO_SHA512 static int ibmca_sha512_init(EVP_MD_CTX * ctx); static int ibmca_sha512_update(EVP_MD_CTX * ctx, const void *data, unsigned long count); static int ibmca_sha512_final(EVP_MD_CTX * ctx, unsigned char *md); static int ibmca_sha512_cleanup(EVP_MD_CTX * ctx); #endif /* WJH - check for more commands, like in nuron */ /* The definitions for control commands specific to this engine */ #define IBMCA_CMD_SO_PATH ENGINE_CMD_BASE static const ENGINE_CMD_DEFN ibmca_cmd_defns[] = { {IBMCA_CMD_SO_PATH, "SO_PATH", "Specifies the path to the 'atasi' shared library", ENGINE_CMD_FLAG_STRING}, {0, NULL, NULL, 0} }; #ifndef OPENSSL_NO_RSA /* Our internal RSA_METHOD that we provide pointers to */ #ifdef OLDER_OPENSSL static RSA_METHOD ibmca_rsa = { "Ibmca RSA method", /* name */ NULL, /* rsa_pub_enc */ NULL, /* rsa_pub_dec */ NULL, /* rsa_priv_enc */ NULL, /* rsa_priv_dec */ ibmca_rsa_mod_exp, /* rsa_mod_exp */ ibmca_mod_exp_mont, /* bn_mod_exp */ ibmca_rsa_init, /* init */ NULL, /* finish */ 0, /* flags */ NULL, /* app_data */ NULL, /* rsa_sign */ NULL, /* rsa_verify */ NULL /* rsa_keygen */ }; #else static RSA_METHOD *ibmca_rsa = NULL; #endif #endif #ifndef OPENSSL_NO_DSA /* Our internal DSA_METHOD that we provide pointers to */ #ifdef OLDER_OPENSSL static DSA_METHOD ibmca_dsa = { "Ibmca DSA method", /* name */ NULL, /* dsa_do_sign */ NULL, /* dsa_sign_setup */ NULL, /* dsa_do_verify */ ibmca_dsa_mod_exp, /* dsa_mod_exp */ ibmca_mod_exp_dsa, /* bn_mod_exp */ NULL, /* init */ NULL, /* finish */ 0, /* flags */ NULL /* app_data */ }; #else static DSA_METHOD *ibmca_dsa = NULL; #endif #endif #ifndef OPENSSL_NO_DH /* Our internal DH_METHOD that we provide pointers to */ #ifdef OLDER_OPENSSL static DH_METHOD ibmca_dh = { "Ibmca DH method", /* name */ NULL, /* generate_key */ NULL, /* compute_key */ ibmca_mod_exp_dh, /* bn_mod_exp */ NULL, /* init */ NULL, /* finish */ 0, /* flags */ NULL /* app_data */ }; #else static DH_METHOD *ibmca_dh = NULL; #endif #endif static RAND_METHOD ibmca_rand = { /* "IBMCA RAND method", */ NULL, /* seed */ ibmca_rand_bytes, /* bytes */ NULL, /* cleanup */ NULL, /* add */ ibmca_rand_bytes, /* pseudorand */ ibmca_rand_status, /* status */ }; #ifdef OLDER_OPENSSL /* DES ECB EVP */ const EVP_CIPHER ibmca_des_ecb = { NID_des_ecb, /* nid */ sizeof(ica_des_vector_t), /* block_size */ sizeof(ica_des_key_single_t), /* key_len */ sizeof(ica_des_vector_t), /* iv_len */ EVP_CIPH_ECB_MODE, /* flags */ ibmca_init_key, /* init */ ibmca_des_cipher, /* do_cipher */ ibmca_cipher_cleanup, /* cleanup */ sizeof(struct ibmca_des_context), /* ctx_size */ EVP_CIPHER_set_asn1_iv, /* set_asn1_parameters */ EVP_CIPHER_get_asn1_iv, /* get_asn1_parameters */ NULL, /* ctrl */ NULL /* app_data */ }; /* DES CBC EVP */ const EVP_CIPHER ibmca_des_cbc = { NID_des_cbc, sizeof(ica_des_vector_t), sizeof(ica_des_key_single_t), sizeof(ica_des_vector_t), EVP_CIPH_CBC_MODE, ibmca_init_key, ibmca_des_cipher, ibmca_cipher_cleanup, sizeof(struct ibmca_des_context), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL, NULL }; /* DES OFB EVP */ const EVP_CIPHER ibmca_des_ofb = { NID_des_ofb, 1, // stream cipher needs blocksize set to 1 sizeof(ica_des_key_single_t), sizeof(ica_des_vector_t), EVP_CIPH_OFB_MODE, ibmca_init_key, /* XXX check me */ ibmca_des_cipher, ibmca_cipher_cleanup, sizeof(struct ibmca_des_context), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL, NULL }; /* DES CFB EVP */ const EVP_CIPHER ibmca_des_cfb = { NID_des_cfb, 1, // stream cipher needs blocksize set to 1 sizeof(ica_des_key_single_t), sizeof(ica_des_vector_t), EVP_CIPH_CFB_MODE, ibmca_init_key, /* XXX check me */ ibmca_des_cipher, ibmca_cipher_cleanup, sizeof(struct ibmca_des_context), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL, NULL }; #else #define EVP_CIPHER_block_size_ECB sizeof(ica_des_vector_t) #define EVP_CIPHER_block_size_CBC sizeof(ica_des_vector_t) #define EVP_CIPHER_block_size_OFB 1 #define EVP_CIPHER_block_size_CFB 1 #define DECLARE_DES_EVP(lmode,umode) \ static EVP_CIPHER *des_##lmode = NULL; \ static const EVP_CIPHER *ibmca_des_##lmode(void) \ { \ if (des_##lmode == NULL) { \ EVP_CIPHER *cipher; \ if (( cipher = EVP_CIPHER_meth_new(NID_des_##lmode, \ EVP_CIPHER_block_size_##umode, \ sizeof(ica_des_key_single_t))) == NULL \ || !EVP_CIPHER_meth_set_iv_length(cipher, sizeof(ica_des_vector_t)) \ || !EVP_CIPHER_meth_set_flags(cipher,EVP_CIPH_##umode##_MODE) \ || !EVP_CIPHER_meth_set_init(cipher, ibmca_init_key) \ || !EVP_CIPHER_meth_set_do_cipher(cipher, ibmca_des_cipher) \ || !EVP_CIPHER_meth_set_cleanup(cipher, ibmca_cipher_cleanup) \ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, \ sizeof(struct ibmca_des_context)) \ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv) \ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) { \ EVP_CIPHER_meth_free(cipher); \ cipher = NULL; \ } \ des_##lmode = cipher; \ } \ return des_##lmode; \ } \ \ static void ibmca_des_##lmode##_destroy(void) \ { \ EVP_CIPHER_meth_free(des_##lmode); \ des_##lmode = NULL; \ } DECLARE_DES_EVP(ecb, ECB) DECLARE_DES_EVP(cbc, CBC) DECLARE_DES_EVP(ofb, OFB) DECLARE_DES_EVP(cfb, CFB) #endif #ifdef OLDER_OPENSSL /* 3DES ECB EVP */ const EVP_CIPHER ibmca_tdes_ecb = { NID_des_ede3_ecb, sizeof(ica_des_vector_t), sizeof(ica_des_key_triple_t), sizeof(ica_des_vector_t), EVP_CIPH_ECB_MODE, ibmca_init_key, ibmca_tdes_cipher, ibmca_cipher_cleanup, sizeof(struct ibmca_des_context), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL, NULL }; /* 3DES CBC EVP */ const EVP_CIPHER ibmca_tdes_cbc = { NID_des_ede3_cbc, sizeof(ica_des_vector_t), sizeof(ica_des_key_triple_t), sizeof(ica_des_vector_t), EVP_CIPH_CBC_MODE, ibmca_init_key, ibmca_tdes_cipher, ibmca_cipher_cleanup, sizeof(struct ibmca_des_context), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL, NULL }; /* 3DES OFB EVP */ const EVP_CIPHER ibmca_tdes_ofb = { NID_des_ede3_ofb, 1, // stream cipher needs blocksize set to 1 sizeof(ica_des_key_triple_t), sizeof(ica_des_vector_t), EVP_CIPH_OFB_MODE, ibmca_init_key, /* XXX check me */ ibmca_tdes_cipher, ibmca_cipher_cleanup, sizeof(struct ibmca_des_context), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL, NULL }; /* 3DES CFB EVP */ const EVP_CIPHER ibmca_tdes_cfb = { NID_des_ede3_cfb, 1, // stream cipher needs blocksize set to 1 sizeof(ica_des_key_triple_t), sizeof(ica_des_vector_t), EVP_CIPH_CFB_MODE, ibmca_init_key, /* XXX check me */ ibmca_tdes_cipher, ibmca_cipher_cleanup, sizeof(struct ibmca_des_context), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL, NULL }; #else #define DECLARE_TDES_EVP(lmode,umode) \ static EVP_CIPHER *tdes_##lmode = NULL; \ static const EVP_CIPHER *ibmca_tdes_##lmode(void) \ { \ if (tdes_##lmode == NULL) { \ EVP_CIPHER *cipher; \ if (( cipher = EVP_CIPHER_meth_new(NID_des_ede3_##lmode, \ EVP_CIPHER_block_size_##umode, \ sizeof(ica_des_key_triple_t))) == NULL \ || !EVP_CIPHER_meth_set_iv_length(cipher, sizeof(ica_des_vector_t)) \ || !EVP_CIPHER_meth_set_flags(cipher,EVP_CIPH_##umode##_MODE) \ || !EVP_CIPHER_meth_set_init(cipher, ibmca_init_key) \ || !EVP_CIPHER_meth_set_do_cipher(cipher, ibmca_tdes_cipher) \ || !EVP_CIPHER_meth_set_cleanup(cipher, ibmca_cipher_cleanup) \ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, \ sizeof(struct ibmca_des_context)) \ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv) \ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) { \ EVP_CIPHER_meth_free(cipher); \ cipher = NULL; \ } \ tdes_##lmode = cipher; \ } \ return tdes_##lmode; \ } \ \ static void ibmca_tdes_##lmode##_destroy(void) \ { \ EVP_CIPHER_meth_free(tdes_##lmode); \ tdes_##lmode = NULL; \ } DECLARE_TDES_EVP(ecb, ECB) DECLARE_TDES_EVP(cbc, CBC) DECLARE_TDES_EVP(ofb, OFB) DECLARE_TDES_EVP(cfb, CFB) #endif #ifdef OLDER_OPENSSL # define DECLARE_AES_EVP(kbits, mode, block_size, key_len, iv_len, \ flags, ctx_size, init, do_cipher, cleanup, \ set_asn1_parameters, get_asn1_parameters, ctrl) \ const EVP_CIPHER aes_##kbits##_##mode = { \ NID_aes_##kbits##_##mode, \ block_size, \ key_len, \ iv_len, \ flags, \ init, \ do_cipher, \ cleanup, \ ctx_size, \ set_asn1_parameters, \ get_asn1_parameters, \ ctrl, \ NULL \ }; \ static const EVP_CIPHER *ibmca_aes_##kbits##_##mode(void) \ { \ return &aes_##kbits##_##mode; \ } #else # define DECLARE_AES_EVP(kbits, mode, block_size, key_len, iv_len, \ flags, ctx_size, init, do_cipher, cleanup, \ set_asn1_parameters, get_asn1_parameters, ctrl)\ static EVP_CIPHER *aes_##kbits##_##mode = NULL; \ static const EVP_CIPHER *ibmca_aes_##kbits##_##mode(void) \ { \ EVP_CIPHER *cipher; \ \ if (aes_##kbits##_##mode != NULL) \ goto done; \ \ if ((cipher = EVP_CIPHER_meth_new(NID_aes_##kbits##_##mode, \ block_size, key_len)) == NULL \ || !EVP_CIPHER_meth_set_iv_length(cipher, iv_len) \ || !EVP_CIPHER_meth_set_flags(cipher, flags) \ || !EVP_CIPHER_meth_set_init(cipher, init) \ || !EVP_CIPHER_meth_set_do_cipher(cipher, do_cipher) \ || !EVP_CIPHER_meth_set_cleanup(cipher, cleanup) \ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, ctx_size) \ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, \ set_asn1_parameters) \ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, \ get_asn1_parameters) \ || !EVP_CIPHER_meth_set_ctrl(cipher, ctrl)) { \ EVP_CIPHER_meth_free(cipher); \ cipher = NULL; \ } \ aes_##kbits##_##mode = cipher; \ done: \ return aes_##kbits##_##mode; \ } \ \ static void ibmca_aes_##kbits##_##mode##_destroy(void) \ { \ EVP_CIPHER_meth_free(aes_##kbits##_##mode); \ aes_##kbits##_##mode = NULL; \ } #endif DECLARE_AES_EVP(128, ecb, sizeof(ica_aes_vector_t), sizeof(ica_aes_key_len_128_t), sizeof(ica_aes_vector_t), EVP_CIPH_ECB_MODE, sizeof(ICA_AES_128_CTX), ibmca_init_key, ibmca_aes_128_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(128, cbc, sizeof(ica_aes_vector_t), sizeof(ica_aes_key_len_128_t), sizeof(ica_aes_vector_t), EVP_CIPH_CBC_MODE, sizeof(ICA_AES_128_CTX), ibmca_init_key, ibmca_aes_128_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(128, ofb, 1, sizeof(ica_aes_key_len_128_t), sizeof(ica_aes_vector_t), EVP_CIPH_OFB_MODE, sizeof(ICA_AES_128_CTX), ibmca_init_key, ibmca_aes_128_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(128, cfb, 1, sizeof(ica_aes_key_len_128_t), sizeof(ica_aes_vector_t), EVP_CIPH_CFB_MODE, sizeof(ICA_AES_128_CTX), ibmca_init_key, ibmca_aes_128_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) #ifndef OPENSSL_NO_AES_GCM DECLARE_AES_EVP(128, gcm, 1, sizeof(ica_aes_key_len_128_t), sizeof(ica_aes_vector_t) - sizeof(uint32_t), EVP_CIPH_GCM_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_AEAD_CIPHER, sizeof(ICA_AES_GCM_CTX), ibmca_aes_gcm_init_key, ibmca_aes_gcm_cipher, NULL, NULL, NULL, ibmca_aes_gcm_ctrl) #endif DECLARE_AES_EVP(192, ecb, sizeof(ica_aes_vector_t), sizeof(ica_aes_key_len_192_t), sizeof(ica_aes_vector_t), EVP_CIPH_ECB_MODE, sizeof(ICA_AES_192_CTX), ibmca_init_key, ibmca_aes_192_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(192, cbc, sizeof(ica_aes_vector_t), sizeof(ica_aes_key_len_192_t), sizeof(ica_aes_vector_t), EVP_CIPH_CBC_MODE, sizeof(ICA_AES_192_CTX), ibmca_init_key, ibmca_aes_192_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(192, ofb, 1, sizeof(ica_aes_key_len_192_t), sizeof(ica_aes_vector_t), EVP_CIPH_OFB_MODE, sizeof(ICA_AES_192_CTX), ibmca_init_key, ibmca_aes_192_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(192, cfb, 1, sizeof(ica_aes_key_len_192_t), sizeof(ica_aes_vector_t), EVP_CIPH_CFB_MODE, sizeof(ICA_AES_192_CTX), ibmca_init_key, ibmca_aes_192_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) #ifndef OPENSSL_NO_AES_GCM DECLARE_AES_EVP(192, gcm, 1, sizeof(ica_aes_key_len_192_t), sizeof(ica_aes_vector_t) - sizeof(uint32_t), EVP_CIPH_GCM_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_AEAD_CIPHER, sizeof(ICA_AES_GCM_CTX), ibmca_aes_gcm_init_key, ibmca_aes_gcm_cipher, NULL, NULL, NULL, ibmca_aes_gcm_ctrl) #endif DECLARE_AES_EVP(256, ecb, sizeof(ica_aes_vector_t), sizeof(ica_aes_key_len_256_t), sizeof(ica_aes_vector_t), EVP_CIPH_ECB_MODE, sizeof(ICA_AES_256_CTX), ibmca_init_key, ibmca_aes_256_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(256, cbc, sizeof(ica_aes_vector_t), sizeof(ica_aes_key_len_256_t), sizeof(ica_aes_vector_t), EVP_CIPH_CBC_MODE, sizeof(ICA_AES_256_CTX), ibmca_init_key, ibmca_aes_256_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(256, ofb, 1, sizeof(ica_aes_key_len_256_t), sizeof(ica_aes_vector_t), EVP_CIPH_OFB_MODE, sizeof(ICA_AES_256_CTX), ibmca_init_key, ibmca_aes_256_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) DECLARE_AES_EVP(256, cfb, 1, sizeof(ica_aes_key_len_256_t), sizeof(ica_aes_vector_t), EVP_CIPH_CFB_MODE, sizeof(ICA_AES_256_CTX), ibmca_init_key, ibmca_aes_256_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) #ifndef OPENSSL_NO_AES_GCM DECLARE_AES_EVP(256, gcm, 1, sizeof(ica_aes_key_len_256_t), sizeof(ica_aes_vector_t) - sizeof(uint32_t), EVP_CIPH_GCM_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_AEAD_CIPHER, sizeof(ICA_AES_GCM_CTX), ibmca_aes_gcm_init_key, ibmca_aes_gcm_cipher, NULL, NULL, NULL, ibmca_aes_gcm_ctrl) #endif #ifdef OLDER_OPENSSL #ifndef OPENSSL_NO_SHA1 static const EVP_MD ibmca_sha1 = { NID_sha1, NID_sha1WithRSAEncryption, SHA_HASH_LENGTH, EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_FIPS, ibmca_sha1_init, ibmca_sha1_update, ibmca_sha1_final, NULL, ibmca_sha1_cleanup, EVP_PKEY_RSA_method, SHA_BLOCK_SIZE, sizeof(EVP_MD *) + sizeof(struct ibmca_sha1_ctx) }; #endif #ifndef OPENSSL_NO_SHA256 static const EVP_MD ibmca_sha256 = { NID_sha256, NID_sha256WithRSAEncryption, SHA256_HASH_LENGTH, EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_FIPS, ibmca_sha256_init, ibmca_sha256_update, ibmca_sha256_final, NULL, ibmca_sha256_cleanup, EVP_PKEY_RSA_method, SHA256_BLOCK_SIZE, sizeof(EVP_MD *) + sizeof(struct ibmca_sha256_ctx) }; #endif #ifndef OPENSSL_NO_SHA512 static const EVP_MD ibmca_sha512 = { NID_sha512, NID_sha512WithRSAEncryption, SHA512_HASH_LENGTH, EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_FIPS, ibmca_sha512_init, ibmca_sha512_update, ibmca_sha512_final, NULL, ibmca_sha512_cleanup, EVP_PKEY_RSA_method, SHA512_BLOCK_SIZE, sizeof(EVP_MD *) + sizeof(struct ibmca_sha512_ctx) }; #endif #else #define DECLARE_SHA_EVP(sha,len) \ static EVP_MD *sha##_md = NULL; \ static const EVP_MD *ibmca_##sha(void) \ { \ if (sha##_md == NULL) { \ EVP_MD *md; \ if (( md = EVP_MD_meth_new(NID_##sha, \ NID_##sha##WithRSAEncryption)) == NULL \ || !EVP_MD_meth_set_result_size(md, len##_HASH_LENGTH) \ || !EVP_MD_meth_set_input_blocksize(md, len##_BLOCK_SIZE) \ || !EVP_MD_meth_set_app_datasize(md, sizeof(EVP_MD *) + \ sizeof(struct ibmca_##sha##_ctx)) \ || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_FIPS) \ || !EVP_MD_meth_set_init(md, ibmca_##sha##_init) \ || !EVP_MD_meth_set_update(md, ibmca_##sha##_update) \ || !EVP_MD_meth_set_final(md, ibmca_##sha##_final) \ || !EVP_MD_meth_set_cleanup(md, ibmca_##sha##_cleanup)) { \ EVP_MD_meth_free(md); \ md = NULL; \ } \ sha##_md = md; \ } \ return sha##_md; \ } \ \ static void ibmca_##sha##_destroy(void) \ { \ EVP_MD_meth_free(sha##_md); \ sha##_md = NULL; \ } DECLARE_SHA_EVP(sha1, SHA) DECLARE_SHA_EVP(sha256, SHA256) DECLARE_SHA_EVP(sha512, SHA512) #endif /* Constants used when creating the ENGINE */ static const char *engine_ibmca_id = "ibmca"; static const char *engine_ibmca_name = "Ibmca hardware engine support"; inline static int set_RSA_prop(ENGINE *e) { static int rsa_enabled = 0; #ifndef OPENSSL_NO_RSA const RSA_METHOD *meth1; #ifndef OLDER_OPENSSL ibmca_rsa = RSA_meth_new("Ibmca RSA method", 0); #endif #endif #ifndef OPENSSL_NO_DSA const DSA_METHOD *meth2; #ifndef OLDER_OPENSSL ibmca_dsa = DSA_meth_new("Ibmca DSA method", 0); #endif #endif #ifndef OPENSSL_NO_DH const DH_METHOD *meth3; #ifndef OLDER_OPENSSL ibmca_dh = DH_meth_new("Ibmca DH method", 0); #endif #endif if(rsa_enabled){ return 1; } if( #ifndef OPENSSL_NO_RSA #ifdef OLDER_OPENSSL !ENGINE_set_RSA(e, &ibmca_rsa) || #else !ENGINE_set_RSA(e, ibmca_rsa) || #endif #endif #ifndef OPENSSL_NO_DSA #ifdef OLDER_OPENSSL !ENGINE_set_DSA(e, &ibmca_dsa) || #else !ENGINE_set_DSA(e, ibmca_dsa) || #endif #endif #ifndef OPENSSL_NO_DH #ifdef OLDER_OPENSSL !ENGINE_set_DH(e, &ibmca_dh) #else !ENGINE_set_DH(e, ibmca_dh) #endif ) #endif return 0; #ifndef OPENSSL_NO_RSA /* We know that the "PKCS1_SSLeay()" functions hook properly * to the ibmca-specific mod_exp and mod_exp_crt so we use * those functions. NB: We don't use ENGINE_openssl() or * anything "more generic" because something like the RSAref * code may not hook properly, and if you own one of these here * cards then you have the right to do RSA operations on it * anyway! */ #ifdef OLDER_OPENSSL meth1 = RSA_PKCS1_SSLeay(); ibmca_rsa.rsa_pub_enc = meth1->rsa_pub_enc; ibmca_rsa.rsa_pub_dec = meth1->rsa_pub_dec; ibmca_rsa.rsa_priv_enc = meth1->rsa_priv_enc; ibmca_rsa.rsa_priv_dec = meth1->rsa_priv_dec; #else meth1 = RSA_PKCS1_OpenSSL(); if ( !RSA_meth_set_pub_enc(ibmca_rsa, RSA_meth_get_pub_enc(meth1)) || !RSA_meth_set_pub_dec(ibmca_rsa, RSA_meth_get_pub_dec(meth1)) || !RSA_meth_set_priv_enc(ibmca_rsa, RSA_meth_get_priv_enc(meth1)) || !RSA_meth_set_priv_dec(ibmca_rsa, RSA_meth_get_priv_dec(meth1)) || !RSA_meth_set_mod_exp(ibmca_rsa, ibmca_rsa_mod_exp) || !RSA_meth_set_bn_mod_exp(ibmca_rsa, ibmca_mod_exp_mont) || !RSA_meth_set_init(ibmca_rsa, ibmca_rsa_init) ) return 0; #endif #endif #ifndef OPENSSL_NO_DSA meth2 = DSA_OpenSSL(); #ifdef OLDER_OPENSSL ibmca_dsa.dsa_do_sign = meth2->dsa_do_sign; ibmca_dsa.dsa_sign_setup = meth2->dsa_sign_setup; ibmca_dsa.dsa_do_verify = meth2->dsa_do_verify; #else if ( !DSA_meth_set_sign(ibmca_dsa, DSA_meth_get_sign(meth2)) || !DSA_meth_set_verify(ibmca_dsa, DSA_meth_get_verify(meth2)) || !DSA_meth_set_mod_exp(ibmca_dsa, ibmca_dsa_mod_exp) || !DSA_meth_set_bn_mod_exp(ibmca_dsa, ibmca_mod_exp_dsa) ) return 0; #endif #endif #ifndef OPENSSL_NO_DH /* Much the same for Diffie-Hellman */ meth3 = DH_OpenSSL(); #ifdef OLDER_OPENSSL ibmca_dh.generate_key = meth3->generate_key; ibmca_dh.compute_key = meth3->compute_key; #else if ( !DH_meth_set_generate_key(ibmca_dh, DH_meth_get_generate_key(meth3)) || !DH_meth_set_compute_key(ibmca_dh, DH_meth_get_compute_key(meth3)) || !DH_meth_set_bn_mod_exp(ibmca_dh, ibmca_mod_exp_dh) ) return 0; #endif #endif rsa_enabled = 1; return 1; } /* * dig_nid_cnt and ciph_nid_cnt count the number of enabled crypt mechanims. * dig_nid_cnt and ciph_nid_cnt needs to be pointer, because only set_engine_prop * knows about how much digest or cipher will be set per call. To count the number of * cipher and digest outside of the function is not feasible */ inline static int set_engine_prop(ENGINE *e, int algo_id, int *dig_nid_cnt, int *ciph_nid_cnt) { switch(algo_id) { case P_RNG: if(!ENGINE_set_RAND(e, &ibmca_rand)) return 0; break; /* * RSA will be enabled if one of this is set. OpenSSL does not distinguish * between RSA_ME and RSA_CRT. It is not the task of ibmca to route one ME * call to CRT or vice versa. */ case RSA_ME: case RSA_CRT: if(!set_RSA_prop(e)) return 0; break; #ifndef OPENSSL_NO_SHA1 case SHA1: ibmca_digest_lists.nids[*dig_nid_cnt] = NID_sha1; #ifdef OLDER_OPENSSL ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++]= &ibmca_sha1; #else ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++]= ibmca_sha1(); #endif break; #endif #ifndef OPENSSL_NO_SHA256 case SHA256: ibmca_digest_lists.nids[*dig_nid_cnt] = NID_sha256; #ifdef OLDER_OPENSSL ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++] = &ibmca_sha256; #else ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++] = ibmca_sha256(); #endif break; #endif #ifndef OPENSSL_NO_SHA512 case SHA512: ibmca_digest_lists.nids[*dig_nid_cnt] = NID_sha512; #ifdef OLDER_OPENSSL ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++] = &ibmca_sha512; #else ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++] = ibmca_sha512(); #endif break; #endif case DES_ECB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ecb; #ifdef OLDER_OPENSSL ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = &ibmca_des_ecb; #else ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_des_ecb(); #endif break; case DES_CBC: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_cbc; #ifdef OLDER_OPENSSL ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = &ibmca_des_cbc; #else ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_des_cbc(); #endif break; case DES_OFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ofb; #ifdef OLDER_OPENSSL ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = &ibmca_des_ofb; #else ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_des_ofb(); #endif break; case DES_CFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_cfb; #ifdef OLDER_OPENSSL ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = &ibmca_des_cfb; #else ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_des_cfb(); #endif break; case DES3_ECB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ede3_ecb; #ifdef OLDER_OPENSSL ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = &ibmca_tdes_ecb; #else ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_tdes_ecb(); #endif break; case DES3_CBC: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ede3_cbc; #ifdef OLDER_OPENSSL ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = &ibmca_tdes_cbc; #else ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_tdes_cbc(); #endif break; case DES3_OFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ede3_ofb; #ifdef OLDER_OPENSSL ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = &ibmca_tdes_ofb; #else ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_tdes_ofb(); #endif break; case DES3_CFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ede3_cfb; #ifdef OLDER_OPENSSL ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = &ibmca_tdes_cfb; #else ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_tdes_cfb(); #endif break; case AES_ECB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_128_ecb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_128_ecb(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_192_ecb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_192_ecb(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_256_ecb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_256_ecb(); break; case AES_CBC: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_128_cbc; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_128_cbc(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_192_cbc; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_192_cbc(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_256_cbc; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_256_cbc(); break; case AES_OFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_128_ofb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_128_ofb(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_192_ofb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_192_ofb(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_256_ofb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_256_ofb(); break; case AES_CFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_128_cfb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_128_cfb(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_192_cfb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_192_cfb(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_256_cfb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_256_cfb(); break; #ifndef OPENSSL_NO_AES_GCM case AES_GCM_KMA: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_128_gcm; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_128_gcm(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_192_gcm; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_192_gcm(); ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_aes_256_gcm; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_aes_256_gcm(); break; #endif default: break; /* do nothing */ } size_cipher_list = *ciph_nid_cnt; size_digest_list = *dig_nid_cnt; return 1; } int is_crypto_card_loaded() { DIR* sysDir; FILE *file; char dev[PATH_MAX] = AP_PATH; struct dirent *direntp; char *type = NULL; size_t size; char c; if ((sysDir = opendir(dev)) == NULL ) return 0; while((direntp = readdir(sysDir)) != NULL){ if(strstr(direntp->d_name, "card") != 0){ snprintf(dev, PATH_MAX, "%s/%s/type", AP_PATH, direntp->d_name); if ((file = fopen(dev, "r")) == NULL){ closedir(sysDir); return 0; } if (getline(&type, &size, file) == -1){ fclose(file); closedir(sysDir); return 0; } /* ignore \n * looking for CEX??A and CEX??C * Skip type CEX??P cards */ if (type[strlen(type)-2] == 'P'){ free(type); type = NULL; fclose(file); continue; } free(type); type = NULL; fclose(file); snprintf(dev, PATH_MAX, "%s/%s/online", AP_PATH, direntp->d_name); if ((file = fopen(dev, "r")) == NULL){ closedir(sysDir); return 0; } if((c = fgetc(file)) == '1'){ fclose(file); return 1; } fclose(file); } } closedir(sysDir); return 0; } typedef unsigned int (*ica_get_functionlist_t)(libica_func_list_element *, unsigned int *); ica_get_functionlist_t p_ica_get_functionlist; static int set_supported_meths(ENGINE *e) { int i, j; unsigned int mech_len; libica_func_list_element *pmech_list; int rc = 0; int dig_nid_cnt = 0; int ciph_nid_cnt = 0; int card_loaded; if (p_ica_get_functionlist(NULL, &mech_len)) return 0; pmech_list = malloc(sizeof(libica_func_list_element)*mech_len); if (!pmech_list) return 0; if (p_ica_get_functionlist(pmech_list, &mech_len)) goto out; card_loaded = is_crypto_card_loaded(); for (i = 0; i < mech_len; i++) { libica_func_list_element *f = &pmech_list[i]; /* Disable crypto algorithm if not supported in hardware */ if (!(f->flags & (ICA_FLAG_SHW | ICA_FLAG_DHW))) continue; /* * If no crypto card is available, disable crypto algos that can * only operate on HW on card */ if ((f->flags & ICA_FLAG_DHW) && !card_loaded) continue; /* Check if this crypto algorithm is supported by ibmca */ for (j = 0; ibmca_crypto_algos[j]; j++) if (ibmca_crypto_algos[j] == f->mech_mode_id) break; if (!ibmca_crypto_algos[j]) continue; /* * This algorith is supported by ibmca and libica * Set NID, ibmca struct and the info for the ENGINE struct */ if (!set_engine_prop(e, ibmca_crypto_algos[j], &dig_nid_cnt, &ciph_nid_cnt)) goto out; } if(dig_nid_cnt > 0) if(!ENGINE_set_digests(e, ibmca_engine_digests)) goto out; if(ciph_nid_cnt > 0) if(!ENGINE_set_ciphers(e, ibmca_engine_ciphers)) goto out; rc = 1; out: free(pmech_list); return rc; } /* This internal function is used by ENGINE_ibmca() and possibly by the * "dynamic" ENGINE support too */ static int bind_helper(ENGINE * e) { if (!ENGINE_set_id(e, engine_ibmca_id) || !ENGINE_set_name(e, engine_ibmca_name) || !ENGINE_set_destroy_function(e, ibmca_destroy) || !ENGINE_set_init_function(e, ibmca_init) || !ENGINE_set_finish_function(e, ibmca_finish) || !ENGINE_set_ctrl_function(e, ibmca_ctrl) || !ENGINE_set_cmd_defns(e, ibmca_cmd_defns)) return 0; /* Ensure the ibmca error handling is set up */ ERR_load_IBMCA_strings(); /* initialize the engine implizit */ ibmca_init(e); return 1; } static ENGINE *engine_ibmca(void) { ENGINE *ret = ENGINE_new(); if (!ret) return NULL; if (!bind_helper(ret)) { ENGINE_free(ret); return NULL; } return ret; } void ENGINE_load_ibmca(void) { /* Copied from eng_[openssl|dyn].c */ ENGINE *toadd = engine_ibmca(); if (!toadd) return; ENGINE_add(toadd); ENGINE_free(toadd); ERR_clear_error(); } /* Destructor (complements the "ENGINE_ibmca()" constructor) */ static int ibmca_destroy(ENGINE * e) { /* Unload the ibmca error strings so any error state including our * functs or reasons won't lead to a segfault (they simply get displayed * without corresponding string data because none will be found). */ #ifndef OLDER_OPENSSL ibmca_des_ecb_destroy(); ibmca_des_cbc_destroy(); ibmca_des_ofb_destroy(); ibmca_des_cfb_destroy(); ibmca_tdes_ecb_destroy(); ibmca_tdes_cbc_destroy(); ibmca_tdes_ofb_destroy(); ibmca_tdes_cfb_destroy(); ibmca_aes_128_ecb_destroy(); ibmca_aes_128_cbc_destroy(); ibmca_aes_128_ofb_destroy(); ibmca_aes_128_cfb_destroy(); ibmca_aes_192_ecb_destroy(); ibmca_aes_192_cbc_destroy(); ibmca_aes_192_ofb_destroy(); ibmca_aes_192_cfb_destroy(); ibmca_aes_256_ecb_destroy(); ibmca_aes_256_cbc_destroy(); ibmca_aes_256_ofb_destroy(); ibmca_aes_256_cfb_destroy(); # ifndef OPENSSL_NO_AES_GCM ibmca_aes_128_gcm_destroy(); ibmca_aes_192_gcm_destroy(); ibmca_aes_256_gcm_destroy(); # endif ibmca_sha1_destroy(); ibmca_sha256_destroy(); ibmca_sha512_destroy(); #endif ERR_unload_IBMCA_strings(); return 1; } /* This is a process-global DSO handle used for loading and unloading * the Ibmca library. NB: This is only set (or unset) during an * init() or finish() call (reference counts permitting) and they're * operating with global locks, so this should be thread-safe * implicitly. */ void *ibmca_dso = NULL; /* These are the function pointers that are (un)set when the library has * successfully (un)loaded. */ typedef void (*ica_set_fallback_mode_t)(int); typedef unsigned int (*ica_open_adapter_t)(ica_adapter_handle_t *); typedef unsigned int (*ica_close_adapter_t)(ica_adapter_handle_t); typedef unsigned int (*ica_rsa_mod_expo_t)(ica_adapter_handle_t, unsigned char *, ica_rsa_key_mod_expo_t *, unsigned char *); typedef unsigned int (*ica_random_number_generate_t)(unsigned int, unsigned char *); typedef unsigned int (*ica_rsa_crt_t)(ica_adapter_handle_t, unsigned char *, ica_rsa_key_crt_t *, unsigned char *); typedef unsigned int (*ica_sha1_t)(unsigned int, unsigned int, unsigned char *, sha_context_t *, unsigned char *); typedef unsigned int (*ica_des_encrypt_t)(unsigned int, unsigned int, unsigned char *, ica_des_vector_t *, ica_des_key_single_t *, unsigned char *); typedef unsigned int (*ica_des_decrypt_t)(unsigned int, unsigned int, unsigned char *, ica_des_vector_t *, ica_des_key_single_t *, unsigned char *); typedef unsigned int (*ica_3des_encrypt_t)(unsigned int, unsigned int, unsigned char *, ica_des_vector_t *, ica_des_key_triple_t *, unsigned char *); typedef unsigned int (*ica_3des_decrypt_t)(unsigned int, unsigned int, unsigned char *, ica_des_vector_t *, ica_des_key_triple_t *, unsigned char *); typedef unsigned int (*ica_aes_encrypt_t)(unsigned int, unsigned int, unsigned char *, ica_aes_vector_t *, unsigned int, unsigned char *, unsigned char *); typedef unsigned int (*ica_aes_decrypt_t)(unsigned int, unsigned int, unsigned char *, ica_aes_vector_t *, unsigned int, unsigned char *, unsigned char *); typedef unsigned int (*ica_sha256_t)(unsigned int, unsigned int, unsigned char *, sha256_context_t *, unsigned char *); typedef unsigned int (*ica_des_ofb_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, const unsigned char *key, unsigned char *iv, unsigned int direction); typedef unsigned int (*ica_sha512_t)(unsigned int, unsigned int, unsigned char *, sha512_context_t *, unsigned char *); typedef unsigned int (*ica_des_cfb_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, const unsigned char *key, unsigned char *iv, unsigned int lcfb, unsigned int direction); typedef unsigned int (*ica_3des_cfb_t)(const unsigned char *, unsigned char *, unsigned long, const unsigned char *, unsigned char *, unsigned int, unsigned int); typedef unsigned int (*ica_3des_ofb_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, const unsigned char *key, unsigned char *iv, unsigned int direction); typedef unsigned int (*ica_aes_ofb_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, const unsigned char *key, unsigned int key_length, unsigned char *iv, unsigned int direction); typedef unsigned int (*ica_aes_cfb_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, const unsigned char *key, unsigned int key_length, unsigned char *iv, unsigned int lcfb, unsigned int direction); typedef unsigned int (*ica_aes_gcm_initialize_t)(const unsigned char *iv, unsigned int iv_length, unsigned char *key, unsigned int key_length, unsigned char *icb, unsigned char *ucb, unsigned char *subkey, unsigned int direction); typedef unsigned int (*ica_aes_gcm_intermediate_t)(unsigned char *plaintext, unsigned long plaintext_length, unsigned char *ciphertext, unsigned char *ucb, unsigned char *aad, unsigned long aad_length, unsigned char *tag, unsigned int tag_length, unsigned char *key, unsigned int key_length, unsigned char *subkey, unsigned int direction); typedef unsigned int (*ica_aes_gcm_last_t)(unsigned char *icb, unsigned long aad_length, unsigned long ciph_length, unsigned char *tag, unsigned char *final_tag, unsigned int final_tag_length, unsigned char *key, unsigned int key_length, unsigned char *subkey, unsigned int direction); /* entry points into libica, filled out at DSO load time */ ica_set_fallback_mode_t p_ica_set_fallback_mode; ica_open_adapter_t p_ica_open_adapter; ica_close_adapter_t p_ica_close_adapter; ica_rsa_mod_expo_t p_ica_rsa_mod_expo; ica_random_number_generate_t p_ica_random_number_generate; ica_rsa_crt_t p_ica_rsa_crt; ica_sha1_t p_ica_sha1; ica_des_encrypt_t p_ica_des_encrypt; ica_des_decrypt_t p_ica_des_decrypt; ica_3des_encrypt_t p_ica_3des_encrypt; ica_3des_decrypt_t p_ica_3des_decrypt; ica_aes_encrypt_t p_ica_aes_encrypt; ica_aes_decrypt_t p_ica_aes_decrypt; ica_sha256_t p_ica_sha256; ica_sha512_t p_ica_sha512; ica_des_ofb_t p_ica_des_ofb; ica_des_cfb_t p_ica_des_cfb; ica_3des_cfb_t p_ica_3des_cfb; ica_3des_ofb_t p_ica_3des_ofb; ica_aes_ofb_t p_ica_aes_ofb; ica_aes_cfb_t p_ica_aes_cfb; #ifndef OPENSSL_NO_AES_GCM ica_aes_gcm_initialize_t p_ica_aes_gcm_initialize; ica_aes_gcm_intermediate_t p_ica_aes_gcm_intermediate; ica_aes_gcm_last_t p_ica_aes_gcm_last; #endif /* utility function to obtain a context */ static int get_context(ica_adapter_handle_t * p_handle) { unsigned int status = 0; status = p_ica_open_adapter(p_handle); if (status != 0) return 0; return 1; } /* similarly to release one. */ static void release_context(ica_adapter_handle_t i_handle) { p_ica_close_adapter(i_handle); } /* initialisation functions. */ #define BIND(dso, sym) (p_##sym = (sym##_t)dlsym(dso, #sym)) static int ibmca_init(ENGINE * e) { static int init = 0; if (init) /* Engine already loaded. */ return 1; init++; DEBUG_PRINTF(">%s\n", __func__); /* Attempt to load libica.so. Needs to be * changed unfortunately because the Ibmca drivers don't have * standard library names that can be platform-translated well. */ /* TODO: Work out how to actually map to the names the Ibmca * drivers really use - for now a symbollic link needs to be * created on the host system from libica.so to ica.so on * unix variants. */ /* WJH XXX check name translation */ ibmca_dso = dlopen(LIBICA_SHARED_LIB, RTLD_NOW); if (ibmca_dso == NULL) { DEBUG_PRINTF("%s: dlopen(%s) failed\n", __func__, LIBICA_SHARED_LIB); IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_DSO_FAILURE); goto err; } if (!BIND(ibmca_dso, ica_open_adapter) || !BIND(ibmca_dso, ica_close_adapter) || !BIND(ibmca_dso, ica_rsa_mod_expo) || !BIND(ibmca_dso, ica_random_number_generate) || !BIND(ibmca_dso, ica_rsa_crt) || !BIND(ibmca_dso, ica_sha1) || !BIND(ibmca_dso, ica_des_encrypt) || !BIND(ibmca_dso, ica_des_decrypt) || !BIND(ibmca_dso, ica_3des_encrypt) || !BIND(ibmca_dso, ica_3des_decrypt) || !BIND(ibmca_dso, ica_aes_encrypt) || !BIND(ibmca_dso, ica_aes_decrypt) || !BIND(ibmca_dso, ica_sha256) || !BIND(ibmca_dso, ica_sha512) || !BIND(ibmca_dso, ica_aes_ofb) || !BIND(ibmca_dso, ica_des_ofb) || !BIND(ibmca_dso, ica_3des_ofb) || !BIND(ibmca_dso, ica_aes_cfb) || !BIND(ibmca_dso, ica_des_cfb) || !BIND(ibmca_dso, ica_get_functionlist) || !BIND(ibmca_dso, ica_3des_cfb) #ifndef OPENSSL_NO_AES_GCM || !BIND(ibmca_dso, ica_aes_gcm_initialize) || !BIND(ibmca_dso, ica_aes_gcm_intermediate) || !BIND(ibmca_dso, ica_aes_gcm_last) #endif ) { IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_DSO_FAILURE); DEBUG_PRINTF("%s: function bind failed\n", __func__); goto err; } // disable fallbacks on Libica if (BIND(ibmca_dso, ica_set_fallback_mode)) p_ica_set_fallback_mode(0); if(!set_supported_meths(e)) goto err; if (!get_context(&ibmca_handle)) { IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_UNIT_FAILURE); goto err; } DEBUG_PRINTF("<%s success\n", __func__); return 1; err: if (ibmca_dso) { dlclose(ibmca_dso); ibmca_dso = NULL; } p_ica_open_adapter = NULL; p_ica_close_adapter = NULL; p_ica_rsa_mod_expo = NULL; p_ica_random_number_generate = NULL; p_ica_rsa_crt = NULL; p_ica_sha1 = NULL; p_ica_des_encrypt = NULL; p_ica_des_decrypt = NULL; p_ica_3des_encrypt = NULL; p_ica_3des_decrypt = NULL; p_ica_aes_encrypt = NULL; p_ica_aes_decrypt = NULL; p_ica_sha256 = NULL; p_ica_sha512 = NULL; p_ica_aes_ofb = NULL; p_ica_des_ofb = NULL; p_ica_3des_ofb = NULL; p_ica_aes_cfb = NULL; p_ica_des_cfb = NULL; p_ica_3des_cfb = NULL; #ifndef OPENSSL_NO_AES_GCM p_ica_aes_gcm_initialize = NULL; p_ica_aes_gcm_intermediate = NULL; p_ica_aes_gcm_last = NULL; #endif return 0; } static int ibmca_finish(ENGINE * e) { if (ibmca_dso == NULL) { IBMCAerr(IBMCA_F_IBMCA_FINISH, IBMCA_R_NOT_LOADED); return 0; } release_context(ibmca_handle); if (!dlclose(ibmca_dso)) { IBMCAerr(IBMCA_F_IBMCA_FINISH, IBMCA_R_DSO_FAILURE); return 0; } ibmca_dso = NULL; return 1; } static int ibmca_ctrl(ENGINE * e, int cmd, long i, void *p, void (*f) ()) { int initialised = ((ibmca_dso == NULL) ? 0 : 1); switch (cmd) { case IBMCA_CMD_SO_PATH: if (p == NULL) { IBMCAerr(IBMCA_F_IBMCA_CTRL, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (initialised) { IBMCAerr(IBMCA_F_IBMCA_CTRL, IBMCA_R_ALREADY_LOADED); return 0; } LIBICA_NAME = (const char *) p; return 1; default: break; } IBMCAerr(IBMCA_F_IBMCA_CTRL, IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED); return 0; } /* * ENGINE calls this to find out how to deal with * a particular NID in the ENGINE. */ static int ibmca_engine_ciphers(ENGINE * e, const EVP_CIPHER ** cipher, const int **nids, int nid) { int i; if (!cipher) return (ibmca_usable_ciphers(nids)); *cipher = NULL; for(i = 0; i < size_cipher_list;i++) if(nid == ibmca_cipher_lists.nids[i]){ *cipher = (EVP_CIPHER*) ibmca_cipher_lists.crypto_meths [i]; break; } /* Check: how can *cipher be NULL? */ return (*cipher != NULL); } static int ibmca_usable_ciphers(const int **nids) { if(nids) *nids = ibmca_cipher_lists.nids; return size_cipher_list; } static int ibmca_init_key(EVP_CIPHER_CTX * ctx, const unsigned char *key, const unsigned char *iv, int enc) { #ifdef OLDER_OPENSSL ICA_DES_CTX *pCtx = ctx->cipher_data; memcpy(pCtx->key, key, ctx->cipher->key_len); #else ICA_DES_CTX *pCtx = (ICA_DES_CTX *) EVP_CIPHER_CTX_get_cipher_data(ctx); memcpy(pCtx->key, key, EVP_CIPHER_CTX_key_length(ctx)); #endif return 1; } // end ibmca_init_key static int ibmca_des_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, const unsigned char *in, size_t inlen) { int mode = 0; int rv; unsigned int len; #ifdef OLDER_OPENSSL ICA_DES_CTX *pCtx = ctx->cipher_data; #else ICA_DES_CTX *pCtx = (ICA_DES_CTX *) EVP_CIPHER_CTX_get_cipher_data(ctx); #endif ica_des_vector_t pre_iv; if (inlen > UINT32_MAX) { IBMCAerr(IBMCA_F_IBMCA_DES_CIPHER, IBMCA_R_OUTLEN_TO_LARGE); return 0; } len = inlen; if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_ECB_MODE) { mode = MODE_ECB; } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CBC_MODE) { mode = MODE_CBC; } else if ((EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_CFB_MODE) && (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE)) { IBMCAerr(IBMCA_F_IBMCA_DES_CIPHER, IBMCA_R_CIPHER_MODE_NOT_SUPPORTED); return 0; } #ifdef OLDER_OPENSSL if (ctx->encrypt) { #else if (EVP_CIPHER_CTX_encrypting(ctx)) { #endif if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { rv = p_ica_des_cfb(in, out, len, pCtx->key, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif 8, ICA_ENCRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_des_ofb(in, out, len, pCtx->key, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_ENCRYPT); } else { rv = p_ica_des_encrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_des_vector_t *) ctx->iv, #else (ica_des_vector_t *) EVP_CIPHER_CTX_iv_noconst(ctx), #endif (ica_des_key_single_t *) pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_DES_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif out + len - EVP_CIPHER_CTX_iv_length(ctx), EVP_CIPHER_CTX_iv_length(ctx)); } } else { if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { /* Protect against decrypt in place */ /* FIXME: Shouldn't we use EVP_CIPHER_CTX_iv_length() instead? */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_des_cfb(in, out, len, pCtx->key, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif 8, ICA_DECRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_des_ofb(in, out, len, pCtx->key, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_DECRYPT); } else { /* Protect against decrypt in place */ /* FIXME: Shouldn't we use EVP_CIPHER_CTX_iv_length() instead? */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_des_decrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_des_vector_t *) ctx->iv, #else (ica_des_vector_t *) EVP_CIPHER_CTX_iv_noconst(ctx), #endif (ica_des_key_single_t *) pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_DES_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif pre_iv, EVP_CIPHER_CTX_iv_length(ctx)); } } return 1; } // end ibmca_des_cipher static int ibmca_tdes_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, const unsigned char *in, size_t inlen) { int mode = 0; int rv; unsigned int len; #ifdef OLDER_OPENSSL ICA_DES_CTX *pCtx = ctx->cipher_data; #else ICA_DES_CTX *pCtx = (ICA_DES_CTX *) EVP_CIPHER_CTX_get_cipher_data(ctx); #endif ica_des_vector_t pre_iv; if (inlen > UINT32_MAX) { IBMCAerr(IBMCA_F_IBMCA_TDES_CIPHER, IBMCA_R_OUTLEN_TO_LARGE); return 0; } len = inlen; if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_ECB_MODE) { mode = MODE_ECB; } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CBC_MODE) { mode = MODE_CBC; } else if ((EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_CFB_MODE) && (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE)) { IBMCAerr(IBMCA_F_IBMCA_TDES_CIPHER, IBMCA_R_CIPHER_MODE_NOT_SUPPORTED); return 0; } #ifdef OLDER_OPENSSL if (ctx->encrypt) { #else if (EVP_CIPHER_CTX_encrypting(ctx)) { #endif if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { rv = p_ica_3des_cfb(in, out, len, pCtx->key, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif 8, ICA_ENCRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_3des_ofb(in, out, len, pCtx->key, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_ENCRYPT); } else { rv = p_ica_3des_encrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_des_vector_t *) ctx->iv, #else (ica_des_vector_t *) EVP_CIPHER_CTX_iv_noconst(ctx), #endif (ica_des_key_triple_t *) pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_TDES_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif out + len - EVP_CIPHER_CTX_iv_length(ctx), EVP_CIPHER_CTX_iv_length(ctx)); } } else { if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { /* Protect against decrypt in place */ /* FIXME: Again, check if EVP_CIPHER_CTX_iv_length() should be used */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_3des_cfb(in, out, len, pCtx->key, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif 8, ICA_DECRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_3des_ofb(in, out, len, pCtx->key, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_DECRYPT); } else { /* Protect against decrypt in place */ /* FIXME: Again, check if EVP_CIPHER_CTX_iv_length() should be used */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_3des_decrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_des_vector_t *) ctx->iv, #else (ica_des_vector_t *) EVP_CIPHER_CTX_iv_noconst(ctx), #endif (ica_des_key_triple_t *) pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_TDES_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif pre_iv, EVP_CIPHER_CTX_iv_length(ctx)); } } return 1; } // end ibmca_tdes_cipher /* FIXME: a lot of common code between ica_aes_[128|192|256]_cipher() fncs */ static int ibmca_aes_128_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, const unsigned char *in, size_t inlen) { int mode = 0; int rv; unsigned int len; #ifdef OLDER_OPENSSL ICA_AES_128_CTX *pCtx = ctx->cipher_data; #else ICA_AES_128_CTX *pCtx = (ICA_AES_128_CTX *) EVP_CIPHER_CTX_get_cipher_data(ctx); #endif ica_aes_vector_t pre_iv; if (inlen > UINT32_MAX) { IBMCAerr(IBMCA_F_IBMCA_AES_128_CIPHER, IBMCA_R_OUTLEN_TO_LARGE); return 0; } len = inlen; if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_ECB_MODE) { mode = MODE_ECB; } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CBC_MODE) { mode = MODE_CBC; } else if ((EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_CFB_MODE) && (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE)) { IBMCAerr(IBMCA_F_IBMCA_AES_128_CIPHER, IBMCA_R_CIPHER_MODE_NOT_SUPPORTED); return 0; } #ifdef OLDER_OPENSSL if (ctx->encrypt) { #else if (EVP_CIPHER_CTX_encrypting(ctx)) { #endif if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { rv = p_ica_aes_cfb(in, out, len, pCtx->key, AES_KEY_LEN128, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_BLOCK_SIZE, ICA_ENCRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_aes_ofb(in, out, len, pCtx->key, AES_KEY_LEN128, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_ENCRYPT); } else { rv = p_ica_aes_encrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_aes_vector_t *)ctx->iv, #else (ica_aes_vector_t *)EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_KEY_LEN128, (unsigned char *)pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_AES_128_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif out + len - EVP_CIPHER_CTX_iv_length(ctx), EVP_CIPHER_CTX_iv_length(ctx)); } } else { if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { /* Protect against decrypt in place */ /* FIXME: Again, check if EVP_CIPHER_CTX_iv_length() should be used */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_aes_cfb(in, out, len, pCtx->key, AES_KEY_LEN128, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_BLOCK_SIZE, ICA_DECRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_aes_ofb(in, out, len, pCtx->key, AES_KEY_LEN128, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_DECRYPT); } else { /* Protect against decrypt in place */ /* FIXME: Again, check if EVP_CIPHER_CTX_iv_length() should be used */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_aes_decrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_aes_vector_t *)ctx->iv, #else (ica_aes_vector_t *)EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_KEY_LEN128, (unsigned char *)pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_AES_128_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif pre_iv, EVP_CIPHER_CTX_iv_length(ctx)); } } return 1; } static int ibmca_aes_192_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, const unsigned char *in, size_t inlen) { int mode = 0; int rv; unsigned int len; #ifdef OLDER_OPENSSL ICA_AES_192_CTX *pCtx = ctx->cipher_data; #else ICA_AES_192_CTX *pCtx = (ICA_AES_192_CTX *) EVP_CIPHER_CTX_get_cipher_data(ctx); #endif ica_aes_vector_t pre_iv; if (inlen > UINT32_MAX) { IBMCAerr(IBMCA_F_IBMCA_AES_192_CIPHER, IBMCA_R_OUTLEN_TO_LARGE); return 0; } len = inlen; if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_ECB_MODE) { mode = MODE_ECB; } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CBC_MODE) { mode = MODE_CBC; } else if ((EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_CFB_MODE) && (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE)) { IBMCAerr(IBMCA_F_IBMCA_AES_192_CIPHER, IBMCA_R_CIPHER_MODE_NOT_SUPPORTED); return 0; } #ifdef OLDER_OPENSSL if (ctx->encrypt) { #else if (EVP_CIPHER_CTX_encrypting(ctx)) { #endif if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { rv = p_ica_aes_cfb(in, out, len, pCtx->key, AES_KEY_LEN192, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_BLOCK_SIZE, ICA_ENCRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_aes_ofb(in, out, len, pCtx->key, AES_KEY_LEN192, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_ENCRYPT); } else { rv = p_ica_aes_encrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_aes_vector_t *)ctx->iv, #else (ica_aes_vector_t *)EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_KEY_LEN192, (unsigned char *)pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_AES_192_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif out + len - EVP_CIPHER_CTX_iv_length(ctx), EVP_CIPHER_CTX_iv_length(ctx)); } } else { if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { /* Protect against decrypt in place */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_aes_cfb(in, out, len, pCtx->key, AES_KEY_LEN192, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_BLOCK_SIZE, ICA_DECRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_aes_ofb(in, out, len, pCtx->key, AES_KEY_LEN192, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_DECRYPT); } else { /* Protect against decrypt in place */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_aes_decrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_aes_vector_t *)ctx->iv, #else (ica_aes_vector_t *)EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_KEY_LEN192, (unsigned char *)pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_AES_192_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif pre_iv, EVP_CIPHER_CTX_iv_length(ctx)); } } return 1; } static int ibmca_aes_256_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, const unsigned char *in, size_t inlen) { int mode = 0; int rv; unsigned int len; #ifdef OLDER_OPENSSL ICA_AES_256_CTX *pCtx = ctx->cipher_data; #else ICA_AES_256_CTX *pCtx = (ICA_AES_256_CTX *) EVP_CIPHER_CTX_get_cipher_data(ctx); #endif ica_aes_vector_t pre_iv; if (inlen > UINT32_MAX) { IBMCAerr(IBMCA_F_IBMCA_AES_256_CIPHER, IBMCA_R_OUTLEN_TO_LARGE); return 0; } len = inlen; if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_ECB_MODE) { mode = MODE_ECB; } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CBC_MODE) { mode = MODE_CBC; } else if ((EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_CFB_MODE) && (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE)) { IBMCAerr(IBMCA_F_IBMCA_AES_256_CIPHER, IBMCA_R_CIPHER_MODE_NOT_SUPPORTED); return 0; } #ifdef OLDER_OPENSSL if (ctx->encrypt) { #else if (EVP_CIPHER_CTX_encrypting(ctx)) { #endif if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { rv = p_ica_aes_cfb(in, out, len, pCtx->key, AES_KEY_LEN256, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_BLOCK_SIZE, ICA_ENCRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_aes_ofb(in, out, len, pCtx->key, AES_KEY_LEN256, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_ENCRYPT); } else { rv = p_ica_aes_encrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_aes_vector_t *)ctx->iv, #else (ica_aes_vector_t *)EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_KEY_LEN256, (unsigned char *)pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_AES_256_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif out + len - EVP_CIPHER_CTX_iv_length(ctx), EVP_CIPHER_CTX_iv_length(ctx)); } } else { if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) { /* Protect against decrypt in place */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_aes_cfb(in, out, len, pCtx->key, AES_KEY_LEN256, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_BLOCK_SIZE, ICA_DECRYPT); } else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) { rv = p_ica_aes_ofb(in, out, len, pCtx->key, AES_KEY_LEN256, #ifdef OLDER_OPENSSL ctx->iv, #else EVP_CIPHER_CTX_iv_noconst(ctx), #endif ICA_DECRYPT); } else { /* Protect against decrypt in place */ memcpy(pre_iv, in + len - sizeof(pre_iv), sizeof(pre_iv)); rv = p_ica_aes_decrypt(mode, len, (unsigned char *)in, #ifdef OLDER_OPENSSL (ica_aes_vector_t *)ctx->iv, #else (ica_aes_vector_t *)EVP_CIPHER_CTX_iv_noconst(ctx), #endif AES_KEY_LEN256, (unsigned char *)pCtx->key, out); } if (rv) { IBMCAerr(IBMCA_F_IBMCA_AES_256_CIPHER, IBMCA_R_REQUEST_FAILED); return 0; } else if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_OFB_MODE) { #ifdef OLDER_OPENSSL memcpy(ctx->iv, #else memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), #endif pre_iv, EVP_CIPHER_CTX_iv_length(ctx)); } } return 1; } static int ibmca_cipher_cleanup(EVP_CIPHER_CTX * ctx) { return 1; } #ifndef OPENSSL_NO_AES_GCM static int ibmca_gcm_aad(ICA_AES_GCM_CTX *ctx, const unsigned char *aad, size_t len, int enc, int keylen) { uint64_t alen = ctx->aadlen; if (ctx->ptlen) return -2; alen += len; if (alen > (1ULL << 61) || (sizeof(len) == 8 && alen < len)) return -1; ctx->aadlen = alen; /* ctx->taglen is not set at this time... and is not needed. The * function only checks, if it's a valid gcm tag length. So we chose * 16. */ return !(p_ica_aes_gcm_intermediate(NULL, 0, NULL, ctx->ucb, (unsigned char *)aad, len, ctx->tag, 16, ctx->key, keylen, ctx->subkey, enc)); } static int ibmca_aes_gcm(ICA_AES_GCM_CTX *ctx, const unsigned char *in, unsigned char *out, size_t len, int enc, int keylen) { uint64_t mlen = ctx->ptlen; unsigned char *pt, *ct; int rv; mlen += len; if (mlen > ((1ULL << 36) - 32) || (sizeof(len) == 8 && mlen < len)) return -1; ctx->ptlen = mlen; if (enc) { pt = (unsigned char *)in; ct = out; } else { ct = (unsigned char *)in; pt = out; } /* ctx->taglen is not set at this time... and is not needed. The * function only checks, if it's a valid gcm tag length. So we chose * 16. */ rv = !(p_ica_aes_gcm_intermediate(pt, len, ct, ctx->ucb, NULL, 0, ctx->tag, 16, ctx->key, keylen, ctx->subkey, enc)); return rv; } static int ibmca_aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { ICA_AES_GCM_CTX *gctx = (ICA_AES_GCM_CTX *)EVP_CIPHER_CTX_get_cipher_data(ctx); const int gkeylen = EVP_CIPHER_CTX_key_length(ctx); if (!iv && !key) return 1; if (key) { memcpy(gctx->key, key, gkeylen); if (iv == NULL && gctx->iv_set) iv = gctx->iv; if (iv) { memset(gctx->icb, 0, sizeof(gctx->icb)); memset(gctx->tag, 0, sizeof(gctx->tag)); gctx->aadlen = 0; gctx->ptlen = 0; if (p_ica_aes_gcm_initialize(iv, gctx->ivlen, gctx->key, gkeylen, gctx->icb, gctx->ucb, gctx->subkey, enc)) return 0; gctx->iv_set = 1; } gctx->key_set = 1; } else { if (gctx->key_set) { memset(gctx->icb, 0, sizeof(gctx->icb)); memset(gctx->tag, 0, sizeof(gctx->tag)); gctx->aadlen = 0; gctx->ptlen = 0; if (p_ica_aes_gcm_initialize(iv, gctx->ivlen, gctx->key, gkeylen, gctx->icb, gctx->ucb, gctx->subkey, enc)) return 0; } else { memcpy(gctx->iv, iv, gctx->ivlen); } gctx->iv_set = 1; gctx->iv_gen = 0; } return 1; } static int ibmca_aes_gcm_setiv(EVP_CIPHER_CTX *c) { ICA_AES_GCM_CTX *gctx = (ICA_AES_GCM_CTX *)EVP_CIPHER_CTX_get_cipher_data(c); const int gkeylen = EVP_CIPHER_CTX_key_length(c); int enc = EVP_CIPHER_CTX_encrypting(c); if (gctx->key == NULL || !gctx->key_set) return 0; memset(gctx->icb, 0, sizeof(gctx->icb)); memset(gctx->tag, 0, sizeof(gctx->tag)); gctx->aadlen = 0; gctx->ptlen = 0; return !(p_ica_aes_gcm_initialize(gctx->iv, gctx->ivlen, gctx->key, gkeylen, gctx->icb, gctx->ucb, gctx->subkey, enc)); } static int ibmca_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { ICA_AES_GCM_CTX *gctx = (ICA_AES_GCM_CTX *)EVP_CIPHER_CTX_get_cipher_data(c); unsigned char *iv_noconst = EVP_CIPHER_CTX_iv_noconst(c); unsigned char *buf_noconst = EVP_CIPHER_CTX_buf_noconst(c); int enc = EVP_CIPHER_CTX_encrypting(c); EVP_CIPHER_CTX *out; ICA_AES_GCM_CTX *gctx_out; unsigned char *iv_noconst_out; unsigned int len; switch (type) { case EVP_CTRL_INIT: gctx->key_set = 0; gctx->iv_set = 0; gctx->ivlen = EVP_CIPHER_CTX_iv_length(c); gctx->iv = iv_noconst; gctx->taglen = -1; gctx->iv_gen = 0; gctx->tls_aadlen = -1; return 1; case EVP_CTRL_GCM_SET_IVLEN: if (arg <= 0) return 0; if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) { if (gctx->iv != iv_noconst) OPENSSL_free(gctx->iv); gctx->iv = OPENSSL_malloc(arg); if (gctx->iv == NULL) return 0; } gctx->ivlen = arg; return 1; case EVP_CTRL_GCM_SET_TAG: if (arg <= 0 || arg > 16 || enc) return 0; memcpy(buf_noconst, ptr, arg); gctx->taglen = arg; return 1; case EVP_CTRL_GCM_GET_TAG: if (arg <= 0 || arg > 16 || !enc || gctx->taglen < 0) return 0; memcpy(ptr, buf_noconst, arg); return 1; case EVP_CTRL_GCM_SET_IV_FIXED: if (arg == -1) { memcpy(gctx->iv, ptr, gctx->ivlen); gctx->iv_gen = 1; return 1; } if ((arg < 4) || (gctx->ivlen - arg) < 8) return 0; if (arg) memcpy(gctx->iv, ptr, arg); if (enc && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) return 0; gctx->iv_gen = 1; return 1; case EVP_CTRL_GCM_IV_GEN: if (gctx->iv_gen == 0 || gctx->key_set == 0) return 0; if (!ibmca_aes_gcm_setiv(c)) return 0; if (arg <= 0 || arg > gctx->ivlen) arg = gctx->ivlen; memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg); ++*(uint64_t *)(gctx->iv + gctx->ivlen - 8); gctx->iv_set = 1; return 1; case EVP_CTRL_GCM_SET_IV_INV: if (gctx->iv_gen == 0 || gctx->key_set == 0 || enc) return 0; memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg); if (!ibmca_aes_gcm_setiv(c)) return 0; gctx->iv_set = 1; return 1; case EVP_CTRL_AEAD_TLS1_AAD: if (arg != EVP_AEAD_TLS1_AAD_LEN) return 0; memcpy(buf_noconst, ptr, arg); gctx->tls_aadlen = arg; len = buf_noconst[arg - 2] << 8 | buf_noconst[arg - 1]; if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN) return 0; len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; if (!enc) { if (len < EVP_GCM_TLS_TAG_LEN) return 0; len -= EVP_GCM_TLS_TAG_LEN; } buf_noconst[arg - 2] = len >> 8; buf_noconst[arg - 1] = len & 0xff; return EVP_GCM_TLS_TAG_LEN; case EVP_CTRL_COPY: { out = ptr; gctx_out = (ICA_AES_GCM_CTX *) EVP_CIPHER_CTX_get_cipher_data(out); iv_noconst_out = EVP_CIPHER_CTX_iv_noconst(out); if (gctx->iv == iv_noconst) { gctx_out->iv = iv_noconst_out; } else { gctx_out->iv = OPENSSL_malloc(gctx->ivlen); if (gctx_out->iv == NULL) return 0; memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); } return 1; } default: return -1; } } static int ibmca_gcm_tag(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, int taglen) { ICA_AES_GCM_CTX *gctx = (ICA_AES_GCM_CTX *)EVP_CIPHER_CTX_get_cipher_data(ctx); int enc = EVP_CIPHER_CTX_encrypting(ctx); const int gkeylen = EVP_CIPHER_CTX_key_length(ctx); if (p_ica_aes_gcm_last(gctx->icb, gctx->aadlen, gctx->ptlen, gctx->tag, (unsigned char *)in, taglen, gctx->key, gkeylen, gctx->subkey, enc)) return 0; if (out) memcpy(out, gctx->tag, taglen); return 1; } static int ibmca_aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { ICA_AES_GCM_CTX *gctx = (ICA_AES_GCM_CTX *)EVP_CIPHER_CTX_get_cipher_data(ctx); unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); int enc = EVP_CIPHER_CTX_encrypting(ctx); const int keylen = EVP_CIPHER_CTX_key_length(ctx); int rv = -1; if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) return -1; if (EVP_CIPHER_CTX_ctrl(ctx, enc ? EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV, EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) goto err; if (!ibmca_gcm_aad(gctx, buf, gctx->tls_aadlen, enc, keylen)) goto err; in += EVP_GCM_TLS_EXPLICIT_IV_LEN; out += EVP_GCM_TLS_EXPLICIT_IV_LEN; len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; if (!ibmca_aes_gcm(gctx, in, out, len, enc, keylen)) goto err; if (enc) { out += len; if (!ibmca_gcm_tag(ctx, out, NULL, EVP_GCM_TLS_TAG_LEN)) { goto err; } rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; } else { if (!ibmca_gcm_tag(ctx, buf, in + len, EVP_GCM_TLS_TAG_LEN)) { OPENSSL_cleanse(out, len); goto err; } rv = len; } err: gctx->iv_set = 0; gctx->tls_aadlen = -1; return rv; } static int ibmca_aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { ICA_AES_GCM_CTX *gctx = (ICA_AES_GCM_CTX *)EVP_CIPHER_CTX_get_cipher_data(ctx); unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); int enc = EVP_CIPHER_CTX_encrypting(ctx); const int keylen = EVP_CIPHER_CTX_key_length(ctx); if (!gctx->key_set) return -1; if (gctx->tls_aadlen >= 0) return ibmca_aes_gcm_tls_cipher(ctx, out, in, len); if (!gctx->iv_set) return -1; if (in) { if (out == NULL) { if (!ibmca_gcm_aad(gctx, in, len, enc, keylen)) return -1; } else { if (!ibmca_aes_gcm(gctx, in, out, len, enc, keylen)) return -1; } return len; } else { if (enc) { gctx->taglen = 16; if (!ibmca_gcm_tag(ctx, buf, NULL, gctx->taglen)) return -1; } else { if (gctx->taglen < 0) return -1; if (!ibmca_gcm_tag(ctx, NULL, buf, gctx->taglen)) return -1; } gctx->iv_set = 0; return 0; } } #endif static int ibmca_engine_digests(ENGINE * e, const EVP_MD ** digest, const int **nids, int nid) { int i; if (!digest) return (ibmca_usable_digests(nids)); *digest = NULL; for(i = 0; i < size_digest_list;i++) if(nid == ibmca_digest_lists.nids[i]){ *digest = (EVP_MD*) ibmca_digest_lists.crypto_meths[i]; break; } return (*digest != NULL); } static int ibmca_usable_digests(const int **nids) { if(nids) *nids = ibmca_digest_lists.nids; return size_digest_list; } #ifndef OPENSSL_NO_SHA1 static int ibmca_sha1_init(EVP_MD_CTX * ctx) { #ifdef OLDER_OPENSSL IBMCA_SHA_CTX *ibmca_sha_ctx = ctx->md_data; #else IBMCA_SHA_CTX *ibmca_sha_ctx = (IBMCA_SHA_CTX *) EVP_MD_CTX_md_data(ctx); #endif memset((unsigned char *)ibmca_sha_ctx, 0, sizeof(*ibmca_sha_ctx)); return 1; } static int ibmca_sha1_update(EVP_MD_CTX * ctx, const void *in_data, unsigned long inlen) { #ifdef OLDER_OPENSSL IBMCA_SHA_CTX *ibmca_sha_ctx = ctx->md_data; #else IBMCA_SHA_CTX *ibmca_sha_ctx = (IBMCA_SHA_CTX *) EVP_MD_CTX_md_data(ctx); #endif unsigned int message_part=SHA_MSG_PART_MIDDLE, fill_size=0; unsigned long in_data_len=inlen; unsigned char tmp_hash[SHA_HASH_LENGTH]; if (in_data_len == 0) return 1; if( ibmca_sha_ctx->c.runningLength == 0 && ibmca_sha_ctx->tail_len == 0) { message_part = SHA_MSG_PART_FIRST; ibmca_sha_ctx->tail_len = in_data_len & 0x3f; if(ibmca_sha_ctx->tail_len) { in_data_len &= ~0x3f; memcpy(ibmca_sha_ctx->tail, in_data + in_data_len, ibmca_sha_ctx->tail_len); } } else if( ibmca_sha_ctx->c.runningLength == 0 && ibmca_sha_ctx->tail_len > 0 ) { /* Here we need to fill out the temporary tail buffer until * it has 64 bytes in it, then call ica_sha1 on that buffer. * If there weren't enough bytes passed in to fill it out, * just copy in what we can and return success without calling * ica_sha1. - KEY */ fill_size = SHA_BLOCK_SIZE - ibmca_sha_ctx->tail_len; if(fill_size < in_data_len) { memcpy(ibmca_sha_ctx->tail + ibmca_sha_ctx->tail_len, in_data, fill_size); /* Submit the filled out tail buffer */ if( p_ica_sha1( (unsigned int)SHA_MSG_PART_FIRST, (unsigned int)SHA_BLOCK_SIZE, ibmca_sha_ctx->tail, &ibmca_sha_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA1_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } } else { memcpy(ibmca_sha_ctx->tail + ibmca_sha_ctx->tail_len, in_data, in_data_len); ibmca_sha_ctx->tail_len += in_data_len; return 1; } /* We had to use 'fill_size' bytes from in_data to fill out the * empty part of save data, so adjust in_data_len */ in_data_len -= fill_size; ibmca_sha_ctx->tail_len = in_data_len & 0x3f; if(ibmca_sha_ctx->tail_len) { in_data_len &= ~0x3f; memcpy(ibmca_sha_ctx->tail, in_data + fill_size + in_data_len, ibmca_sha_ctx->tail_len); // fill_size is added to in_data down below } } else if( ibmca_sha_ctx->c.runningLength > 0 ) { if(ibmca_sha_ctx->tail_len) { fill_size = SHA_BLOCK_SIZE - ibmca_sha_ctx->tail_len; if(fill_size < in_data_len) { memcpy(ibmca_sha_ctx->tail + ibmca_sha_ctx->tail_len, in_data, fill_size); /* Submit the filled out save buffer */ if( p_ica_sha1( message_part, (unsigned int)SHA_BLOCK_SIZE, ibmca_sha_ctx->tail, &ibmca_sha_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA1_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } } else { memcpy(ibmca_sha_ctx->tail + ibmca_sha_ctx->tail_len, in_data, in_data_len); ibmca_sha_ctx->tail_len += in_data_len; return 1; } /* * We had to use some of the data from in_data to * fill out the empty part of save data, so adjust * in_data_len */ in_data_len -= fill_size; ibmca_sha_ctx->tail_len = in_data_len & 0x3f; if(ibmca_sha_ctx->tail_len) { in_data_len &= ~0x3f; memcpy(ibmca_sha_ctx->tail, in_data + fill_size +in_data_len, ibmca_sha_ctx->tail_len); } } else { /* This is the odd case, where we need to go ahead and * send the first X * 64 byte chunks in to be processed * and copy the last <64 byte area into the tail. -KEY */ ibmca_sha_ctx->tail_len = in_data_len & 0x3f; if( ibmca_sha_ctx->tail_len) { in_data_len &= ~0x3f; memcpy(ibmca_sha_ctx->tail, in_data + in_data_len, ibmca_sha_ctx->tail_len); } } } /* If the data passed in was <64 bytes, in_data_len will be 0 */ if( in_data_len && p_ica_sha1(message_part, (unsigned int)in_data_len, (unsigned char *)(in_data + fill_size), &ibmca_sha_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA1_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } return 1; } static int ibmca_sha1_final(EVP_MD_CTX * ctx, unsigned char *md) { #ifdef OLDER_OPENSSL IBMCA_SHA_CTX *ibmca_sha_ctx = ctx->md_data; #else IBMCA_SHA_CTX *ibmca_sha_ctx = (IBMCA_SHA_CTX *) EVP_MD_CTX_md_data(ctx); #endif unsigned int message_part = 0; if (ibmca_sha_ctx->c.runningLength) message_part = SHA_MSG_PART_FINAL; else message_part = SHA_MSG_PART_ONLY; if( p_ica_sha1(message_part, ibmca_sha_ctx->tail_len, (unsigned char *)ibmca_sha_ctx->tail, &ibmca_sha_ctx->c, md)) { IBMCAerr(IBMCA_F_IBMCA_SHA1_FINAL, IBMCA_R_REQUEST_FAILED); return 0; } return 1; } // end ibmca_sha1_final static int ibmca_sha1_cleanup(EVP_MD_CTX * ctx) { return 1; } // end ibmca_sha1_cleanup #endif // OPENSSL_NO_SHA1 #ifndef OPENSSL_NO_SHA256 static int ibmca_sha256_init(EVP_MD_CTX *ctx) { #ifdef OLDER_OPENSSL IBMCA_SHA256_CTX *ibmca_sha256_ctx = ctx->md_data; #else IBMCA_SHA256_CTX *ibmca_sha256_ctx = (IBMCA_SHA256_CTX *) EVP_MD_CTX_md_data(ctx); #endif memset((unsigned char *)ibmca_sha256_ctx, 0, sizeof(*ibmca_sha256_ctx)); return 1; } // end ibmca_sha256_init static int ibmca_sha256_update(EVP_MD_CTX *ctx, const void *in_data, unsigned long inlen) { #ifdef OLDER_OPENSSL IBMCA_SHA256_CTX *ibmca_sha256_ctx = ctx->md_data; #else IBMCA_SHA256_CTX *ibmca_sha256_ctx = (IBMCA_SHA256_CTX *) EVP_MD_CTX_md_data(ctx); #endif unsigned int message_part = SHA_MSG_PART_MIDDLE, fill_size = 0; unsigned long in_data_len = inlen; unsigned char tmp_hash[SHA256_HASH_LENGTH]; if (in_data_len == 0) return 1; if (ibmca_sha256_ctx->c.runningLength == 0 && ibmca_sha256_ctx->tail_len == 0) { message_part = SHA_MSG_PART_FIRST; ibmca_sha256_ctx->tail_len = in_data_len & 0x3f; if(ibmca_sha256_ctx->tail_len) { in_data_len &= ~0x3f; memcpy(ibmca_sha256_ctx->tail, in_data + in_data_len, ibmca_sha256_ctx->tail_len); } } else if (ibmca_sha256_ctx->c.runningLength == 0 && ibmca_sha256_ctx->tail_len > 0 ) { /* Here we need to fill out the temporary tail buffer * until it has 64 bytes in it, then call ica_sha256 on * that buffer. If there weren't enough bytes passed * in to fill it out, just copy in what we can and * return success without calling ica_sha256. - KEY */ fill_size = SHA256_BLOCK_SIZE - ibmca_sha256_ctx->tail_len; if (fill_size < in_data_len) { memcpy(ibmca_sha256_ctx->tail + ibmca_sha256_ctx->tail_len, in_data, fill_size); /* Submit the filled out tail buffer */ if (p_ica_sha256((unsigned int)SHA_MSG_PART_FIRST, (unsigned int)SHA256_BLOCK_SIZE, ibmca_sha256_ctx->tail, &ibmca_sha256_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA256_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } } else { memcpy(ibmca_sha256_ctx->tail + ibmca_sha256_ctx->tail_len, in_data, in_data_len); ibmca_sha256_ctx->tail_len += in_data_len; return 1; } /* We had to use 'fill_size' bytes from in_data to fill out the * empty part of save data, so adjust in_data_len */ in_data_len -= fill_size; ibmca_sha256_ctx->tail_len = in_data_len & 0x3f; if(ibmca_sha256_ctx->tail_len) { in_data_len &= ~0x3f; memcpy(ibmca_sha256_ctx->tail, in_data + fill_size + in_data_len, ibmca_sha256_ctx->tail_len); /* fill_size is added to in_data down below */ } } else if (ibmca_sha256_ctx->c.runningLength > 0) { if (ibmca_sha256_ctx->tail_len) { fill_size = SHA256_BLOCK_SIZE - ibmca_sha256_ctx->tail_len; if (fill_size < in_data_len) { memcpy(ibmca_sha256_ctx->tail + ibmca_sha256_ctx->tail_len, in_data, fill_size); /* Submit the filled out save buffer */ if (p_ica_sha256(message_part, (unsigned int)SHA256_BLOCK_SIZE, ibmca_sha256_ctx->tail, &ibmca_sha256_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA256_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } } else { memcpy(ibmca_sha256_ctx->tail + ibmca_sha256_ctx->tail_len, in_data, in_data_len); ibmca_sha256_ctx->tail_len += in_data_len; return 1; } /* * We had to use some of the data from in_data to * fill out the empty part of save data, so adjust * in_data_len */ in_data_len -= fill_size; ibmca_sha256_ctx->tail_len = in_data_len & 0x3f; if (ibmca_sha256_ctx->tail_len) { in_data_len &= ~0x3f; memcpy(ibmca_sha256_ctx->tail, in_data + fill_size + in_data_len, ibmca_sha256_ctx->tail_len); } } else { /* This is the odd case, where we need to go * ahead and send the first X * 64 byte chunks * in to be processed and copy the last <64 * byte area into the tail. -KEY */ ibmca_sha256_ctx->tail_len = in_data_len & 0x3f; if (ibmca_sha256_ctx->tail_len) { in_data_len &= ~0x3f; memcpy(ibmca_sha256_ctx->tail, in_data + in_data_len, ibmca_sha256_ctx->tail_len); } } } /* If the data passed in was <64 bytes, in_data_len will be 0 */ if (in_data_len && p_ica_sha256(message_part, (unsigned int)in_data_len, (unsigned char *)(in_data + fill_size), &ibmca_sha256_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA256_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } return 1; } // end ibmca_sha256_update static int ibmca_sha256_final(EVP_MD_CTX *ctx, unsigned char *md) { #ifdef OLDER_OPENSSL IBMCA_SHA256_CTX *ibmca_sha256_ctx = ctx->md_data; #else IBMCA_SHA256_CTX *ibmca_sha256_ctx = (IBMCA_SHA256_CTX *) EVP_MD_CTX_md_data(ctx); #endif unsigned int message_part = 0; if (ibmca_sha256_ctx->c.runningLength) message_part = SHA_MSG_PART_FINAL; else message_part = SHA_MSG_PART_ONLY; if (p_ica_sha256(message_part, ibmca_sha256_ctx->tail_len, (unsigned char *)ibmca_sha256_ctx->tail, &ibmca_sha256_ctx->c, md)) { IBMCAerr(IBMCA_F_IBMCA_SHA256_FINAL, IBMCA_R_REQUEST_FAILED); return 0; } return 1; } // end ibmca_sha256_final static int ibmca_sha256_cleanup(EVP_MD_CTX *ctx) { return 1; } // end ibmca_sha256_cleanup #endif // OPENSSL_NO_SHA256 #ifndef OPENSSL_NO_SHA512 static int ibmca_sha512_init(EVP_MD_CTX *ctx) { #ifdef OLDER_OPENSSL IBMCA_SHA512_CTX *ibmca_sha512_ctx = ctx->md_data; #else IBMCA_SHA512_CTX *ibmca_sha512_ctx = (IBMCA_SHA512_CTX *) EVP_MD_CTX_md_data(ctx); #endif memset((unsigned char *)ibmca_sha512_ctx, 0, sizeof(*ibmca_sha512_ctx)); return 1; } static int ibmca_sha512_update(EVP_MD_CTX *ctx, const void *in_data, unsigned long inlen) { #ifdef OLDER_OPENSSL IBMCA_SHA512_CTX *ibmca_sha512_ctx = ctx->md_data; #else IBMCA_SHA512_CTX *ibmca_sha512_ctx = (IBMCA_SHA512_CTX *) EVP_MD_CTX_md_data(ctx); #endif unsigned int message_part = SHA_MSG_PART_MIDDLE, fill_size = 0; unsigned long in_data_len = inlen; unsigned char tmp_hash[SHA512_HASH_LENGTH]; if (in_data_len == 0) return 1; if (ibmca_sha512_ctx->c.runningLengthLow == 0 && ibmca_sha512_ctx->tail_len == 0) { message_part = SHA_MSG_PART_FIRST; ibmca_sha512_ctx->tail_len = in_data_len & 0x7f; if (ibmca_sha512_ctx->tail_len) { in_data_len &= ~0x7f; memcpy(ibmca_sha512_ctx->tail, in_data + in_data_len, ibmca_sha512_ctx->tail_len); } } else if (ibmca_sha512_ctx->c.runningLengthLow == 0 && ibmca_sha512_ctx->tail_len > 0 ) { /* Here we need to fill out the temporary tail buffer * until it has 128 bytes in it, then call ica_sha512 on * that buffer. If there weren't enough bytes passed * in to fill it out, just copy in what we can and * return success without calling ica_sha512. */ fill_size = SHA512_BLOCK_SIZE - ibmca_sha512_ctx->tail_len; if (fill_size < in_data_len) { memcpy(ibmca_sha512_ctx->tail + ibmca_sha512_ctx->tail_len, in_data, fill_size); /* Submit the filled out tail buffer */ if (p_ica_sha512((unsigned int)SHA_MSG_PART_FIRST, (unsigned int)SHA512_BLOCK_SIZE, ibmca_sha512_ctx->tail, &ibmca_sha512_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA512_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } } else { memcpy(ibmca_sha512_ctx->tail + ibmca_sha512_ctx->tail_len, in_data, in_data_len); ibmca_sha512_ctx->tail_len += in_data_len; return 1; } /* We had to use 'fill_size' bytes from in_data to fill out the * empty part of save data, so adjust in_data_len */ in_data_len -= fill_size; ibmca_sha512_ctx->tail_len = in_data_len & 0x7f; if (ibmca_sha512_ctx->tail_len) { in_data_len &= ~0x7f; memcpy(ibmca_sha512_ctx->tail, in_data + fill_size + in_data_len, ibmca_sha512_ctx->tail_len); /* fill_size is added to in_data down below */ } } else if (ibmca_sha512_ctx->c.runningLengthLow > 0) { if (ibmca_sha512_ctx->tail_len) { fill_size = SHA512_BLOCK_SIZE - ibmca_sha512_ctx->tail_len; if (fill_size < in_data_len) { memcpy(ibmca_sha512_ctx->tail + ibmca_sha512_ctx->tail_len, in_data, fill_size); /* Submit the filled out save buffer */ if (p_ica_sha512(message_part, (unsigned int)SHA512_BLOCK_SIZE, ibmca_sha512_ctx->tail, &ibmca_sha512_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA512_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } } else { memcpy(ibmca_sha512_ctx->tail + ibmca_sha512_ctx->tail_len, in_data, in_data_len); ibmca_sha512_ctx->tail_len += in_data_len; return 1; } /* * We had to use some of the data from in_data to * fill out the empty part of save data, so adjust * in_data_len */ in_data_len -= fill_size; ibmca_sha512_ctx->tail_len = in_data_len & 0x7f; if (ibmca_sha512_ctx->tail_len) { in_data_len &= ~0x7f; memcpy(ibmca_sha512_ctx->tail, in_data + fill_size + in_data_len, ibmca_sha512_ctx->tail_len); } } else { /* This is the odd case, where we need to go * ahead and send the first X * 128 byte chunks * in to be processed and copy the last <128 * byte area into the tail. */ ibmca_sha512_ctx->tail_len = in_data_len & 0x7f; if (ibmca_sha512_ctx->tail_len) { in_data_len &= ~0x7f; memcpy(ibmca_sha512_ctx->tail, in_data + in_data_len, ibmca_sha512_ctx->tail_len); } } } /* If the data passed in was <128 bytes, in_data_len will be 0 */ if (in_data_len && p_ica_sha512(message_part, (unsigned int)in_data_len, (unsigned char *)(in_data + fill_size), &ibmca_sha512_ctx->c, tmp_hash)) { IBMCAerr(IBMCA_F_IBMCA_SHA512_UPDATE, IBMCA_R_REQUEST_FAILED); return 0; } return 1; } static int ibmca_sha512_final(EVP_MD_CTX *ctx, unsigned char *md) { #ifdef OLDER_OPENSSL IBMCA_SHA512_CTX *ibmca_sha512_ctx = ctx->md_data; #else IBMCA_SHA512_CTX *ibmca_sha512_ctx = (IBMCA_SHA512_CTX *) EVP_MD_CTX_md_data(ctx); #endif unsigned int message_part = 0; if (ibmca_sha512_ctx->c.runningLengthLow) message_part = SHA_MSG_PART_FINAL; else message_part = SHA_MSG_PART_ONLY; if (p_ica_sha512(message_part, ibmca_sha512_ctx->tail_len, (unsigned char *)ibmca_sha512_ctx->tail, &ibmca_sha512_ctx->c, md)) { IBMCAerr(IBMCA_F_IBMCA_SHA512_FINAL, IBMCA_R_REQUEST_FAILED); return 0; } return 1; } static int ibmca_sha512_cleanup(EVP_MD_CTX *ctx) { return 1; } #endif // OPENSSL_NO_SHA512 static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) { /* r = (a^p) mod m r = output a = input p = exponent m = modulus */ unsigned char *input = NULL, *output = NULL; ica_rsa_key_mod_expo_t *key = NULL; unsigned int rc; int plen, mlen, inputlen; if (!ibmca_dso) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_NOT_LOADED); goto err; } /* make necessary memory allocations FIXME: Would it be possible to minimize memory allocation overhead by either allocating it all at once or having a static storage? */ key = (ica_rsa_key_mod_expo_t *) calloc(1, sizeof(ica_rsa_key_mod_expo_t)); if (key == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } key->key_length = mlen = BN_num_bytes(m); key->modulus = (unsigned char *) calloc(1, key->key_length); if (key->modulus == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } plen = BN_num_bytes(p); /* despite plen, key->exponent must be key->key_length in size */ key->exponent = (unsigned char *) calloc(1, key->key_length); if (key->exponent == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } inputlen = BN_num_bytes(a); /* despite inputlen, input and output must be key->key_length in size */ input = (unsigned char *) calloc(1, key->key_length); if (input == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } output = (unsigned char *) calloc(1, key->key_length); if (output == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } /* Now convert from BIGNUM representation. * Everything must be right-justified */ BN_bn2bin(m, key->modulus); BN_bn2bin(p, key->exponent + key->key_length - plen); BN_bn2bin(a, input + key->key_length - inputlen); /* execute the ica mod_exp call */ rc = p_ica_rsa_mod_expo(ibmca_handle, input, key, output); if (rc != 0) { goto err; } else { rc = 1; } /* Convert output to BIGNUM representation. * right-justified output applies */ /* BN_bin2bn((unsigned char *) (output + key->key_length - inputlen), inputlen, r); */ BN_bin2bn((unsigned char *) output, key->key_length, r); goto end; err: rc = 0; /* error condition */ end: free(key->exponent); free(key->modulus); free(key); free(input); free(output); return rc; } #ifndef OPENSSL_NO_RSA static int ibmca_rsa_init(RSA *rsa) { RSA_blinding_off(rsa); return 1; } #ifdef OLDER_OPENSSL static int ibmca_rsa_mod_exp(BIGNUM * r0, const BIGNUM * I, RSA * rsa, BN_CTX *ctx) { int to_return = 0; if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { if (!rsa->d || !rsa->n) { IBMCAerr(IBMCA_F_IBMCA_RSA_MOD_EXP, IBMCA_R_MISSING_KEY_COMPONENTS); goto err; } to_return = ibmca_mod_exp(r0, I, rsa->d, rsa->n, ctx); } else { to_return = ibmca_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, rsa->dmq1, rsa->iqmp, ctx); } err: return to_return; } #else static int ibmca_rsa_mod_exp(BIGNUM * r0, const BIGNUM * I, RSA * rsa, BN_CTX *ctx) { int to_return = 0; const BIGNUM *d, *n, *p, *q, *dmp1, *dmq1, *iqmp; RSA_get0_key(rsa, &n, NULL, &d); RSA_get0_factors(rsa, &p, &q); RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); if (!p || !q || !dmp1 || !dmq1 || iqmp) { if (!d || !n) { IBMCAerr(IBMCA_F_IBMCA_RSA_MOD_EXP, IBMCA_R_MISSING_KEY_COMPONENTS); goto err; } to_return = ibmca_mod_exp(r0, I, d, n, ctx); } else { to_return = ibmca_mod_exp_crt(r0, I, p, q, dmp1, dmq1, iqmp, ctx); } err: return to_return; } #endif #endif /* Ein kleines chinesisches "Restessen" */ static int ibmca_mod_exp_crt(BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * q, const BIGNUM * dmp1, const BIGNUM * dmq1, const BIGNUM * iqmp, BN_CTX * ctx) { /* r = output a = input p and q are themselves dmp1, dmq1 are dp and dq respectively iqmp is qInverse */ ica_rsa_key_crt_t *key = NULL; unsigned char *output = NULL, *input = NULL; int rc; int plen, qlen, dplen, dqlen, qInvlen; int inputlen; /* make necessary memory allocations FIXME: Would it be possible to minimize memory allocation overhead by either allocating it all at once or having a static storage? */ key = (ica_rsa_key_crt_t *) calloc(1, sizeof(ica_rsa_key_crt_t)); if (key == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } /* 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. */ plen = BN_num_bytes(p); qlen = BN_num_bytes(q); key->key_length = 2 * (plen > qlen ? plen : qlen); key->p = (unsigned char *) calloc(1, (key->key_length/2) + 8); if (key->p == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } dplen = BN_num_bytes(dmp1); key->dp = (unsigned char *) calloc(1, (key->key_length/2) + 8); if (key->dp == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } key->q = (unsigned char *) calloc(1, key->key_length/2); if (key->q == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } dqlen = BN_num_bytes(dmq1); key->dq = (unsigned char *) calloc(1, key->key_length/2); if (key->dq == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } qInvlen = BN_num_bytes(iqmp); key->qInverse = (unsigned char *) calloc(1, (key->key_length/2) + 8); if (key->qInverse == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } inputlen = BN_num_bytes(a); if (inputlen > key->key_length) { /* input can't be larger than key */ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } /* allocate input to the size of key_length in bytes, and * pad front with zero if inputlen < key->key_length */ input = (unsigned char *) calloc(1, key->key_length); if (input == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } /* output must also be key_length in size */ output = (unsigned char *) calloc(1, key->key_length); if (output == NULL) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } /* Now convert from BIGNUM representation. * p, dp and qInverse have an additional 8-byte padding, * and everything must be right-justified */ BN_bn2bin(p, key->p + 8 + (key->key_length/2) - plen); BN_bn2bin(dmp1, key->dp + 8 + (key->key_length/2) - dplen); BN_bn2bin(q, key->q + (key->key_length/2) - qlen); BN_bn2bin(dmq1, key->dq + (key->key_length/2) - dqlen); BN_bn2bin(iqmp, key->qInverse + 8 + (key->key_length/2) - qInvlen); BN_bn2bin(a, input + key->key_length - inputlen); /* execute the ica crt call */ rc = p_ica_rsa_crt(ibmca_handle, input, key, output); if (rc != 0) { IBMCAerr(IBMCA_F_IBMCA_MOD_EXP, IBMCA_R_REQUEST_FAILED); goto err; } else { rc = 1; } /* Convert output to BIGNUM representation */ /* BN_bin2bn((unsigned char *) (output + key->key_length - inputlen), inputlen, r); */ BN_bin2bn((unsigned char *) output, key->key_length, r); goto end; err: rc = 0; /* error condition */ end: free(key->p); free(key->q); free(key->dp); free(key->dq); free(key->qInverse); free(key); free(input); free(output); return rc; } #ifndef OPENSSL_NO_DSA /* This code was liberated and adapted from the commented-out code in * dsa_ossl.c. Because of the unoptimised form of the Ibmca acceleration * (it doesn't have a CRT form for RSA), this function means that an * Ibmca system running with a DSA server certificate can handshake * around 5 or 6 times faster/more than an equivalent system running with * RSA. Just check out the "signs" statistics from the RSA and DSA parts * of "openssl speed -engine ibmca dsa1024 rsa1024". */ #ifdef OLDER_OPENSSL static int ibmca_dsa_mod_exp(DSA * dsa, BIGNUM * rr, BIGNUM * a1, BIGNUM * p1, BIGNUM * a2, BIGNUM * p2, BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * in_mont) #else static int ibmca_dsa_mod_exp(DSA * dsa, BIGNUM * rr, const BIGNUM * a1, const BIGNUM * p1, const BIGNUM * a2, const BIGNUM * p2, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * in_mont) #endif { BIGNUM *t; int to_return = 0; t = BN_new(); /* let rr = a1 ^ p1 mod m */ if (!ibmca_mod_exp(rr, a1, p1, m, ctx)) goto end; /* let t = a2 ^ p2 mod m */ if (!ibmca_mod_exp(t, a2, p2, m, ctx)) goto end; /* let rr = rr * t mod m */ if (!BN_mod_mul(rr, rr, t, m, ctx)) goto end; to_return = 1; end: BN_free(t); return to_return; } #ifdef OLDER_OPENSSL static int ibmca_mod_exp_dsa(DSA * dsa, BIGNUM * r, BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx) #else static int ibmca_mod_exp_dsa(DSA * dsa, BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx) #endif { return ibmca_mod_exp(r, a, p, m, ctx); } #endif /* This function is aliased to mod_exp (with the mont stuff dropped). */ static int ibmca_mod_exp_mont(BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx) { return ibmca_mod_exp(r, a, p, m, ctx); } #ifndef OPENSSL_NO_DH /* This function is aliased to mod_exp (with the dh and mont dropped). */ static int ibmca_mod_exp_dh(DH const *dh, BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx) { return ibmca_mod_exp(r, a, p, m, ctx); } #endif /* Random bytes are good */ static int ibmca_rand_bytes(unsigned char *buf, int num) { unsigned int rc; rc = p_ica_random_number_generate(num, buf); if (rc < 0) { IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES, IBMCA_R_REQUEST_FAILED); return 0; } return 1; } static int ibmca_rand_status(void) { return 1; } /* This stuff is needed if this ENGINE is being compiled into a self-contained * shared-library. */ static int bind_fn(ENGINE * e, const char *id) { if (id && (strcmp(id, engine_ibmca_id) != 0)) /* WJH XXX */ return 0; if (!bind_helper(e)) return 0; return 1; } IMPLEMENT_DYNAMIC_CHECK_FN() IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) #endif /* !OPENSSL_NO_HW_IBMCA */ #endif /* !OPENSSL_NO_HW */ openssl-ibmca-1.4.1/src/e_ibmca_err.c000066400000000000000000000102631324360754100174420ustar00rootroot00000000000000/* * Copyright [2005-2017] International Business Machines Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /* NOTE: this file was auto generated by the mkerr.pl script: any changes * made to it will be overwritten when the script next updates this file, * only reason strings will be preserved. */ #include #include #include "e_ibmca_err.h" /* BEGIN ERROR CODES */ #ifndef OPENSSL_NO_ERR static ERR_STRING_DATA IBMCA_str_functs[] = { {ERR_PACK(0, IBMCA_F_IBMCA_CTRL, 0), "IBMCA_CTRL"}, {ERR_PACK(0, IBMCA_F_IBMCA_FINISH, 0), "IBMCA_FINISH"}, {ERR_PACK(0, IBMCA_F_IBMCA_INIT, 0), "IBMCA_INIT"}, {ERR_PACK(0, IBMCA_F_IBMCA_MOD_EXP, 0), "IBMCA_MOD_EXP"}, {ERR_PACK(0, IBMCA_F_IBMCA_MOD_EXP_CRT, 0), "IBMCA_MOD_EXP_CRT"}, {ERR_PACK(0, IBMCA_F_IBMCA_RAND_BYTES, 0), "IBMCA_RAND_BYTES"}, {ERR_PACK(0, IBMCA_F_IBMCA_RSA_MOD_EXP, 0), "IBMCA_RSA_MOD_EXP"}, {ERR_PACK(0, IBMCA_F_IBMCA_DES_CIPHER, 0), "IBMCA_DES_CIPHER"}, {ERR_PACK(0, IBMCA_F_IBMCA_TDES_CIPHER, 0), "IBMCA_TDES_CIPHER"}, {ERR_PACK(0, IBMCA_F_IBMCA_SHA1_UPDATE, 0), "IBMCA_SHA1_UPDATE"}, {ERR_PACK(0, IBMCA_F_IBMCA_SHA1_FINAL, 0), "IBMCA_SHA1_FINAL"}, {ERR_PACK(0, IBMCA_F_IBMCA_AES_128_CIPHER, 0), "IBMCA_AES_128_CIPHER"}, {ERR_PACK(0, IBMCA_F_IBMCA_AES_192_CIPHER, 0), "IBMCA_AES_192_CIPHER"}, {ERR_PACK(0, IBMCA_F_IBMCA_AES_256_CIPHER, 0), "IBMCA_AES_256_CIPHER"}, {ERR_PACK(0, IBMCA_F_IBMCA_SHA256_UPDATE, 0), "IBMCA_SHA256_UPDATE"}, {ERR_PACK(0, IBMCA_F_IBMCA_SHA256_FINAL, 0), "IBMCA_SHA256_FINAL"}, {ERR_PACK(0, IBMCA_F_IBMCA_SHA512_UPDATE, 0), "IBMCA_SHA512_UPDATE"}, {ERR_PACK(0, IBMCA_F_IBMCA_SHA512_FINAL, 0), "IBMCA_SHA512_FINAL"}, {0, NULL} }; static ERR_STRING_DATA IBMCA_str_reasons[] = { {IBMCA_R_ALREADY_LOADED, "already loaded"}, {IBMCA_R_BN_CTX_FULL, "bn ctx full"}, {IBMCA_R_BN_EXPAND_FAIL, "bn expand fail"}, {IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctrl command not implemented"}, {IBMCA_R_DSO_FAILURE, "dso failure"}, {IBMCA_R_MEXP_LENGTH_TO_LARGE, "mexp length to large"}, {IBMCA_R_MISSING_KEY_COMPONENTS, "missing key components"}, {IBMCA_R_NOT_INITIALISED, "not initialised"}, {IBMCA_R_NOT_LOADED, "not loaded"}, {IBMCA_R_OPERANDS_TO_LARGE, "operands to large"}, {IBMCA_R_OUTLEN_TO_LARGE, "outlen to large"}, {IBMCA_R_REQUEST_FAILED, "request failed"}, {IBMCA_R_UNDERFLOW_CONDITION, "underflow condition"}, {IBMCA_R_UNDERFLOW_KEYRECORD, "underflow keyrecord"}, {IBMCA_R_UNIT_FAILURE, "unit failure"}, {IBMCA_R_CIPHER_MODE_NOT_SUPPORTED, "cipher mode not supported"}, {0, NULL} }; #endif #ifdef IBMCA_LIB_NAME static ERR_STRING_DATA IBMCA_lib_name[] = { {0, IBMCA_LIB_NAME}, {0, NULL} }; #endif static int IBMCA_lib_error_code = 0; static int IBMCA_error_init = 1; void ERR_load_IBMCA_strings(void) { if (IBMCA_lib_error_code == 0) IBMCA_lib_error_code = ERR_get_next_error_library(); if (IBMCA_error_init) { IBMCA_error_init = 0; #ifndef OPENSSL_NO_ERR ERR_load_strings(IBMCA_lib_error_code, IBMCA_str_functs); ERR_load_strings(IBMCA_lib_error_code, IBMCA_str_reasons); #endif #ifdef IBMCA_LIB_NAME IBMCA_lib_name->error = ERR_PACK(IBMCA_lib_error_code, 0, 0); ERR_load_strings(0, IBMCA_lib_name); #endif } } void ERR_unload_IBMCA_strings(void) { if (IBMCA_error_init == 0) { #ifndef OPENSSL_NO_ERR ERR_unload_strings(IBMCA_lib_error_code, IBMCA_str_functs); ERR_unload_strings(IBMCA_lib_error_code, IBMCA_str_reasons); #endif #ifdef IBMCA_LIB_NAME ERR_unload_strings(0, IBMCA_lib_name); #endif IBMCA_error_init = 1; } } void ERR_IBMCA_error(int function, int reason, char *file, int line) { if (IBMCA_lib_error_code == 0) IBMCA_lib_error_code = ERR_get_next_error_library(); ERR_PUT_error(IBMCA_lib_error_code, function, reason, file, line); } openssl-ibmca-1.4.1/src/e_ibmca_err.h000066400000000000000000000047751324360754100174620ustar00rootroot00000000000000/* * Copyright [2005-2017] International Business Machines Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef HEADER_IBMCA_ERR_H #define HEADER_IBMCA_ERR_H /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. */ void ERR_load_IBMCA_strings(void); void ERR_unload_IBMCA_strings(void); void ERR_IBMCA_error(int function, int reason, char *file, int line); #define IBMCAerr(f,r) ERR_IBMCA_error((f),(r),__FILE__,__LINE__) /* Error codes for the IBMCA functions. */ /* Function codes. */ #define IBMCA_F_IBMCA_CTRL 100 #define IBMCA_F_IBMCA_FINISH 101 #define IBMCA_F_IBMCA_INIT 102 #define IBMCA_F_IBMCA_MOD_EXP 103 #define IBMCA_F_IBMCA_MOD_EXP_CRT 104 #define IBMCA_F_IBMCA_RAND_BYTES 105 #define IBMCA_F_IBMCA_RSA_MOD_EXP 106 #define IBMCA_F_IBMCA_DES_CIPHER 107 #define IBMCA_F_IBMCA_TDES_CIPHER 108 #define IBMCA_F_IBMCA_SHA1_UPDATE 109 #define IBMCA_F_IBMCA_SHA1_FINAL 110 #define IBMCA_F_IBMCA_AES_128_CIPHER 111 #define IBMCA_F_IBMCA_AES_192_CIPHER 112 #define IBMCA_F_IBMCA_AES_256_CIPHER 113 #define IBMCA_F_IBMCA_SHA256_UPDATE 114 #define IBMCA_F_IBMCA_SHA256_FINAL 115 #define IBMCA_F_IBMCA_SHA512_UPDATE 116 #define IBMCA_F_IBMCA_SHA512_FINAL 117 /* Reason codes. */ #define IBMCA_R_ALREADY_LOADED 100 #define IBMCA_R_BN_CTX_FULL 101 #define IBMCA_R_BN_EXPAND_FAIL 102 #define IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED 103 #define IBMCA_R_DSO_FAILURE 104 #define IBMCA_R_MEXP_LENGTH_TO_LARGE 110 #define IBMCA_R_MISSING_KEY_COMPONENTS 105 #define IBMCA_R_NOT_INITIALISED 106 #define IBMCA_R_NOT_LOADED 107 #define IBMCA_R_OPERANDS_TO_LARGE 111 #define IBMCA_R_OUTLEN_TO_LARGE 112 #define IBMCA_R_REQUEST_FAILED 108 #define IBMCA_R_UNDERFLOW_CONDITION 113 #define IBMCA_R_UNDERFLOW_KEYRECORD 114 #define IBMCA_R_UNIT_FAILURE 109 #define IBMCA_R_CIPHER_MODE_NOT_SUPPORTED 115 #endif openssl-ibmca-1.4.1/src/openssl.cnf.sample000066400000000000000000000027111324360754100205010ustar00rootroot00000000000000# # OpenSSL example configuration file. This file will load the IBMCA engine # for all operations that the IBMCA engine implements for all apps that # have OpenSSL config support compiled into them. # # Adding OpenSSL config support is as simple as adding the following line to # the app: # # #define OPENSSL_LOAD_CONF 1 # openssl_conf = openssl_def [openssl_def] engines = engine_section [engine_section] ibmca = ibmca_section [ibmca_section] # The openssl engine path for ibmca.so. # Set the dynamic_path to where the ibmca.so engine # resides on the system. dynamic_path = /usr/local/lib/ibmca.so engine_id = ibmca init = 1 # # The following ibmca algorithms will be enabled by these parameters # to the default_algorithms line. Any combination of these is valid, # with "ALL" denoting the same as all of them in a comma separated # list. # # RSA # - RSA encrypt, decrypt, sign and verify, key lengths 512-4096 # # DH # - DH key exchange # # DSA # - DSA sign and verify # # RAND # - Hardware random number generation # # CIPHERS # - DES-ECB, DES-CBC, DES-CFB, DES-OFB, # DES-EDE3, DES-EDE3-CBC, DES-EDE3-CFB, DES-EDE3-OFB, # AES-128-ECB, AES-128-CBC, AES-128-CFB, AES-128-OFB, id-aes128-GCM, # AES-192-ECB, AES-192-CBC, AES-192-CFB, AES-192-OFB, id-aes192-GCM, # AES-256-ECB, AES-256-CBC, AES-256-CFB, AES-256-OFB, id-aes256-GCM ciphers # # DIGESTS # - SHA1, SHA256, SHA512 digests # default_algorithms = ALL #default_algorithms = RAND,RSA,DH,DSA,CIPHERS,DIGESTS openssl-ibmca-1.4.1/src/test/000077500000000000000000000000001324360754100160245ustar00rootroot00000000000000openssl-ibmca-1.4.1/src/test/Makefile.linux000066400000000000000000000004701324360754100206230ustar00rootroot00000000000000PTS = -O0 -g -Wall -fprofile-arcs -ftest-coverage -fPIC #OPTS = -O0 -g -Wall -m31 -D_LINUX_S390_ OPTS = -O0 -g -Wall -D_LINUX_S390_ -std=gnu99 TARGETS = ibmca_mechaList_test all: $(TARGETS) # Every target is created from a single .c file. %: %.c gcc $(OPTS) -lica -lcrypto -o $@ $^ clean: rm -f $(TARGETS) openssl-ibmca-1.4.1/src/test/ibmca_mechaList_test.c000066400000000000000000000266341324360754100223060ustar00rootroot00000000000000/* * Copyright [2015-2017] International Business Machines Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include #include #include #include #define CIPH 1 #define DIG 2 #define SET 1 #define UNSET 0 typedef struct{ int nid; int ica_id; int dig_ciph; } id_map; #define AP_PATH "/sys/devices/ap" #define IBMCA_PATH "/usr/lib64/openssl/engines/ibmca.so" id_map ica_to_ssl_map[] = { #ifndef OPENSSL_NO_SHA1 {NID_sha1, SHA1, DIG}, #endif #ifndef OPENSSL_NO_SHA256 {NID_sha256, SHA256, DIG}, #endif #ifndef OPENSSL_NO_SHA512 {NID_sha512, SHA512, DIG}, #endif {NID_des_ecb, DES_ECB, CIPH}, {NID_des_cbc, DES_CBC, CIPH}, {NID_des_ofb64, DES_OFB, CIPH}, {NID_des_cfb64, DES_CFB, CIPH}, {NID_des_ede3_ecb, DES3_ECB, CIPH}, {NID_des_ede3_cbc, DES3_CBC, CIPH}, {NID_des_ede3_ofb64, DES3_OFB, CIPH}, {NID_des_ede3_cfb64, DES3_CFB, CIPH}, {NID_aes_128_ecb, AES_ECB, CIPH}, {NID_aes_192_ecb, AES_ECB, CIPH}, {NID_aes_256_ecb, AES_ECB, CIPH}, {NID_aes_128_cbc, AES_CBC, CIPH}, {NID_aes_192_cbc, AES_CBC, CIPH}, {NID_aes_256_cbc, AES_CBC, CIPH}, {NID_aes_128_ofb128, AES_OFB, CIPH}, {NID_aes_192_ofb128, AES_OFB, CIPH}, {NID_aes_256_ofb128, AES_OFB, CIPH}, {NID_aes_128_cfb128, AES_CFB, CIPH}, {NID_aes_192_cfb128, AES_CFB, CIPH}, {NID_aes_256_cfb128, AES_CFB, CIPH}, {0, 0, 0} }; ENGINE *eng; int failure = 0; int init_engine(char *id) { ENGINE_load_builtin_engines(); eng = ENGINE_by_id("dynamic"); if(!eng){ return 1; return 1; } if(!ENGINE_ctrl_cmd_string(eng, "SO_PATH", id, 0)){ return 1; } if (!ENGINE_ctrl_cmd_string(eng, "LOAD", NULL, 0)){ return 1; } if (!ENGINE_init(eng)){ return 1; } if(!ENGINE_set_default_RSA(eng)) return 1; ENGINE_set_default_DSA(eng); ENGINE_set_default_RAND(eng); ENGINE_set_default_DH(eng); ENGINE_set_default_ciphers(eng); ENGINE_set_default_digests(eng); return 0; } void exit_engine() { /* Release the functional reference from ENGINE_init() */ ENGINE_finish(eng); /* Release the structural reference from ENGINE_by_id() */ ENGINE_free(eng); } void nid_failure(int nid, int set) { failure++; if(set == SET){ fprintf(stderr, "ERROR: NID %d not set in Engine!\n", nid); } else if(set == UNSET) fprintf(stderr, "ERROR: NID %d set despite missing hardware support!", nid); } int is_crypto_card_loaded() { DIR* sysDir; FILE *file; char dev[PATH_MAX] = AP_PATH; struct dirent *direntp; char *type = NULL; size_t size; char c; if ((sysDir = opendir(dev)) == NULL ) return 0; while((direntp = readdir(sysDir)) != NULL){ if(strstr(direntp->d_name, "card") != 0){ snprintf(dev, PATH_MAX, "%s/%s/type", AP_PATH, direntp->d_name); if ((file = fopen(dev, "r")) == NULL){ closedir(sysDir); return 0; } if (getline(&type, &size, file) == -1){ fclose(file); closedir(sysDir); return 0; } /* ignore \n * looking for CEX??A and CEX??C * Skip type CEX??P cards */ if (type[strlen(type)-2] == 'P'){ free(type); type = NULL; fclose(file); continue; } free(type); type = NULL; fclose(file); snprintf(dev, PATH_MAX, "%s/%s/online", AP_PATH, direntp->d_name); if ((file = fopen(dev, "r")) == NULL){ closedir(sysDir); return 0; } if((c = fgetc(file)) == '1'){ fclose(file); return 1; } fclose(file); } } closedir(sysDir); return 0; } void check_mech(int i, int j, libica_func_list_element *pmech_list) { if(!(pmech_list[j].flags & (ICA_FLAG_SHW))){ if(ica_to_ssl_map[i].dig_ciph == CIPH){ if(ENGINE_get_cipher_engine(ica_to_ssl_map[i].nid)){ nid_failure(ica_to_ssl_map[i].nid, UNSET); } else{ printf("NID %d not found! SUCCESS\n", ica_to_ssl_map[i].nid); } } else{ if(ENGINE_get_digest_engine(ica_to_ssl_map[i].nid)){ nid_failure(ica_to_ssl_map[i].nid, UNSET); } else{ printf("NID %d not found! SUCCESS\n", ica_to_ssl_map[i].nid); } } } else{ if(ica_to_ssl_map[i].dig_ciph == CIPH){ if(!ENGINE_get_cipher_engine(ica_to_ssl_map[i].nid)){ nid_failure(ica_to_ssl_map[i].nid, SET); } else{ printf("NID %d found! SUCCESS %d\n", ica_to_ssl_map[i].nid, j); } } else{ if(!ENGINE_get_digest_engine(ica_to_ssl_map[i].nid)){ nid_failure(ica_to_ssl_map[i].nid, SET); } else{ printf("NID %d found! SUCCESS %d\n", ica_to_ssl_map[i].nid, j); } } } } int main (int argc, char *argv[]) { int i, j, opt, option_index = 0; int card_loaded; unsigned int mech_len; bool found = false; libica_func_list_element *pmech_list = NULL; char *engine_id = IBMCA_PATH; struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"file", required_argument, 0, 'f'}, {0 ,0 ,0, 0} }; while ((opt = getopt_long(argc, argv, "hf:", long_options, &option_index)) != -1) { switch (opt) { case 'f': engine_id = optarg; break; case 'h': printf("This test checks with the engine API of libcrypto if a\n" "crypto mechanism is enabled or not.\n" "If one mechanism is not found the NID is returned.\n" "The NID can be mapped to a name in the file \n" "/usr/include/openssl/obj_mac.h\n"); printf("Usage: %s [-f | --file ibmca.so] [-h | --help]\n", argv[0]); exit(EXIT_SUCCESS); default: /* '?' */ fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n", argv[0]); exit(EXIT_FAILURE); } } printf("This test checks with the engine API of libcrypto if a\n" "crypto mechanism is enabled or not.\n" "If one mechanism is not found the NID is returned.\n" "The NID can be mapped to a name in the file \n" "/usr/include/openssl/obj_mac.h\n"); printf("IBMCA path: %s\n", engine_id); printf("--------------------------------------------------------------\n\n"); if(init_engine(engine_id)){ fprintf(stderr, "Could not initialize Ibmca engine\n"); return EXIT_FAILURE; } if (ica_get_functionlist(NULL, &mech_len) != 0){ perror("get_functionlist"); return EXIT_FAILURE; } pmech_list = malloc(sizeof(libica_func_list_element)*mech_len); if (ica_get_functionlist(pmech_list, &mech_len) != 0){ perror("get_functionlist"); free(pmech_list); return EXIT_FAILURE; } card_loaded = is_crypto_card_loaded(); for(i=0;ica_to_ssl_map[i].nid;i++){ for(j=0;j