pax_global_header00006660000000000000000000000064135353136710014521gustar00rootroot0000000000000052 comment=77b04cebd7bc61ae8abbeeac5ad7987436de0712 openssl-ibmca-2.1.0/000077500000000000000000000000001353531367100142555ustar00rootroot00000000000000openssl-ibmca-2.1.0/.gitignore000066400000000000000000000002121353531367100162400ustar00rootroot00000000000000build-aux autom4te.cache .deps .libs *.m4 *.lo *.la *.o *.tar.gz Makefile Makefile.in config.status config.log configure libtool cscope.* openssl-ibmca-2.1.0/AUTHORS000066400000000000000000000000441353531367100153230ustar00rootroot00000000000000Mike Halcrow openssl-ibmca-2.1.0/CONTRIBUTING.md000066400000000000000000000052271353531367100165140ustar00rootroot00000000000000# 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-2.1.0/ChangeLog000066400000000000000000000037441353531367100160370ustar00rootroot00000000000000* openssl-ibmca 2.1.0 - Add MSA9 CPACF support for X25519, X448, Ed25519 and Ed448 * openssl-ibmca 2.0.3 - Add MSA9 CPACF support for ECDSA sign/verify * openssl-ibmca 2.0.2 - Fix doing rsa-me, altough rsa-crt would be possible. * openssl-ibmca 2.0.1 - Dont fail when a libica symbol cannot be resolved. * openssl-ibmca 2.0.0 - Add ECC support. - Add check and distcheck make-targets. - Project cleanup, code was broken into multiple files and coding style cleanup. - Improvements to compat macros for openssl. - Don't disable libica sw fallbacks. - Fix dlclose logic. * 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-2.1.0/LICENSE000066400000000000000000000220311353531367100152600ustar00rootroot00000000000000Apache 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-2.1.0/Makefile.am000066400000000000000000000001441353531367100163100ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src test EXTRA_DIST = openssl-ibmca.spec bootstrap.sh cleanup.sh openssl-ibmca-2.1.0/README.md000066400000000000000000000042241353531367100155360ustar00rootroot00000000000000# 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.3.0 * autoconf * automake * libtool The runtime requirements are: * openssl >= 0.9.8 * libica >= 3.3.0 ## 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 Apps with compiled-in OpenSSL config support can enable the engine via an OpenSSL configuration file. Refer to config(5). A sample OpenSSL configuration file (`openssl.cnf.sample`) is included in this package. If the engine is configured properly, 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-2.1.0/bootstrap.sh000077500000000000000000000011761353531367100166360ustar00rootroot00000000000000#!/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-2.1.0/cleanup.sh000077500000000000000000000016021353531367100162420ustar00rootroot00000000000000#!/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-2.1.0/configure.ac000066400000000000000000000035051353531367100165460ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # See autoconf and autoscan online documentation for details. AC_INIT([openssl-ibmca], [2.1.0], [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 >= 3.3.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 >= 3.3.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 >= 3.3.0 and libica-devel >= 3.3.0 are required ***]), [#include ]) AC_CONFIG_FILES([ Makefile src/Makefile test/Makefile src/doc/Makefile]) AC_OUTPUT echo "CFLAGS=$CFLAGS" openssl-ibmca-2.1.0/docs/000077500000000000000000000000001353531367100152055ustar00rootroot00000000000000openssl-ibmca-2.1.0/docs/coding_style.md000066400000000000000000000074201353531367100202150ustar00rootroot00000000000000# 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-2.1.0/ibmca.map000066400000000000000000000001651353531367100160310ustar00rootroot00000000000000IBMCA_2.0.0 { global: v_check; bind_engine; ENGINE_load_ibmca; local: *; }; openssl-ibmca-2.1.0/m4/000077500000000000000000000000001353531367100145755ustar00rootroot00000000000000openssl-ibmca-2.1.0/m4/.dont_remove000066400000000000000000000002221353531367100171130ustar00rootroot00000000000000REQUIRED 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-2.1.0/openssl-ibmca.spec000066400000000000000000000047571353531367100177020ustar00rootroot00000000000000%global enginesdir %(pkg-config --variable=enginesdir libcrypto) Name: openssl-ibmca Version: 2.1.0 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.3.0 BuildRequires: openssl-devel >= 0.9.8 libica-devel >= 3.3.0 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 * Mon Sep 09 2019 Patrick Steuer 2.1.0 - Update Version * Tue Apr 23 2019 Patrick Steuer 2.0.3 - Update Version * Tue Nov 27 2018 Patrick Steuer 2.0.2 - Update Version * Thu Nov 08 2018 Patrick Steuer 2.0.1 - Update Version * Wed Jun 06 2018 Eduardo Barretto 2.0.0 - Update Version - Update libica version required for building ibmca * 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-2.1.0/src/000077500000000000000000000000001353531367100150445ustar00rootroot00000000000000openssl-ibmca-2.1.0/src/Makefile.am000066400000000000000000000007721353531367100171060ustar00rootroot00000000000000VERSION = 2:1:0 lib_LTLIBRARIES=ibmca.la ibmca_la_SOURCES=e_ibmca.c \ e_ibmca_err.c \ ibmca_cipher.c \ ibmca_digest.c \ ibmca_rsa.c \ ibmca_dsa.c \ ibmca_dh.c \ ibmca_ec.c \ ibmca_pkey.c ibmca_la_LIBADD=-ldl ibmca_la_LDFLAGS=-module -version-number ${VERSION} -shared -no-undefined \ -avoid-version -Wl,--version-script=${srcdir}/../ibmca.map dist_ibmca_la_SOURCES=ibmca.h e_ibmca_err.h EXTRA_DIST = openssl.cnf.sample ACLOCAL_AMFLAGS = -I m4 SUBDIRS = doc openssl-ibmca-2.1.0/src/doc/000077500000000000000000000000001353531367100156115ustar00rootroot00000000000000openssl-ibmca-2.1.0/src/doc/Makefile.am000066400000000000000000000000641353531367100176450ustar00rootroot00000000000000man5_MANS = ibmca.man dist_man5_MANS = $(man5_MANS) openssl-ibmca-2.1.0/src/doc/ibmca.man000066400000000000000000000035511353531367100173650ustar00rootroot00000000000000.\" 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-2.1.0/src/e_ibmca.c000066400000000000000000000702361353531367100165770ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 #include #include "ibmca.h" #include "e_ibmca_err.h" #ifndef OPENSSL_NO_HW #ifndef OPENSSL_NO_HW_IBMCA #define IBMCA_LIB_NAME "ibmca engine" #define LIBICA_SHARED_LIB "libica.so.3" #define AP_PATH "/sys/devices/ap" /* * It would be good to disable libica's software-fallbacks for they may * eventually lead to infinite looping (libcrypto->ibmca->libica->libcrypto). * However, right now we cannot disable the fallbacks because they are still * needed for rsa > 4k. */ #define DISABLE_SW_FALLBACKS 0 static const char *LIBICA_NAME = "ica"; /* Constants used when creating the ENGINE */ static const char *engine_ibmca_id = "ibmca"; static const char *engine_ibmca_name = "Ibmca hardware engine support"; /* 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; ica_adapter_handle_t ibmca_handle = DRIVER_NOT_LOADED; /* entry points into libica, filled out at DSO load time */ ica_get_functionlist_t p_ica_get_functionlist; 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_sha256_t p_ica_sha256; ica_sha512_t p_ica_sha512; ica_des_ecb_t p_ica_des_ecb; ica_des_cbc_t p_ica_des_cbc; ica_des_ofb_t p_ica_des_ofb; ica_des_cfb_t p_ica_des_cfb; ica_3des_ecb_t p_ica_3des_ecb; ica_3des_cbc_t p_ica_3des_cbc; ica_3des_cfb_t p_ica_3des_cfb; ica_3des_ofb_t p_ica_3des_ofb; ica_aes_ecb_t p_ica_aes_ecb; ica_aes_cbc_t p_ica_aes_cbc; 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 /* save libcrypto's default ec methods */ #ifndef NO_EC #ifdef OLDER_OPENSSL const ECDSA_METHOD *ossl_ecdsa; const ECDH_METHOD *ossl_ecdh; #else const EC_KEY_METHOD *ossl_ec; #endif #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, EC_KGEN, EC_DSA_SIGN, EC_DSA_VERIFY, EC_DH, ED25519_KEYGEN, ED25519_SIGN, ED25519_VERIFY, ED448_KEYGEN, ED448_SIGN, ED448_VERIFY, X25519_KEYGEN, X25519_DERIVE, X448_KEYGEN, X448_DERIVE, 0 }; #define MAX_CIPHER_NIDS sizeof(ibmca_crypto_algos) /* * This struct maps one NID to one crypto algo. * So we can tell OpenSSL this 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 size_t size_pkey_meths_list = 0; static struct crypto_pair ibmca_cipher_lists; static struct crypto_pair ibmca_digest_lists; static struct crypto_pair ibmca_pkey_meths_lists; 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_usable_digests(const int **nids); static int ibmca_engine_digests(ENGINE * e, const EVP_MD ** digest, const int **nids, int nid); static int ibmca_engine_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, const int **nids, int nid); static int ibmca_usable_pkey_meths(const int **nids); /* RAND stuff */ static int ibmca_rand_bytes(unsigned char *buf, int num); static int ibmca_rand_status(void); 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 */ }; /* 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 'ibmca' shared library", ENGINE_CMD_FLAG_STRING}, {0, NULL, NULL, 0} }; /* 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 #ifndef OPENSSL_NO_SHA1 ibmca_sha1_destroy(); #endif #ifndef OPENSSL_NO_SHA256 ibmca_sha256_destroy(); #endif #ifndef OPENSSL_NO_SHA512 ibmca_sha512_destroy(); #endif #ifndef OPENSSL_NO_RSA ibmca_rsa_destroy(); #endif #ifndef OPENSSL_NO_DSA ibmca_dsa_destroy(); #endif #ifndef OPENSSL_NO_DH ibmca_dh_destroy(); #endif #endif /* !OLDER_OPENSSL */ #ifndef NO_EC ibmca_ec_destroy(); #endif ERR_unload_IBMCA_strings(); return 1; } inline static int set_RSA_prop(ENGINE *e) { static int rsa_enabled = 0; if (rsa_enabled) { return 1; } if ( #ifndef OPENSSL_NO_RSA !ENGINE_set_RSA(e, ibmca_rsa()) || #endif #ifndef OPENSSL_NO_DSA !ENGINE_set_DSA(e, ibmca_dsa()) || #endif #ifndef OPENSSL_NO_DH !ENGINE_set_DH(e, ibmca_dh()) #endif ) return 0; rsa_enabled = 1; return 1; } #ifndef OPENSSL_NO_EC static int set_EC_prop(ENGINE *e) { static int ec_enabled = 0; if (ec_enabled) { return 1; } #ifdef OLDER_OPENSSL ossl_ecdh = ECDH_get_default_method(); ossl_ecdsa = ECDSA_get_default_method(); ibmca_ecdh = ECDH_METHOD_new(NULL); ibmca_ecdsa = ECDSA_METHOD_new(NULL); ECDSA_METHOD_set_name(ibmca_ecdsa, "Ibmca ECDSA method"); ECDSA_METHOD_set_sign(ibmca_ecdsa, ibmca_older_ecdsa_do_sign); ECDSA_METHOD_set_verify(ibmca_ecdsa, ibmca_older_ecdsa_do_verify); #ifdef ECDSA_FLAG_FIPS_METHOD ECDSA_METHOD_set_flags(ibmca_ecdsa, ECDSA_FLAG_FIPS_METHOD); #endif ECDH_METHOD_set_name(ibmca_ecdh, "Ibmca ECDH method"); ECDH_METHOD_set_compute_key(ibmca_ecdh, ibmca_older_ecdh_compute_key); #ifdef ECDH_FLAG_FIPS_METHOD ECDH_METHOD_set_flags(ibmca_ecdh, ECDH_FLAG_FIPS_METHOD); #endif if (!ENGINE_set_ECDH(e, ibmca_ecdh)) return 0; if (!ENGINE_set_ECDSA(e, ibmca_ecdsa)) return 0; #else ossl_ec = EC_KEY_get_default_method(); ibmca_ec = EC_KEY_METHOD_new(ibmca_ec); EC_KEY_METHOD_set_keygen(ibmca_ec, ibmca_ec_key_gen); EC_KEY_METHOD_set_compute_key(ibmca_ec, ibmca_ecdh_compute_key); EC_KEY_METHOD_set_sign(ibmca_ec, ibmca_ecdsa_sign, ECDSA_sign_setup, ibmca_ecdsa_sign_sig); EC_KEY_METHOD_set_verify(ibmca_ec, ibmca_ecdsa_verify, ibmca_ecdsa_verify_sig); if (!ENGINE_set_EC(e, ibmca_ec)) return 0; #endif ec_enabled = 1; return 1; } #endif /* * 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, int *pkey_nid_cnt) { static int ec_kgen_switch, ec_dh_switch, ec_dsa_sign_switch, ec_dsa_verify_switch, x25519_keygen_switch, x25519_derive_switch, x448_keygen_switch, x448_derive_switch, ed25519_keygen_switch, ed25519_sign_switch, ed25519_verify_switch, ed448_keygen_switch, ed448_sign_switch, ed448_verify_switch, x25519_switch, x448_switch, ed25519_switch, ed448_switch; 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; ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++] = ibmca_sha1(); break; #endif #ifndef OPENSSL_NO_SHA256 case SHA256: ibmca_digest_lists.nids[*dig_nid_cnt] = NID_sha256; ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++] = ibmca_sha256(); break; #endif #ifndef OPENSSL_NO_SHA512 case SHA512: ibmca_digest_lists.nids[*dig_nid_cnt] = NID_sha512; ibmca_digest_lists.crypto_meths[(*dig_nid_cnt)++] = ibmca_sha512(); break; #endif case DES_ECB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ecb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_des_ecb(); break; case DES_CBC: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_cbc; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_des_cbc(); break; case DES_OFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ofb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_des_ofb(); break; case DES_CFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_cfb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_des_cfb(); break; case DES3_ECB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ede3_ecb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_tdes_ecb(); break; case DES3_CBC: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ede3_cbc; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_tdes_cbc(); break; case DES3_OFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ede3_ofb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_tdes_ofb(); break; case DES3_CFB: ibmca_cipher_lists.nids[*ciph_nid_cnt] = NID_des_ede3_cfb; ibmca_cipher_lists.crypto_meths[(*ciph_nid_cnt)++] = ibmca_tdes_cfb(); 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 #ifndef OPENSSL_NO_EC case EC_KGEN: ec_kgen_switch = 1; break; case EC_DH: ec_dh_switch = 1; break; case EC_DSA_SIGN: ec_dsa_sign_switch = 1; break; case EC_DSA_VERIFY: ec_dsa_verify_switch = 1; break; #endif case ED25519_KEYGEN: ed25519_keygen_switch = 1; break; case ED25519_SIGN: ed25519_sign_switch = 1; break; case ED25519_VERIFY: ed25519_verify_switch = 1; break; case ED448_KEYGEN: ed448_keygen_switch = 1; break; case ED448_SIGN: ed448_sign_switch = 1; break; case ED448_VERIFY: ed448_verify_switch = 1; break; case X25519_KEYGEN: x25519_keygen_switch = 1; break; case X25519_DERIVE: x25519_derive_switch = 1; break; case X448_KEYGEN: x448_keygen_switch = 1; break; case X448_DERIVE: x448_derive_switch = 1; break; default: break; /* do nothing */ } #ifndef OPENSSL_NO_EC if (ec_kgen_switch && ec_dh_switch && ec_dsa_sign_switch && ec_dsa_verify_switch) { if (!set_EC_prop(e)) return 0; } #endif if (x25519_keygen_switch && x25519_derive_switch && !x25519_switch) { x25519_switch = 1; ibmca_pkey_meths_lists.nids[*pkey_nid_cnt] = NID_X25519; ibmca_pkey_meths_lists.crypto_meths[(*pkey_nid_cnt)++] = ibmca_x25519(); } if (x448_keygen_switch && x448_derive_switch && !x448_switch) { x448_switch = 1; ibmca_pkey_meths_lists.nids[*pkey_nid_cnt] = NID_X448; ibmca_pkey_meths_lists.crypto_meths[(*pkey_nid_cnt)++] = ibmca_x448(); } if (ed25519_keygen_switch && ed25519_sign_switch && ed25519_verify_switch && !ed25519_switch) { ed25519_switch = 1; ibmca_pkey_meths_lists.nids[*pkey_nid_cnt] = NID_ED25519; ibmca_pkey_meths_lists.crypto_meths[(*pkey_nid_cnt)++] = ibmca_ed25519(); } if (ed448_keygen_switch && ed448_sign_switch && ed448_verify_switch && !ed448_switch) { ed448_switch = 1; ibmca_pkey_meths_lists.nids[*pkey_nid_cnt] = NID_ED448; ibmca_pkey_meths_lists.crypto_meths[(*pkey_nid_cnt)++] = ibmca_ed448(); } size_cipher_list = *ciph_nid_cnt; size_digest_list = *dig_nid_cnt; size_pkey_meths_list = *pkey_nid_cnt; return 1; } 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 pkey_nid_cnt = 0; 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; 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; /* 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, &pkey_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; if (pkey_nid_cnt > 0) if (!ENGINE_set_pkey_meths(e, ibmca_engine_pkey_meths)) goto out; rc = 1; out: free(pmech_list); return rc; } __attribute__((constructor)) static void ibmca_constructor(void) { static int init = 0; DEBUG_PRINTF(">%s\n", __func__); if (init) return; 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; } #define BIND(dso, sym) (p_##sym = (sym##_t)dlsym(dso, #sym)) if (!BIND(ibmca_dso, ica_open_adapter) || !BIND(ibmca_dso, ica_close_adapter) || !BIND(ibmca_dso, ica_get_functionlist)) { IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_DSO_FAILURE); DEBUG_PRINTF("%s: function bind failed\n", __func__); goto err; } BIND(ibmca_dso, ica_rsa_mod_expo); BIND(ibmca_dso, ica_rsa_crt); BIND(ibmca_dso, ica_random_number_generate); BIND(ibmca_dso, ica_sha1); BIND(ibmca_dso, ica_sha256); BIND(ibmca_dso, ica_sha512); BIND(ibmca_dso, ica_aes_ecb); BIND(ibmca_dso, ica_des_ecb); BIND(ibmca_dso, ica_3des_ecb); BIND(ibmca_dso, ica_aes_cbc); BIND(ibmca_dso, ica_des_cbc); BIND(ibmca_dso, ica_3des_cbc); 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_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 #ifndef OPENSSL_NO_EC BIND(ibmca_dso, ica_ec_key_new); BIND(ibmca_dso, ica_ec_key_init); BIND(ibmca_dso, ica_ec_key_generate); BIND(ibmca_dso, ica_ecdh_derive_secret); BIND(ibmca_dso, ica_ecdsa_sign); BIND(ibmca_dso, ica_ecdsa_verify); BIND(ibmca_dso, ica_ec_key_get_public_key); BIND(ibmca_dso, ica_ec_key_get_private_key); BIND(ibmca_dso, ica_ec_key_free); #endif #if DISABLE_SW_FALLBACKS /* disable fallbacks on Libica */ if (BIND(ibmca_dso, ica_set_fallback_mode)) p_ica_set_fallback_mode(0); #endif if (p_ica_open_adapter(&ibmca_handle)) { IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_UNIT_FAILURE); goto err; } DEBUG_PRINTF("<%s success\n", __func__); return; err: DEBUG_PRINTF("<%s failure\n", __func__); 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_rsa_crt = NULL; #ifndef OPENSSL_NO_EC p_ica_ec_key_new = NULL; p_ica_ec_key_init = NULL; p_ica_ec_key_generate = NULL; p_ica_ecdh_derive_secret = NULL; p_ica_ecdsa_sign = NULL; p_ica_ecdsa_verify = NULL; p_ica_ec_key_get_public_key = NULL; p_ica_ec_key_get_private_key = NULL; p_ica_ec_key_free = NULL; #endif p_ica_random_number_generate = NULL; p_ica_sha1 = NULL; p_ica_sha256 = NULL; p_ica_sha512 = NULL; p_ica_aes_ecb = NULL; p_ica_des_ecb = NULL; p_ica_3des_ecb = NULL; p_ica_aes_cbc = NULL; p_ica_des_cbc = NULL; p_ica_3des_cbc = 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 } __attribute__((destructor)) static void ibmca_destructor(void) { if (ibmca_dso == NULL) { IBMCAerr(IBMCA_F_IBMCA_FINISH, IBMCA_R_NOT_LOADED); return; } if (dlclose(ibmca_dso)) { IBMCAerr(IBMCA_F_IBMCA_FINISH, IBMCA_R_DSO_FAILURE); return; } p_ica_close_adapter(ibmca_handle); } static int ibmca_init(ENGINE *e) { if (ibmca_dso == NULL) return 0; return 1; } static int ibmca_finish(ENGINE *e) { 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; } /* * This internal function is used by ENGINE_ibmca() * and possibly by the "dynamic" ENGINE support too */ static int bind_helper(ENGINE *e) { ERR_load_IBMCA_strings(); 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; if (ibmca_dso == NULL) return 0; if (!set_supported_meths(e)) return 0; 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(); } /* * 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_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; } static int ibmca_engine_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, const int **nids, int nid) { int i; if (!pmeth) return (ibmca_usable_pkey_meths(nids)); *pmeth = NULL; for (i = 0; i < size_pkey_meths_list; i++) { if (nid == ibmca_pkey_meths_lists.nids[i]) { *pmeth = (EVP_PKEY_METHOD *)ibmca_pkey_meths_lists.crypto_meths[i]; break; } } return (*pmeth != NULL); } static int ibmca_usable_pkey_meths(const int **nids) { if (nids) *nids = ibmca_pkey_meths_lists.nids; return size_pkey_meths_list; } /* 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)) { fprintf(stderr, "wrong engine id\n"); return 0; } if (!bind_helper(e)) { fprintf(stderr, "bind failed\n"); 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-2.1.0/src/e_ibmca_err.c000066400000000000000000000135341353531367100174450ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 "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"}, {ERR_PACK(0, IBMCA_F_IBMCA_EC_KEY_GEN, 0), "IBMCA_EC_KEY_GEN"}, {ERR_PACK(0, IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, 0), "IBMCA_ECDH_COMPUTE_KEY"}, {ERR_PACK(0, IBMCA_F_IBMCA_ECDSA_SIGN, 0), "IBMCA_ECDSA_SIGN"}, {ERR_PACK(0, IBMCA_F_IBMCA_ECDSA_SIGN_SIG, 0), "IBMCA_ECDSA_SIGN_SIG"}, {ERR_PACK(0, IBMCA_F_IBMCA_ECDSA_DO_SIGN, 0), "IBMCA_ECDSA_DO_SIGN"}, {ERR_PACK(0, IBMCA_F_IBMCA_ECDSA_VERIFY, 0), "IBMCA_ECDSA_VERIFY"}, {ERR_PACK(0, IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, 0), "IBMCA_ECDSA_VERIFY_SIG"}, {ERR_PACK(0, IBMCA_F_ICA_EC_KEY_NEW, 0), "ICA_EC_KEY_NEW"}, {ERR_PACK(0, IBMCA_F_ICA_EC_KEY_INIT, 0), "ICA_EC_KEY_INIT"}, {ERR_PACK(0, IBMCA_F_ICA_EC_KEY_GENERATE, 0), "ICA_EC_KEY_GENERATE"}, {ERR_PACK(0, IBMCA_F_ICA_EC_KEY_GET_PUBLIC_KEY, 0), "ICA_EC_KEY_GET_PUBLIC_KEY"}, {ERR_PACK(0, IBMCA_F_ICA_EC_KEY_GET_PRIVATE_KEY, 0), "ICA_EC_KEY_GET_PRIVATE_KEY"}, {ERR_PACK(0, IBMCA_F_ICA_ECDH_DERIVE_SECRET, 0), "ICA_ECDH_DERIVE_SECRET"}, {ERR_PACK(0, IBMCA_F_ICA_ECDSA_SIGN, 0), "ICA_ECDSA_SIGN"}, {ERR_PACK(0, IBMCA_F_ICA_ECDSA_VERIFY, 0), "ICA_ECDSA_VERIFY"}, {ERR_PACK(0, IBMCA_F_ICA_ECDSA_VERIFY, 0), "IBMCA_X25519_KEYGEN"}, {ERR_PACK(0, IBMCA_F_ICA_ECDSA_VERIFY, 0), "IBMCA_X25519_DERIVE"}, {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"}, {IBMCA_R_EC_INVALID_PARM, "ec invalid parameter"}, {IBMCA_R_EC_UNSUPPORTED_CURVE, "ec unsupported curve"}, {IBMCA_R_EC_INTERNAL_ERROR, "ec internal error"}, {IBMCA_R_EC_ICA_EC_KEY_INIT, "ec ica ec key init"}, {IBMCA_R_EC_CURVE_DOES_NOT_SUPPORT_SIGNING, "ec curve does not support signing"}, {IBMCA_R_PKEY_INTERNAL_ERROR, "internal error"}, {IBMCA_R_PKEY_KEYGEN_FAILED, "keygen failed"}, {IBMCA_R_PKEY_KEYS_NOT_SET, "keys not set"}, {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-2.1.0/src/e_ibmca_err.h000066400000000000000000000075751353531367100174620ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 */ 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 #define IBMCA_F_IBMCA_EC_KEY_GEN 120 #define IBMCA_F_IBMCA_ECDH_COMPUTE_KEY 121 #define IBMCA_F_IBMCA_ECDSA_SIGN 122 #define IBMCA_F_IBMCA_ECDSA_SIGN_SIG 123 #define IBMCA_F_IBMCA_ECDSA_DO_SIGN 124 #define IBMCA_F_IBMCA_ECDSA_VERIFY 125 #define IBMCA_F_IBMCA_ECDSA_VERIFY_SIG 126 #define IBMCA_F_ICA_EC_KEY_NEW 127 #define IBMCA_F_ICA_EC_KEY_INIT 128 #define IBMCA_F_ICA_EC_KEY_GENERATE 129 #define IBMCA_F_ICA_EC_KEY_GET_PUBLIC_KEY 130 #define IBMCA_F_ICA_EC_KEY_GET_PRIVATE_KEY 131 #define IBMCA_F_ICA_ECDH_DERIVE_SECRET 132 #define IBMCA_F_ICA_ECDSA_SIGN 133 #define IBMCA_F_ICA_ECDSA_VERIFY 134 #define IBMCA_F_IBMCA_X25519_KEYGEN 140 #define IBMCA_F_IBMCA_X25519_DERIVE 141 #define IBMCA_F_IBMCA_X448_KEYGEN 142 #define IBMCA_F_IBMCA_X448_DERIVE 143 #define IBMCA_F_IBMCA_ED25519_KEYGEN 144 #define IBMCA_F_IBMCA_ED448_KEYGEN 145 #define IBMCA_F_IBMCA_ED25519_SIGN 146 #define IBMCA_F_IBMCA_ED448_SIGN 147 #define IBMCA_F_IBMCA_ED25519_VERIFY 148 #define IBMCA_F_IBMCA_ED448_VERIFY 149 /* 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 #define IBMCA_R_EC_INVALID_PARM 120 #define IBMCA_R_EC_UNSUPPORTED_CURVE 121 #define IBMCA_R_EC_INTERNAL_ERROR 122 #define IBMCA_R_EC_ICA_EC_KEY_INIT 123 #define IBMCA_R_EC_CURVE_DOES_NOT_SUPPORT_SIGNING 159 #define IBMCA_R_PKEY_INTERNAL_ERROR 160 #define IBMCA_R_PKEY_KEYGEN_FAILED 161 #define IBMCA_R_PKEY_KEYS_NOT_SET 162 #endif openssl-ibmca-2.1.0/src/ibmca.h000066400000000000000000000655361353531367100163070ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 #if OPENSSL_VERSION_NUMBER < 0x10100000L #define OLDER_OPENSSL #endif /* * Here is a DEBUG_PRINTF macro 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 /* 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) #define EVP_CIPHER_CTX_key_length(ctx) ((ctx)->cipher->key_len) #define EVP_MD_CTX_md_data(ctx) ((ctx)->md_data) #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 /******************************* Cipher stuff *********************************/ typedef struct ibmca_des_context { unsigned char key[sizeof(ica_des_key_triple_t)]; } ICA_DES_CTX; typedef ICA_DES_CTX ICA_TDES_CTX; #define AES_128_KEYLEN AES_KEY_LEN128 typedef struct ibmca_aes_128_context { unsigned char key[sizeof(ica_aes_key_len_128_t)]; } ICA_AES_128_CTX; #define AES_192_KEYLEN AES_KEY_LEN192 typedef struct ibmca_aes_192_context { unsigned char key[sizeof(ica_aes_key_len_192_t)]; } ICA_AES_192_CTX; #define AES_256_KEYLEN AES_KEY_LEN256 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; #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 const EVP_CIPHER *ibmca_des_ecb(); const EVP_CIPHER *ibmca_des_cbc(); const EVP_CIPHER *ibmca_des_ofb(); const EVP_CIPHER *ibmca_des_cfb(); const EVP_CIPHER *ibmca_tdes_ecb(); const EVP_CIPHER *ibmca_tdes_cbc(); const EVP_CIPHER *ibmca_tdes_ofb(); const EVP_CIPHER *ibmca_tdes_cfb(); const EVP_CIPHER *ibmca_aes_128_ecb(); const EVP_CIPHER *ibmca_aes_128_cbc(); const EVP_CIPHER *ibmca_aes_128_ofb(); const EVP_CIPHER *ibmca_aes_128_cfb(); const EVP_CIPHER *ibmca_aes_192_ecb(); const EVP_CIPHER *ibmca_aes_192_cbc(); const EVP_CIPHER *ibmca_aes_192_ofb(); const EVP_CIPHER *ibmca_aes_192_cfb(); const EVP_CIPHER *ibmca_aes_256_ecb(); const EVP_CIPHER *ibmca_aes_256_cbc(); const EVP_CIPHER *ibmca_aes_256_ofb(); const EVP_CIPHER *ibmca_aes_256_cfb(); #ifndef OPENSSL_NO_AES_GCM const EVP_CIPHER *ibmca_aes_128_gcm(); const EVP_CIPHER *ibmca_aes_192_gcm(); const EVP_CIPHER *ibmca_aes_256_gcm(); #endif #ifndef OLDER_OPENSSL void ibmca_des_ecb_destroy(); void ibmca_des_cbc_destroy(); void ibmca_des_ofb_destroy(); void ibmca_des_cfb_destroy(); void ibmca_tdes_ecb_destroy(); void ibmca_tdes_cbc_destroy(); void ibmca_tdes_ofb_destroy(); void ibmca_tdes_cfb_destroy(); void ibmca_aes_128_ecb_destroy(); void ibmca_aes_128_cbc_destroy(); void ibmca_aes_128_ofb_destroy(); void ibmca_aes_128_cfb_destroy(); void ibmca_aes_192_ecb_destroy(); void ibmca_aes_192_cbc_destroy(); void ibmca_aes_192_ofb_destroy(); void ibmca_aes_192_cfb_destroy(); void ibmca_aes_256_ecb_destroy(); void ibmca_aes_256_cbc_destroy(); void ibmca_aes_256_ofb_destroy(); void ibmca_aes_256_cfb_destroy(); void ibmca_aes_128_gcm_destroy(); void ibmca_aes_192_gcm_destroy(); void ibmca_aes_256_gcm_destroy(); #endif /******************************* Digest stuff *********************************/ #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; const EVP_MD *ibmca_sha1(); #ifndef OLDER_OPENSSL void ibmca_sha1_destroy(); #endif #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; const EVP_MD *ibmca_sha256(); #ifndef OLDER_OPENSSL void ibmca_sha256_destroy(); #endif #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; const EVP_MD *ibmca_sha512(); #ifndef OLDER_OPENSSL void ibmca_sha512_destroy(); #endif #endif /******************************** BIGNUM stuff ********************************/ int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx); /********************************* RSA stuff **********************************/ #ifndef OPENSSL_NO_RSA RSA_METHOD *ibmca_rsa(); #ifndef OLDER_OPENSSL void ibmca_rsa_destroy(void); #endif #endif extern ica_adapter_handle_t ibmca_handle; /********************************* DSA stuff **********************************/ #ifndef OPENSSL_NO_DSA DSA_METHOD *ibmca_dsa(); #ifndef OLDER_OPENSSL void ibmca_dsa_destroy(void); #endif #endif /********************************** DH stuff **********************************/ #ifndef OPENSSL_NO_DH DH_METHOD *ibmca_dh(); #ifndef OLDER_OPENSSL void ibmca_dh_destroy(void); #endif #endif /********************************** EC stuff **********************************/ /* Either enable or disable ALL ECC */ #ifndef OPENSSL_NO_EC #if defined(OPENSSL_NO_ECDH) || defined(OPENSSL_NO_ECDSA) #define OPENSSL_NO_EC #endif #endif #define IBMCA_EC_MAX_D_LEN 66 #define IBMCA_EC_MAX_Q_LEN (2 * IBMCA_EC_MAX_D_LEN) #define IBMCA_EC_MAX_SIG_LEN IBMCA_EC_MAX_Q_LEN #define IBMCA_EC_MAX_Z_LEN IBMCA_EC_MAX_D_LEN #ifndef OPENSSL_NO_EC void ibmca_ec_destroy(void); int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh); ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey); int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); #ifdef OLDER_OPENSSL extern ECDSA_METHOD *ibmca_ecdsa; extern ECDH_METHOD *ibmca_ecdh; extern const ECDSA_METHOD *ossl_ecdsa; extern const ECDH_METHOD *ossl_ecdh; int ibmca_older_ecdh_compute_key(void *out, size_t len, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)); ECDSA_SIG *ibmca_older_ecdsa_do_sign(const unsigned char *dgst, int dlen, const BIGNUM *, const BIGNUM *, EC_KEY *eckey); int ibmca_older_ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); /* * APIs which are missing in openssl 1.0.2. */ ECDH_METHOD *ECDH_METHOD_new(const ECDH_METHOD *meth); void ECDH_METHOD_set_compute_key(ECDH_METHOD *meth, int (*compute_key)(void *out, size_t len, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))); void ECDH_METHOD_get_compute_key(const ECDH_METHOD *meth, int (**compute_key)(void *out, size_t len, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))); void ECDH_METHOD_set_name(ECDH_METHOD *meth, char *name); void ECDH_METHOD_free(ECDH_METHOD *meth); void ECDSA_METHOD_get_sign(const ECDSA_METHOD *meth, int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp), ECDSA_SIG *(**psign_sig)(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)); void ECDSA_METHOD_get_verify(const ECDSA_METHOD *meth, int (**pverify_sig)(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey)); #else extern EC_KEY_METHOD *ibmca_ec; extern const EC_KEY_METHOD *ossl_ec; int ibmca_ec_key_gen(EC_KEY *eckey); int ibmca_ecdsa_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig_array, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey); int ibmca_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); #endif #endif const EVP_PKEY_METHOD *ibmca_x25519(void); const EVP_PKEY_METHOD *ibmca_x448(void); const EVP_PKEY_METHOD *ibmca_ed25519(void); const EVP_PKEY_METHOD *ibmca_ed448(void); void ibmca_x25519_destroy(void); void ibmca_x448_destroy(void); void ibmca_ed25519_destroy(void); void ibmca_ed448_destroy(void); /******************************* Libica stuff *********************************/ /* * These are the function pointers that are (un)set when the library has * successfully (un)loaded. */ typedef unsigned int (*ica_get_functionlist_t)(libica_func_list_element *, unsigned int *); 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_rsa_crt_t)(ica_adapter_handle_t, unsigned char *, ica_rsa_key_crt_t *, unsigned char *); typedef unsigned int (*ica_random_number_generate_t)(unsigned int, unsigned char *); typedef unsigned int (*ica_sha1_t)(unsigned int, unsigned int, unsigned char *, sha_context_t *, unsigned char *); typedef unsigned int (*ica_sha256_t)(unsigned int, unsigned int, unsigned char *, sha256_context_t *, unsigned char *); typedef unsigned int (*ica_sha512_t)(unsigned int, unsigned int, unsigned char *, sha512_context_t *, unsigned char *); typedef unsigned int (*ica_des_ecb_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, unsigned char *key, unsigned int direction); typedef unsigned int (*ica_des_cbc_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, unsigned char *key, unsigned char *iv, unsigned int direction); 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_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_3des_ecb_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, unsigned char *key, unsigned int direction); typedef unsigned int (*ica_3des_cbc_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, unsigned char *key, unsigned char *iv, 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_ecb_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, unsigned char *key, unsigned int key_length, unsigned int direction); typedef unsigned int (*ica_aes_cbc_t)(const unsigned char *in_data, unsigned char *out_data, unsigned long data_length, unsigned char *key, unsigned int key_length, 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); #ifndef OPENSSL_NO_EC typedef ICA_EC_KEY* (*ica_ec_key_new_t)(unsigned int nid, unsigned int *privlen); typedef int (*ica_ec_key_init_t)(const unsigned char *X, const unsigned char *Y, const unsigned char *D, ICA_EC_KEY *key); typedef int (*ica_ec_key_generate_t)(ica_adapter_handle_t adapter_handle, ICA_EC_KEY *key); typedef int (*ica_ecdh_derive_secret_t)(ica_adapter_handle_t adapter_handle, const ICA_EC_KEY *privkey_A, const ICA_EC_KEY *pubkey_B, unsigned char *z, unsigned int z_length); typedef int (*ica_ecdsa_sign_t)(ica_adapter_handle_t adapter_handle, const ICA_EC_KEY *privkey, const unsigned char *hash, unsigned int hash_length, unsigned char *signature, unsigned int signature_length); typedef int (*ica_ecdsa_verify_t)(ica_adapter_handle_t adapter_handle, const ICA_EC_KEY *pubkey, const unsigned char *hash, unsigned int hash_length, const unsigned char *signature, unsigned int signature_length); typedef int (*ica_ec_key_get_public_key_t)(ICA_EC_KEY *key, unsigned char *q, unsigned int *q_len); typedef int (*ica_ec_key_get_private_key_t)(ICA_EC_KEY *key, unsigned char *d, unsigned int *d_len); typedef void (*ica_ec_key_free_t)(ICA_EC_KEY *key); #endif typedef int (*ica_x25519_ctx_new_t)(ICA_X25519_CTX **ctx); typedef int (*ica_x448_ctx_new_t)(ICA_X448_CTX **ctx); typedef int (*ica_ed25519_ctx_new_t)(ICA_ED25519_CTX **ctx); typedef int (*ica_ed448_ctx_new_t)(ICA_ED448_CTX **ctx); typedef int (*ica_x25519_key_set_t)(ICA_X25519_CTX *ctx, const unsigned char priv[32], const unsigned char pub[32]); typedef int (*ica_x448_key_set_t)(ICA_X448_CTX *ctx, const unsigned char priv[56], const unsigned char pub[56]); typedef int (*ica_ed25519_key_set_t)(ICA_ED25519_CTX *ctx, const unsigned char priv[32], const unsigned char pub[32]); typedef int (*ica_ed448_key_set_t)(ICA_ED448_CTX *ctx, const unsigned char priv[56], const unsigned char pub[56]); typedef int (*ica_x25519_key_get_t)(ICA_X25519_CTX *ctx, unsigned char priv[32], unsigned char pub[32]); typedef int (*ica_x448_key_get_t)(ICA_X448_CTX *ctx, unsigned char priv[56], unsigned char pub[56]); typedef int (*ica_ed25519_key_get_t)(ICA_ED25519_CTX *ctx, unsigned char priv[32], unsigned char pub[32]); typedef int (*ica_ed448_key_get_t)(ICA_ED448_CTX *ctx, unsigned char priv[57], unsigned char pub[57]); typedef int (*ica_x25519_key_gen_t)(ICA_X25519_CTX *ctx); typedef int (*ica_x448_key_gen_t)(ICA_X448_CTX *ctx); typedef int (*ica_ed25519_key_gen_t)(ICA_ED25519_CTX *ctx); typedef int (*ica_ed448_key_gen_t)(ICA_ED448_CTX *ctx); typedef int (*ica_x25519_derive_t)(ICA_X25519_CTX *ctx, unsigned char shared_secret[32], const unsigned char peer_pub[32]); typedef int (*ica_x448_derive_t)(ICA_X448_CTX *ctx, unsigned char shared_secret[56], const unsigned char peer_pub[56]); typedef int (*ica_ed25519_sign_t)(ICA_ED25519_CTX *ctx, unsigned char sig[64], const unsigned char *msg, size_t msglen); typedef int (*ica_ed448_sign_t)(ICA_ED448_CTX *ctx, unsigned char sig[114], const unsigned char *msg, size_t msglen); typedef int (*ica_ed25519_verify_t)(ICA_ED25519_CTX *ctx, const unsigned char sig[64], const unsigned char *msg, size_t msglen); typedef int (*ica_ed448_verify_t)(ICA_ED448_CTX *ctx, const unsigned char sig[114], const unsigned char *msg, size_t msglen); typedef int (*ica_x25519_ctx_del_t)(ICA_X25519_CTX **ctx); typedef int (*ica_x448_ctx_del_t)(ICA_X448_CTX **ctx); typedef int (*ica_ed25519_ctx_del_t)(ICA_ED25519_CTX **ctx); typedef int (*ica_ed448_ctx_del_t)(ICA_ED448_CTX **ctx); /* entry points into libica, filled out at DSO load time */ extern ica_get_functionlist_t p_ica_get_functionlist; extern ica_set_fallback_mode_t p_ica_set_fallback_mode; extern ica_open_adapter_t p_ica_open_adapter; extern ica_close_adapter_t p_ica_close_adapter; extern ica_rsa_mod_expo_t p_ica_rsa_mod_expo; extern ica_random_number_generate_t p_ica_random_number_generate; extern ica_rsa_crt_t p_ica_rsa_crt; extern ica_sha1_t p_ica_sha1; extern ica_sha256_t p_ica_sha256; extern ica_sha512_t p_ica_sha512; extern ica_des_ecb_t p_ica_des_ecb; extern ica_des_cbc_t p_ica_des_cbc; extern ica_des_ofb_t p_ica_des_ofb; extern ica_des_cfb_t p_ica_des_cfb; extern ica_3des_ecb_t p_ica_3des_ecb; extern ica_3des_cbc_t p_ica_3des_cbc; extern ica_3des_cfb_t p_ica_3des_cfb; extern ica_3des_ofb_t p_ica_3des_ofb; extern ica_aes_ecb_t p_ica_aes_ecb; extern ica_aes_cbc_t p_ica_aes_cbc; extern ica_aes_ofb_t p_ica_aes_ofb; extern ica_aes_cfb_t p_ica_aes_cfb; #ifndef OPENSSL_NO_AES_GCM extern ica_aes_gcm_initialize_t p_ica_aes_gcm_initialize; extern ica_aes_gcm_intermediate_t p_ica_aes_gcm_intermediate; extern ica_aes_gcm_last_t p_ica_aes_gcm_last; #endif #ifndef OPENSSL_NO_EC extern ica_ec_key_new_t p_ica_ec_key_new; extern ica_ec_key_init_t p_ica_ec_key_init; extern ica_ec_key_generate_t p_ica_ec_key_generate; extern ica_ecdh_derive_secret_t p_ica_ecdh_derive_secret; extern ica_ecdsa_sign_t p_ica_ecdsa_sign; extern ica_ecdsa_verify_t p_ica_ecdsa_verify; extern ica_ec_key_get_public_key_t p_ica_ec_key_get_public_key; extern ica_ec_key_get_private_key_t p_ica_ec_key_get_private_key; extern ica_ec_key_free_t p_ica_ec_key_free; #endif extern ica_x25519_ctx_new_t p_ica_x25519_ctx_new; extern ica_x448_ctx_new_t p_ica_x448_ctx_new; extern ica_ed25519_ctx_new_t p_ica_ed25519_ctx_new; extern ica_ed448_ctx_new_t p_ica_ed448_ctx_new; extern ica_x25519_key_set_t p_ica_x25519_key_set; extern ica_x448_key_set_t p_ica_x448_key_set; extern ica_ed25519_key_set_t p_ica_ed25519_key_set; extern ica_ed448_key_set_t p_ica_ed448_key_set; extern ica_x25519_key_get_t p_ica_x25519_key_get; extern ica_x448_key_get_t p_ica_x448_key_get; extern ica_ed25519_key_get_t p_ica_ed25519_key_get; extern ica_ed448_key_get_t p_ica_ed448_key_get; extern ica_x25519_key_gen_t p_ica_x25519_key_gen; extern ica_x448_key_gen_t p_ica_x448_key_gen; extern ica_ed25519_key_gen_t p_ica_ed25519_key_gen; extern ica_ed448_key_gen_t p_ica_ed448_key_gen; extern ica_x25519_derive_t p_ica_x25519_derive; extern ica_x448_derive_t p_ica_x448_derive; extern ica_ed25519_sign_t p_ica_ed25519_sign; extern ica_ed448_sign_t p_ica_ed448_sign; extern ica_ed25519_verify_t p_ica_ed25519_verify; extern ica_ed448_verify_t p_ica_ed448_verify; extern ica_x25519_ctx_del_t p_ica_x25519_ctx_del; extern ica_x448_ctx_del_t p_ica_x448_ctx_del; extern ica_ed25519_ctx_del_t p_ica_ed25519_ctx_del; extern ica_ed448_ctx_del_t p_ica_ed448_ctx_del; openssl-ibmca-2.1.0/src/ibmca_cipher.c000066400000000000000000001145661353531367100176320ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 "ibmca.h" #include "e_ibmca_err.h" static int ibmca_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { ICA_DES_CTX *pCtx = (ICA_DES_CTX *) EVP_CIPHER_CTX_get_cipher_data(ctx); memcpy(pCtx->key, key, EVP_CIPHER_CTX_key_length(ctx)); return 1; } static int ibmca_cipher_cleanup(EVP_CIPHER_CTX *ctx) { return 1; } #define IMPLEMENT_IBMCA_DES_CIPHER_FN(name, NAME) \ static int ibmca_##name##_cipher(EVP_CIPHER_CTX *ctx, \ unsigned char *out, \ const unsigned char *in, size_t len) \ { \ ICA_##NAME##_CTX *c = \ (ICA_##NAME##_CTX *)EVP_CIPHER_CTX_get_cipher_data(ctx); \ unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); \ const int mode = EVP_CIPHER_CTX_mode(ctx); \ const int enc = EVP_CIPHER_CTX_encrypting(ctx) ? \ ICA_ENCRYPT : ICA_DECRYPT; \ int rv; \ \ switch (mode) { \ case EVP_CIPH_ECB_MODE: \ rv = p_ica_##name##_ecb(in, out, len, c->key, enc); \ break; \ case EVP_CIPH_CBC_MODE: \ rv = p_ica_##name##_cbc(in, out, len, c->key, iv, enc); \ break; \ case EVP_CIPH_CFB_MODE: \ rv = p_ica_##name##_cfb(in, out, len, c->key, iv, 8, enc); \ break; \ case EVP_CIPH_OFB_MODE: \ rv = p_ica_##name##_ofb(in, out, len, c->key, iv, enc); \ break; \ default: \ IBMCAerr(IBMCA_F_IBMCA_##NAME##_CIPHER, \ IBMCA_R_CIPHER_MODE_NOT_SUPPORTED); \ return 0; \ } \ if (rv) { \ IBMCAerr(IBMCA_F_IBMCA_##NAME##_CIPHER, \ IBMCA_R_REQUEST_FAILED); \ return 0; \ } \ return 1; \ } IMPLEMENT_IBMCA_DES_CIPHER_FN(des, DES) IMPLEMENT_IBMCA_DES_CIPHER_FN(3des, TDES) #ifdef OLDER_OPENSSL # define DECLARE_DES_EVP(mode, block_size, key_len, iv_len, flags, \ ctx_size, init, do_cipher, cleanup, \ set_asn1_parameters, get_asn1_parameters) \ const EVP_CIPHER des_##mode = { \ NID_des_##mode, \ block_size, \ key_len, \ iv_len, \ flags, \ init, \ do_cipher, \ cleanup, \ ctx_size, \ set_asn1_parameters, \ get_asn1_parameters, \ NULL, \ NULL \ }; \ const EVP_CIPHER *ibmca_des_##mode(void) \ { \ return &des_##mode; \ } #else # define DECLARE_DES_EVP(mode, block_size, key_len, iv_len, flags, \ ctx_size, init, do_cipher, cleanup, \ set_asn1_parameters, get_asn1_parameters) \ static EVP_CIPHER *des_##mode = NULL; \ const EVP_CIPHER *ibmca_des_##mode(void) \ { \ EVP_CIPHER *cipher; \ \ if (des_##mode != NULL) \ goto done; \ \ if ((cipher = EVP_CIPHER_meth_new(NID_des_##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_free(cipher); \ cipher = NULL; \ } \ des_##mode = cipher; \ done: \ return des_##mode; \ } \ \ void ibmca_des_##mode##_destroy(void) \ { \ EVP_CIPHER_meth_free(des_##mode); \ des_##mode = NULL; \ } #endif DECLARE_DES_EVP(ecb, sizeof(ica_des_vector_t), sizeof(ica_des_key_single_t), sizeof(ica_des_vector_t), EVP_CIPH_ECB_MODE, sizeof(struct ibmca_des_context), ibmca_init_key, ibmca_des_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv) DECLARE_DES_EVP(cbc, sizeof(ica_des_vector_t), sizeof(ica_des_key_single_t), sizeof(ica_des_vector_t), EVP_CIPH_CBC_MODE, sizeof(struct ibmca_des_context), ibmca_init_key, ibmca_des_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv) DECLARE_DES_EVP(ofb, 1, sizeof(ica_des_key_single_t), sizeof(ica_des_vector_t), EVP_CIPH_OFB_MODE, sizeof(struct ibmca_des_context), ibmca_init_key, ibmca_des_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv) DECLARE_DES_EVP(cfb, 1, sizeof(ica_des_key_single_t), sizeof(ica_des_vector_t), EVP_CIPH_CFB_MODE, sizeof(struct ibmca_des_context), ibmca_init_key, ibmca_des_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv) #ifdef OLDER_OPENSSL # define DECLARE_TDES_EVP(mode, block_size, key_len, iv_len, flags, \ ctx_size, init, do_cipher, cleanup, \ set_asn1_parameters, get_asn1_parameters) \ const EVP_CIPHER tdes_##mode = { \ NID_des_ede3_##mode, \ block_size, \ key_len, \ iv_len, \ flags, \ init, \ do_cipher, \ cleanup, \ ctx_size, \ set_asn1_parameters, \ get_asn1_parameters, \ NULL, \ NULL \ }; \ const EVP_CIPHER *ibmca_tdes_##mode(void) \ { \ return &tdes_##mode; \ } #else # define DECLARE_TDES_EVP(mode, block_size, key_len, iv_len, flags, \ ctx_size, init, do_cipher, cleanup, \ set_asn1_parameters, get_asn1_parameters) \ static EVP_CIPHER *tdes_##mode = NULL; \ const EVP_CIPHER *ibmca_tdes_##mode(void) \ { \ EVP_CIPHER *cipher; \ \ if (tdes_##mode != NULL) \ goto done; \ \ if ((cipher = EVP_CIPHER_meth_new(NID_des_ede3_##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_free(cipher); \ cipher = NULL; \ } \ tdes_##mode = cipher; \ done: \ return tdes_##mode; \ } \ \ void ibmca_tdes_##mode##_destroy(void) \ { \ EVP_CIPHER_meth_free(tdes_##mode); \ tdes_##mode = NULL; \ } #endif DECLARE_TDES_EVP(ecb, sizeof(ica_des_vector_t), sizeof(ica_des_key_triple_t), sizeof(ica_des_vector_t), EVP_CIPH_ECB_MODE | EVP_CIPH_FLAG_FIPS, sizeof(struct ibmca_des_context), ibmca_init_key, ibmca_3des_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv) DECLARE_TDES_EVP(cbc, sizeof(ica_des_vector_t), sizeof(ica_des_key_triple_t), sizeof(ica_des_vector_t), EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_FIPS, sizeof(struct ibmca_des_context), ibmca_init_key, ibmca_3des_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv) DECLARE_TDES_EVP(ofb, 1, sizeof(ica_des_key_triple_t), sizeof(ica_des_vector_t), EVP_CIPH_OFB_MODE | EVP_CIPH_FLAG_FIPS, sizeof(struct ibmca_des_context), ibmca_init_key, ibmca_3des_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv) DECLARE_TDES_EVP(cfb, 1, sizeof(ica_des_key_triple_t), sizeof(ica_des_vector_t), EVP_CIPH_CFB_MODE | EVP_CIPH_FLAG_FIPS, sizeof(struct ibmca_des_context), ibmca_init_key, ibmca_3des_cipher, ibmca_cipher_cleanup, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv) #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 #define IMPLEMENT_IBMCA_AES_CIPHER_FN(name, NAME) \ static int ibmca_##name##_cipher(EVP_CIPHER_CTX *ctx, \ unsigned char *out, \ const unsigned char *in, size_t len) \ { \ ICA_##NAME##_CTX *c = \ (ICA_##NAME##_CTX *)EVP_CIPHER_CTX_get_cipher_data(ctx); \ unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); \ const int mode = EVP_CIPHER_CTX_mode(ctx); \ const int enc = EVP_CIPHER_CTX_encrypting(ctx) ? \ ICA_ENCRYPT : ICA_DECRYPT; \ int rv; \ \ switch (mode) { \ case EVP_CIPH_ECB_MODE: \ rv = p_ica_aes_ecb(in, out, len, c->key, NAME##_KEYLEN, enc); \ break; \ case EVP_CIPH_CBC_MODE: \ rv = p_ica_aes_cbc(in, out, len, c->key, NAME##_KEYLEN, \ iv, enc); \ break; \ case EVP_CIPH_CFB_MODE: \ rv = p_ica_aes_cfb(in, out, len, c->key, NAME##_KEYLEN, \ iv, 16, enc); \ break; \ case EVP_CIPH_OFB_MODE: \ rv = p_ica_aes_ofb(in, out, len, c->key, NAME##_KEYLEN, \ iv, enc); \ break; \ default: \ IBMCAerr(IBMCA_F_IBMCA_##NAME##_CIPHER, \ IBMCA_R_CIPHER_MODE_NOT_SUPPORTED); \ return 0; \ } \ if (rv) { \ IBMCAerr(IBMCA_F_IBMCA_##NAME##_CIPHER, \ IBMCA_R_REQUEST_FAILED); \ return 0; \ } \ \ return 1; \ } IMPLEMENT_IBMCA_AES_CIPHER_FN(aes_128, AES_128) IMPLEMENT_IBMCA_AES_CIPHER_FN(aes_192, AES_192) IMPLEMENT_IBMCA_AES_CIPHER_FN(aes_256, AES_256) #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 \ }; \ 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; \ 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; \ } \ \ 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, 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 | EVP_CIPH_FLAG_FIPS, sizeof(ICA_AES_GCM_CTX), ibmca_aes_gcm_init_key, ibmca_aes_gcm_cipher, NULL, NULL, NULL, ibmca_aes_gcm_ctrl) #endif openssl-ibmca-2.1.0/src/ibmca_dh.c000066400000000000000000000045471353531367100167500ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 "ibmca.h" #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); } #ifdef OLDER_OPENSSL static DH_METHOD dh_m = { "Ibmca DH method", /* name */ NULL, /* generate_key */ NULL, /* compute_key */ ibmca_mod_exp_dh, /* bn_mod_exp */ NULL, /* init */ NULL, /* finish */ DH_FLAG_FIPS_METHOD, /* flags */ NULL /* app_data */ }; DH_METHOD *ibmca_dh(void) { const DH_METHOD *meth1 = DH_OpenSSL(); dh_m.generate_key = meth1->generate_key; dh_m.compute_key = meth1->compute_key; return &dh_m; } #else static DH_METHOD *dh_m = NULL; DH_METHOD *ibmca_dh(void) { const DH_METHOD *meth1; DH_METHOD *method; if (dh_m != NULL) goto done; if ((method = DH_meth_new("Ibmca DH method", 0)) == NULL || (meth1 = DH_OpenSSL()) == NULL || !DH_meth_set_generate_key(method, DH_meth_get_generate_key(meth1)) || !DH_meth_set_compute_key(method, DH_meth_get_compute_key(meth1)) || !DH_meth_set_bn_mod_exp(method, ibmca_mod_exp_dh) || !DH_meth_set_flags(method, DH_FLAG_FIPS_METHOD)) { DH_meth_free(method); method = NULL; meth1 = NULL; } dh_m = method; done: return dh_m; } void ibmca_dh_destroy(void) { DH_meth_free(dh_m); } #endif #endif /* end OPENSSL_NO_DH */ openssl-ibmca-2.1.0/src/ibmca_digest.c000066400000000000000000000563201353531367100176300ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 "ibmca.h" #include "e_ibmca_err.h" #ifndef OPENSSL_NO_SHA1 static int ibmca_sha1_init(EVP_MD_CTX *ctx) { IBMCA_SHA_CTX *ibmca_sha_ctx = (IBMCA_SHA_CTX *) EVP_MD_CTX_md_data(ctx); 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) { IBMCA_SHA_CTX *ibmca_sha_ctx = (IBMCA_SHA_CTX *) EVP_MD_CTX_md_data(ctx); 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) { IBMCA_SHA_CTX *ibmca_sha_ctx = (IBMCA_SHA_CTX *) EVP_MD_CTX_md_data(ctx); 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; } static int ibmca_sha1_cleanup(EVP_MD_CTX *ctx) { return 1; } #endif /* OPENSSL_NO_SHA1 */ #ifndef OPENSSL_NO_SHA256 static int ibmca_sha256_init(EVP_MD_CTX *ctx) { IBMCA_SHA256_CTX *ibmca_sha256_ctx = (IBMCA_SHA256_CTX *) EVP_MD_CTX_md_data(ctx); memset((unsigned char *) ibmca_sha256_ctx, 0, sizeof(*ibmca_sha256_ctx)); return 1; } static int ibmca_sha256_update(EVP_MD_CTX *ctx, const void *in_data, unsigned long inlen) { IBMCA_SHA256_CTX *ibmca_sha256_ctx = (IBMCA_SHA256_CTX *) EVP_MD_CTX_md_data(ctx); 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; } static int ibmca_sha256_final(EVP_MD_CTX *ctx, unsigned char *md) { IBMCA_SHA256_CTX *ibmca_sha256_ctx = (IBMCA_SHA256_CTX *) EVP_MD_CTX_md_data(ctx); 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; } static int ibmca_sha256_cleanup(EVP_MD_CTX *ctx) { return 1; } #endif /* OPENSSL_NO_SHA256 */ #ifndef OPENSSL_NO_SHA512 static int ibmca_sha512_init(EVP_MD_CTX *ctx) { IBMCA_SHA512_CTX *ibmca_sha512_ctx = (IBMCA_SHA512_CTX *) EVP_MD_CTX_md_data(ctx); 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) { IBMCA_SHA512_CTX *ibmca_sha512_ctx = (IBMCA_SHA512_CTX *) EVP_MD_CTX_md_data(ctx); 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) { IBMCA_SHA512_CTX *ibmca_sha512_ctx = (IBMCA_SHA512_CTX *) EVP_MD_CTX_md_data(ctx); 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 */ #ifdef OLDER_OPENSSL # define DECLARE_SHA_EVP(type, pkey_type, md_size, flags, \ block_size, ctx_size, init, update, \ final, copy, cleanup) \ static const EVP_MD type##_md = { \ NID_##type, \ NID_##pkey_type, \ md_size, \ EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|flags, \ init, \ update, \ final, \ copy, \ cleanup, \ EVP_PKEY_RSA_method, \ block_size, \ ctx_size \ }; \ const EVP_MD *ibmca_##type(void) \ { \ return &type##_md; \ } #else # define DECLARE_SHA_EVP(type, pkey_type, md_size, flags, \ block_size, ctx_size, init, update, \ final, copy, cleanup) \ static EVP_MD *type##_md = NULL; \ const EVP_MD *ibmca_##type(void) \ { \ EVP_MD *md; \ \ if (type##_md != NULL) \ goto done; \ \ if ((md = EVP_MD_meth_new(NID_##type, NID_##pkey_type)) == NULL \ || !EVP_MD_meth_set_result_size(md, md_size) \ || !EVP_MD_meth_set_input_blocksize(md, block_size) \ || !EVP_MD_meth_set_app_datasize(md, ctx_size) \ || !EVP_MD_meth_set_flags(md, flags) \ || !EVP_MD_meth_set_init(md, init) \ || !EVP_MD_meth_set_update(md, update) \ || !EVP_MD_meth_set_final(md, final) \ || !EVP_MD_meth_set_cleanup(md, cleanup)) { \ EVP_MD_meth_free(md); \ md = NULL; \ } \ type##_md = md; \ done: \ return type##_md; \ } \ \ void ibmca_##type##_destroy(void) \ { \ EVP_MD_meth_free(type##_md); \ type##_md = NULL; \ } #endif #ifndef OPENSSL_NO_SHA1 DECLARE_SHA_EVP(sha1, sha1WithRSAEncryption, SHA_HASH_LENGTH, EVP_MD_FLAG_FIPS, SHA_BLOCK_SIZE, sizeof(EVP_MD *) + sizeof(struct ibmca_sha1_ctx), ibmca_sha1_init, ibmca_sha1_update, ibmca_sha1_final, NULL, ibmca_sha1_cleanup) #endif #ifndef OPENSSL_NO_SHA256 DECLARE_SHA_EVP(sha256, sha256WithRSAEncryption, SHA256_HASH_LENGTH, EVP_MD_FLAG_FIPS, SHA256_BLOCK_SIZE, sizeof(EVP_MD *) + sizeof(struct ibmca_sha256_ctx), ibmca_sha256_init, ibmca_sha256_update, ibmca_sha256_final, NULL, ibmca_sha256_cleanup) #endif #ifndef OPENSSL_NO_SHA512 DECLARE_SHA_EVP(sha512, sha512WithRSAEncryption, SHA512_HASH_LENGTH, EVP_MD_FLAG_FIPS, SHA512_BLOCK_SIZE, sizeof(EVP_MD *) + sizeof(struct ibmca_sha512_ctx), ibmca_sha512_init, ibmca_sha512_update, ibmca_sha512_final, NULL, ibmca_sha512_cleanup) #endif openssl-ibmca-2.1.0/src/ibmca_dsa.c000066400000000000000000000102221353531367100171070ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 "ibmca.h" #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); } #ifdef OLDER_OPENSSL static DSA_METHOD dsa_m = { "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 */ DSA_FLAG_FIPS_METHOD, /* flags */ NULL /* app_data */ }; DSA_METHOD *ibmca_dsa(void) { const DSA_METHOD *meth1 = DSA_OpenSSL(); dsa_m.dsa_do_sign = meth1->dsa_do_sign; dsa_m.dsa_sign_setup = meth1->dsa_sign_setup; dsa_m.dsa_do_verify = meth1->dsa_do_verify; return &dsa_m; } #else static DSA_METHOD *dsa_m = NULL; DSA_METHOD *ibmca_dsa(void) { const DSA_METHOD *meth1; DSA_METHOD *method; if (dsa_m != NULL) goto done; if ((method = DSA_meth_new("Ibmca DSA method", 0)) == NULL || (meth1 = DSA_OpenSSL()) == NULL || !DSA_meth_set_sign(method, DSA_meth_get_sign(meth1)) || !DSA_meth_set_sign_setup(method, DSA_meth_get_sign_setup(meth1)) || !DSA_meth_set_verify(method, DSA_meth_get_verify(meth1)) || !DSA_meth_set_mod_exp(method, ibmca_dsa_mod_exp) || !DSA_meth_set_bn_mod_exp(method, ibmca_mod_exp_dsa) || !DSA_meth_set_flags(method, DSA_FLAG_FIPS_METHOD)) { DSA_meth_free(method); method = NULL; meth1 = NULL; } dsa_m = method; done: return dsa_m; } void ibmca_dsa_destroy(void) { DSA_meth_free(dsa_m); } #endif #endif /* endif OPENSSL_NO_DSA */ openssl-ibmca-2.1.0/src/ibmca_ec.c000066400000000000000000000702361353531367100167420ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 "ibmca.h" #include "e_ibmca_err.h" #ifndef OPENSSL_NO_EC ica_ec_key_new_t p_ica_ec_key_new; ica_ec_key_init_t p_ica_ec_key_init; ica_ec_key_generate_t p_ica_ec_key_generate; ica_ecdh_derive_secret_t p_ica_ecdh_derive_secret; ica_ecdsa_sign_t p_ica_ecdsa_sign; ica_ecdsa_verify_t p_ica_ecdsa_verify; ica_ec_key_get_public_key_t p_ica_ec_key_get_public_key; ica_ec_key_get_private_key_t p_ica_ec_key_get_private_key; ica_ec_key_free_t p_ica_ec_key_free; void ibmca_ec_destroy(void) { #ifdef OLDER_OPENSSL if (ibmca_ecdh) ECDH_METHOD_free(ibmca_ecdh); if (ibmca_ecdh) ECDSA_METHOD_free(ibmca_ecdsa); #else if (ibmca_ec) EC_KEY_METHOD_free(ibmca_ec); #endif } /** * ECDH key derivation method, replaces ossl_ecdh_compute_key. * * @return 1 success * 0 error */ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh) { ICA_EC_KEY *ica_pubkey = NULL, *ica_privkey = NULL; const EC_GROUP *group; BIGNUM *bn_d, *bn_x, *bn_y; unsigned int n, privlen; unsigned char X[IBMCA_EC_MAX_D_LEN]; unsigned char Y[IBMCA_EC_MAX_D_LEN]; unsigned char D[IBMCA_EC_MAX_D_LEN]; unsigned char *z_buf = NULL; int rc, ret = 0, nid; #ifndef OLDER_OPENSSL int (*compute_key_sw)(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh) = NULL; #endif /* Get group from EC_KEY */ if ((group = EC_KEY_get0_group(ecdh)) == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INVALID_PARM); return 0; } /* Determine curve nid */ nid = EC_GROUP_get_curve_name(group); if (nid <= 0) { IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR); return 0; } /* Create ICA_EC_KEY object for public key */ ica_pubkey = p_ica_ec_key_new(nid, &privlen); if (ica_pubkey == NULL) { /* This curve is not supported by libica. */ #ifdef OLDER_OPENSSL return 0; #else /* * EC_KEY_METHOD_get_compute_key misses the const-qualifier of the * parameter in some openssl versions. */ EC_KEY_METHOD_get_compute_key((EC_KEY_METHOD *)ossl_ec, &compute_key_sw); if (compute_key_sw == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR); return 0; } return compute_key_sw(pout, poutlen, pub_key, ecdh); #endif } /* Get (X,Y) from EC_POINT */ bn_x = BN_new(); bn_y = BN_new(); if (!EC_POINT_get_affine_coordinates_GFp(group, pub_key, bn_x, bn_y, NULL)) { IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Format (X) as char array, with leading zeros if necessary */ n = privlen - BN_num_bytes(bn_x); memset(X, 0, n); BN_bn2bin(bn_x, &(X[n])); /* Format (Y) as char array, with leading zeros if necessary */ n = privlen - BN_num_bytes(bn_y); memset(Y, 0, n); BN_bn2bin(bn_y, &(Y[n])); /* Initialize public ICA_EC_KEY with (X,Y) */ rc = p_ica_ec_key_init(X, Y, NULL, ica_pubkey); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); goto end; } /* Create ICA_EC_KEY object for private key */ ica_privkey = p_ica_ec_key_new(nid, &privlen); if (!ica_privkey) { IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Get private (D) value from EC_KEY */ bn_d = (BIGNUM*)EC_KEY_get0_private_key((EC_KEY*)ecdh); if (bn_d == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Format (D) as char array, with leading zeros if necessary */ n = privlen - BN_num_bytes(bn_d); memset(D, 0, n); BN_bn2bin(bn_d, &(D[n])); /* Initialize private ICA_EC_KEY with (D) */ rc = p_ica_ec_key_init(NULL, NULL, D, ica_privkey); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); goto end; } /* Allocate memory for shared secret z, will be freed by caller */ if ((z_buf = OPENSSL_malloc(privlen)) == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Calculate shared secret z */ rc = p_ica_ecdh_derive_secret(ibmca_handle, ica_privkey, ica_pubkey, z_buf, privlen); if (rc != 0) { /* Possibly no suitable adapter. */ OPENSSL_free(z_buf); #ifdef OLDER_OPENSSL goto end; #else /* * EC_KEY_METHOD_get_compute_key misses the const-qualifier of the * parameter in some openssl versions. */ EC_KEY_METHOD_get_compute_key((EC_KEY_METHOD *)ossl_ec, &compute_key_sw); if (compute_key_sw == NULL) { IBMCAerr(IBMCA_F_ICA_ECDH_DERIVE_SECRET, rc); goto end; } ret = compute_key_sw(pout, poutlen, pub_key, ecdh); goto end; #endif } *pout = z_buf; *poutlen = privlen; ret = 1; end: p_ica_ec_key_free(ica_pubkey); p_ica_ec_key_free(ica_privkey); BN_clear_free(bn_x); BN_clear_free(bn_y); return ret; } /** * ECDSA signing method (replaces ossl_ecdsa_sign_sig). * * @return pointer to a ECDSA_SIG structure or NULL if an error occurred */ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) { ECDSA_SIG *sig = NULL; ICA_EC_KEY *icakey = NULL; const EC_GROUP *group; unsigned int privlen; BIGNUM *r, *s, *bn_d, *kinv; unsigned char D[IBMCA_EC_MAX_D_LEN]; unsigned char sigret[IBMCA_EC_MAX_SIG_LEN]; int n, nid, rc; #ifndef OLDER_OPENSSL int (*sign_sw)(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) = NULL; #endif int (*sign_setup_sw)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) = NULL; ECDSA_SIG *(*sign_sig_sw)(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) = NULL; BN_CTX *ctx; /* Check parms: precomputed (k,r) are not supported by ibmca */ if (in_kinv != NULL || in_r != NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INVALID_PARM); return NULL; } /* Get group */ if ((group = EC_KEY_get0_group(eckey)) == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INVALID_PARM); return NULL; } /* Check if key usable */ #ifndef OLDER_OPENSSL if (!EC_KEY_can_sign(eckey)) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_CURVE_DOES_NOT_SUPPORT_SIGNING); return NULL; } #endif /* Get curve nid */ nid = EC_GROUP_get_curve_name(group); if (nid <= 0) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_UNSUPPORTED_CURVE); return NULL; } /* Create ICA_EC_KEY object */ icakey = p_ica_ec_key_new(nid, &privlen); if (icakey == NULL) { /* This curve is not supported by libica. */ #ifdef OLDER_OPENSSL ECDSA_METHOD_get_sign(ossl_ecdsa, &sign_setup_sw, &sign_sig_sw); #else /* * EC_KEY_METHOD_get_sign misses the const-qualifier of the * parameter in some openssl versions. */ EC_KEY_METHOD_get_sign((EC_KEY_METHOD *)ossl_ec, &sign_sw, &sign_setup_sw, &sign_sig_sw); #endif if (sign_sig_sw == NULL || sign_setup_sw == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INTERNAL_ERROR); return NULL; } kinv = NULL; r = NULL; ctx = BN_CTX_new(); sign_setup_sw(eckey, ctx, &kinv, &r); BN_CTX_free(ctx); sig = sign_sig_sw(dgst, dgst_len, kinv, r, eckey); BN_clear_free(kinv); BN_clear_free(r); return sig; } /* Get private (D) value from EC_KEY */ bn_d = (BIGNUM*)EC_KEY_get0_private_key(eckey); if (bn_d == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Format (D) as char array, with leading zeros if necessary */ n = privlen - BN_num_bytes(bn_d); memset(D, 0, n); BN_bn2bin(bn_d, &(D[n])); /* Initialize private ICA_EC_KEY */ rc = p_ica_ec_key_init(NULL, NULL, D, icakey); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); goto end; } /* Call libica signing routine */ rc = p_ica_ecdsa_sign(ibmca_handle, icakey, dgst, dgst_len, sigret, sizeof(sigret)); if (rc != 0) { /* Possibly no adapter. */ #ifdef OLDER_OPENSSL ECDSA_METHOD_get_sign(ossl_ecdsa, &sign_setup_sw, &sign_sig_sw); #else /* * EC_KEY_METHOD_get_sign misses the const-qualifier of the * parameter in some openssl versions. */ EC_KEY_METHOD_get_sign((EC_KEY_METHOD *)ossl_ec, &sign_sw, &sign_setup_sw, &sign_sig_sw); #endif if (sign_sig_sw == NULL || sign_setup_sw == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INTERNAL_ERROR); return NULL; } kinv = NULL; r = NULL; ctx = BN_CTX_new(); sign_setup_sw(eckey, ctx, &kinv, &r); BN_CTX_free(ctx); sig = sign_sig_sw(dgst, dgst_len, kinv, r, eckey); BN_clear_free(kinv); BN_clear_free(r); goto end2; } /* Construct ECDSA_SIG object from char array */ r = BN_bin2bn(sigret, privlen, NULL); s = BN_bin2bn(sigret + privlen, privlen, NULL); sig = ECDSA_SIG_new(); end: #ifndef OLDER_OPENSSL if (sig) ECDSA_SIG_set0(sig, r, s); #else if (sig) { BN_free(sig->r); sig->r = r; BN_free(sig->s); sig->s = s; } #endif end2: p_ica_ec_key_free(icakey); return sig; } /** * ECDSA verify method (replaces ossl_ecdsa_verify_sig). * * @return * 1: correct signature * 0: incorrect signature * -1: error */ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { const EC_GROUP *group; const EC_POINT *q; unsigned char x_array[IBMCA_EC_MAX_D_LEN]; unsigned char y_array[IBMCA_EC_MAX_D_LEN]; unsigned char sig_array[IBMCA_EC_MAX_Q_LEN]; BIGNUM *bn_x = NULL, *bn_y = NULL; const BIGNUM *bn_r, *bn_s; unsigned int privlen; ICA_EC_KEY *icakey = NULL; int rc, n, nid; int ret = -1; #ifndef OLDER_OPENSSL int (*verify_sw)(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) = NULL; #endif int (*verify_sig_sw)(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) = NULL; /* Check parms */ if (eckey == NULL || sig == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, EC_R_MISSING_PARAMETERS); return ret; } /* Check if key usable */ #ifndef OLDER_OPENSSL if (!EC_KEY_can_sign(eckey)) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_CURVE_DOES_NOT_SUPPORT_SIGNING); return ret; } #endif /* Get group */ if ((group = EC_KEY_get0_group(eckey)) == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_INTERNAL_ERROR); return ret; } /* Get curve nid */ nid = EC_GROUP_get_curve_name(group); if (nid <= 0) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_UNSUPPORTED_CURVE); return ret; } /* Create ICA_EC_KEY object */ icakey = p_ica_ec_key_new(nid, &privlen); if (icakey == NULL) { /* This curve is not supported by libica. */ #ifdef OLDER_OPENSSL ECDSA_METHOD_get_verify(ossl_ecdsa, &verify_sig_sw); #else /* * EC_KEY_METHOD_get_verify misses the const-qualifier of the * parameter in some openssl versions. */ EC_KEY_METHOD_get_verify((EC_KEY_METHOD *)ossl_ec, &verify_sw, &verify_sig_sw); #endif if (verify_sig_sw == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_INTERNAL_ERROR); return ret; } return verify_sig_sw(dgst, dgst_len, sig, eckey); } /* Provide public key (X,Y) */ bn_x = BN_new(); bn_y = BN_new(); q = EC_KEY_get0_public_key(eckey); if (!EC_POINT_get_affine_coordinates_GFp(group, q, bn_x, bn_y, NULL)) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Format (X) as char array with leading nulls if necessary */ n = privlen - BN_num_bytes(bn_x); memset(x_array, 0, n); BN_bn2bin(bn_x, &(x_array[n])); /* Format (Y) as char array with leading nulls if necessary */ n = privlen - BN_num_bytes(bn_y); memset(y_array, 0, n); BN_bn2bin(bn_y, &(y_array[n])); /* Initialize ICA_EC_KEY */ rc = p_ica_ec_key_init(x_array, y_array, NULL, icakey); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); goto end; } /* Get (r,s) from ECDSA_SIG */ #ifdef OLDER_OPENSSL bn_r = sig->r; bn_s = sig->s; #else ECDSA_SIG_get0(sig, &bn_r, &bn_s); #endif /* Format r as byte array with leading 0x00's if necessary */ n = privlen - BN_num_bytes(bn_r); memset(sig_array, 0, n); BN_bn2bin(bn_r, &(sig_array[n])); /* Format s as byte array with leading 0x00's if necessary */ n = privlen - BN_num_bytes(bn_s); memset(&(sig_array[privlen]), 0, n); BN_bn2bin(bn_s, &(sig_array[privlen+n])); /* Call libica verify routine */ rc = p_ica_ecdsa_verify(ibmca_handle, icakey, dgst, dgst_len, sig_array, 2 * privlen); switch (rc) { case 0: ret = 1; /* signature valid */ break; case EFAULT: ret = 0; /* signature invalid */ break; default: /* Possibly no suitable adapter. */ #ifdef OLDER_OPENSSL ECDSA_METHOD_get_verify(ossl_ecdsa, &verify_sig_sw); #else /* * EC_KEY_METHOD_get_verify misses the const-qualifier of the * parameter in some openssl versions. */ EC_KEY_METHOD_get_verify((EC_KEY_METHOD *)ossl_ec, &verify_sw, &verify_sig_sw); #endif if (verify_sig_sw == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_INTERNAL_ERROR); goto end; } ret = verify_sig_sw(dgst, dgst_len, sig, eckey); break; } end: p_ica_ec_key_free(icakey); BN_clear_free(bn_x); BN_clear_free(bn_y); return ret; } /* --- OLDER_OPENSSL section --- */ #ifdef OLDER_OPENSSL ECDSA_METHOD *ibmca_ecdsa = NULL; ECDH_METHOD *ibmca_ecdh = NULL; /* * This structure is opaque in openssl. However, get/set methods are missing * so we copy its definition and write our own. */ struct ecdh_method { const char *name; int (*compute_key)(void *out, size_t len, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)); int flags; void *app_data; }; struct ecdsa_method { const char *name; ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey); int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **r); int (*verify_sig)(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); int flags; void *app_data; }; /** * ECDH key derivation method, replaces ossl_ecdh_compute_key for older openssl. * * @return 1 success * 0 error */ int ibmca_older_ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen)) { int rc = 0; unsigned char *temp_p = NULL; size_t temp_len = 0; int (*compute_key_sw)(void *out, size_t len, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)) = NULL; rc = ibmca_ecdh_compute_key(&temp_p, &temp_len, pub_key, ecdh); if (!rc) { ECDH_METHOD_get_compute_key(ossl_ecdh, &compute_key_sw); rc = compute_key_sw == NULL ? 0 : compute_key_sw(out, outlen, pub_key, ecdh, KDF); goto end; } if (outlen < temp_len) { rc = 0; goto end; } if (KDF != NULL) { if (KDF(temp_p, temp_len, out, &outlen) == NULL) { rc = 0; goto end; } rc = outlen; } else { if (outlen > temp_len) outlen = temp_len; memcpy(out, temp_p, outlen); rc = outlen; } end: OPENSSL_free(temp_p); return rc; } /** * ECDSA sign method, replaces ecdsa_do_sign for older openssl. */ ECDSA_SIG *ibmca_older_ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) { if (in_kinv != NULL || in_r != NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_DO_SIGN, IBMCA_R_EC_INVALID_PARM); return NULL; } return ibmca_ecdsa_sign_sig(dgst, dgst_len, NULL, NULL, eckey); } /** * ECDSA verify method, replaces ecdsa_do_verify for older openssl. * * @return 1 success * 0 error */ int ibmca_older_ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { return ibmca_ecdsa_verify_sig(dgst, dgst_len, sig, eckey); } /* * APIs which are missing in openssl 1.0.2. */ ECDH_METHOD *ECDH_METHOD_new(const ECDH_METHOD *meth) { ECDH_METHOD *out; out = OPENSSL_malloc(sizeof(*out)); if (out == NULL) return NULL; if (meth) memcpy(out, meth, sizeof(*out)); else memset(out, 0, sizeof(*out)); return out; } void ECDH_METHOD_set_compute_key(ECDH_METHOD *meth, int (*compute_key)(void *out, size_t len, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))) { meth->compute_key = compute_key; } void ECDH_METHOD_get_compute_key(const ECDH_METHOD *meth, int (**compute_key)(void *out, size_t len, const EC_POINT *pub_key, EC_KEY *ecdh, void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))) { if (compute_key != NULL) *compute_key = meth->compute_key; } void ECDH_METHOD_set_name(ECDH_METHOD *meth, char *name) { meth->name = name; } void ECDH_METHOD_free(ECDH_METHOD *meth) { OPENSSL_free(meth); } void ECDSA_METHOD_get_sign(const ECDSA_METHOD *meth, int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp), ECDSA_SIG *(**psign_sig)(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)) { if (psign_setup != NULL) *psign_setup = meth->sign_setup; if (psign_sig != NULL) *psign_sig = meth->sign_sig; } void ECDSA_METHOD_get_verify(const ECDSA_METHOD *meth, int (**pverify_sig)(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey)) { if (pverify_sig != NULL) *pverify_sig = meth->verify_sig; } /* --- !OLDER_OPENSSL section --- */ #else EC_KEY_METHOD *ibmca_ec = NULL; /** * EC key generation method, replaces ossl_ec_key_gen. * * @return 1 success * 0 error */ int ibmca_ec_key_gen(EC_KEY *eckey) { ICA_EC_KEY *icakey = NULL; EC_POINT *pubkey = NULL; const EC_GROUP *group; BIGNUM *privkey = NULL, *bn_x = NULL, *bn_y = NULL; unsigned int privlen; int nid, rc, ret = 0; unsigned int q_len, d_len; unsigned char q[IBMCA_EC_MAX_Q_LEN]; unsigned char d[IBMCA_EC_MAX_D_LEN]; int (*keygen_sw)(EC_KEY *key) = NULL; /* Check group */ if ((group = EC_KEY_get0_group(eckey)) == NULL) { IBMCAerr(IBMCA_F_IBMCA_EC_KEY_GEN, IBMCA_R_EC_INVALID_PARM); return 0; } /* Determine curve nid */ nid = EC_GROUP_get_curve_name(group); if (nid <= 0) { IBMCAerr(IBMCA_F_IBMCA_EC_KEY_GEN, IBMCA_R_EC_INTERNAL_ERROR); return 0; } /* Create ICA_EC_KEY object */ icakey = p_ica_ec_key_new(nid, &privlen); if (icakey == NULL) { /* This curve is not supported by libica */ /* * EC_KEY_METHOD_get_keygen misses the const-qualifier of the * parameter in some openssl versions. */ EC_KEY_METHOD_get_keygen((EC_KEY_METHOD *)ossl_ec, &keygen_sw); if (keygen_sw == NULL) { IBMCAerr(IBMCA_F_IBMCA_EC_KEY_GEN, IBMCA_R_EC_INTERNAL_ERROR); return 0; } return keygen_sw(eckey); } /* Generate key */ rc = p_ica_ec_key_generate(ibmca_handle, icakey); if (rc != 0) { /* Possibly disabled adapter. */ /* * EC_KEY_METHOD_get_keygen misses the const-qualifier of the * parameter in some openssl versions. */ EC_KEY_METHOD_get_keygen((EC_KEY_METHOD *)ossl_ec, &keygen_sw); if (keygen_sw == NULL) { IBMCAerr(IBMCA_F_ICA_EC_KEY_GENERATE, rc); goto end; } ret = keygen_sw(eckey); goto end; } /* Get public key data from ICA_EC_KEY */ rc = p_ica_ec_key_get_public_key(icakey, (unsigned char*)&q, &q_len); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_GET_PUBLIC_KEY, rc); goto end; } /* Make EC_POINT */ pubkey = EC_POINT_new(group); if (!pubkey) { IBMCAerr(IBMCA_F_IBMCA_EC_KEY_GEN, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Add public key data to EC_POINT */ bn_x = BN_bin2bn((const unsigned char*)&q, q_len / 2, NULL); bn_y = BN_bin2bn((const unsigned char*)&(q[q_len / 2]), q_len / 2, NULL); if (!EC_POINT_set_affine_coordinates_GFp(group, pubkey, bn_x, bn_y, NULL)) { IBMCAerr(IBMCA_F_IBMCA_EC_KEY_GEN, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Add EC_POINT to EC_KEY */ if (!EC_KEY_set_public_key(eckey, pubkey)) { IBMCAerr(IBMCA_F_IBMCA_EC_KEY_GEN, IBMCA_R_EC_INTERNAL_ERROR); goto end; } /* Get private key data from ICA_EC_KEY */ rc = p_ica_ec_key_get_private_key(icakey, (unsigned char*)&d, &d_len); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_GET_PRIVATE_KEY, rc); goto end; } /* Add private key data to EC_KEY */ privkey = BN_bin2bn((unsigned char*)&d, d_len, NULL); if (!EC_KEY_set_private_key(eckey, privkey)) { IBMCAerr(IBMCA_F_IBMCA_EC_KEY_GEN, IBMCA_R_EC_INTERNAL_ERROR); goto end; } ret = 1; end: p_ica_ec_key_free(icakey); EC_POINT_free(pubkey); BN_clear_free(privkey); BN_clear_free(bn_x); BN_clear_free(bn_y); return ret; } /** * ECDSA signing method (replaces ossl_ecdsa_sign). * * returns 1 if success * 0 if error */ int ibmca_ecdsa_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig_array, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) { ECDSA_SIG *sig; const BIGNUM *bn_r, *bn_s; const EC_GROUP *group; int n, r_len, rc; /* Check parms: precomputed (k,r) are not supported by ibmca */ if (kinv != NULL || r != NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN, IBMCA_R_EC_INVALID_PARM); return 0; } /* Create signature */ sig = ibmca_ecdsa_sign_sig(dgst, dlen, NULL, NULL, eckey); if (sig == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN, IBMCA_R_EC_INTERNAL_ERROR); *siglen = 0; return 0; } /* Determine r-length */ if ((group = EC_KEY_get0_group(eckey)) == NULL) { IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN, IBMCA_R_EC_INTERNAL_ERROR); rc = 0; goto ret; } r_len = (EC_GROUP_get_degree(group) + 7) / 8; /* Get (r,s) from ECDSA_SIG */ ECDSA_SIG_get0(sig, &bn_r, &bn_s); /* Format r as byte array with leading 0x00's if necessary */ n = r_len - BN_num_bytes(bn_r); memset(sig_array, 0, n); BN_bn2bin(bn_r, &(sig_array[n])); /* Format s as byte array with leading 0x00's if necessary */ n = r_len - BN_num_bytes(bn_s); memset(&(sig_array[r_len]), 0, n); BN_bn2bin(bn_s, &(sig_array[r_len + n])); /* Create DER encoding */ *siglen = i2d_ECDSA_SIG(sig, &sig_array); rc = 1; ret: ECDSA_SIG_free(sig); return rc; } /** * ECDSA verify method (replaces ossl_ecdsa_verify). Just create an ECDSA_SIG object * from given byte array and call ibmca_ecdsa_verify_sig. * * @return * 1: correct signature * 0: incorrect signature * -1: error */ int ibmca_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) { ECDSA_SIG *s; const unsigned char *p = sigbuf; unsigned char *der = NULL; int derlen = -1; int ret = -1; s = ECDSA_SIG_new(); if (s == NULL) return ret; if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) goto err; /* Ensure signature uses DER and doesn't have trailing garbage */ derlen = i2d_ECDSA_SIG(s, &der); if (derlen != sig_len || memcmp(sigbuf, der, derlen) != 0) goto err; ret = ibmca_ecdsa_verify_sig(dgst, dgst_len, s, eckey); err: OPENSSL_clear_free(der, derlen); ECDSA_SIG_free(s); return ret; } #endif #else /* non-empty compilation unit */ static void *variable = &variable; #endif openssl-ibmca-2.1.0/src/ibmca_pkey.c000066400000000000000000000505441353531367100173230ustar00rootroot00000000000000/* * Copyright [2019] 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 "ibmca.h" #include "e_ibmca_err.h" /* * copied from evp_int.h: * missing set/get methods for opaque types. */ typedef struct { unsigned char pub[57]; unsigned char *priv; } ECX_KEY; typedef struct evp_pkey_method_st { int pkey_id; int flags; int (*init) (EVP_PKEY_CTX *ctx); int (*copy) (EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src); void (*cleanup) (EVP_PKEY_CTX *ctx); int (*paramgen_init) (EVP_PKEY_CTX *ctx); int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); int (*keygen_init) (EVP_PKEY_CTX *ctx); int (*keygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); int (*sign_init) (EVP_PKEY_CTX *ctx); int (*sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); int (*verify_init) (EVP_PKEY_CTX *ctx); int (*verify) (EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen); int (*verify_recover_init) (EVP_PKEY_CTX *ctx); int (*verify_recover) (EVP_PKEY_CTX *ctx, unsigned char *rout, size_t *routlen, const unsigned char *sig, size_t siglen); int (*signctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); int (*signctx) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, EVP_MD_CTX *mctx); int (*verifyctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); int (*verifyctx) (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen, EVP_MD_CTX *mctx); int (*encrypt_init) (EVP_PKEY_CTX *ctx); int (*encrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen); int (*decrypt_init) (EVP_PKEY_CTX *ctx); int (*decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen); int (*derive_init) (EVP_PKEY_CTX *ctx); int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2); int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value); int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen); int (*check) (EVP_PKEY *pkey); int (*public_check) (EVP_PKEY *pkey); int (*param_check) (EVP_PKEY *pkey); int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); } EVP_PKEY_METHOD; ica_x25519_ctx_new_t p_ica_x25519_ctx_new; ica_x448_ctx_new_t p_ica_x448_ctx_new; ica_ed25519_ctx_new_t p_ica_ed25519_ctx_new; ica_ed448_ctx_new_t p_ica_ed448_ctx_new; ica_x25519_key_set_t p_ica_x25519_key_set; ica_x448_key_set_t p_ica_x448_key_set; ica_ed25519_key_set_t p_ica_ed25519_key_set; ica_ed448_key_set_t p_ica_ed448_key_set; ica_x25519_key_get_t p_ica_x25519_key_get; ica_x448_key_get_t p_ica_x448_key_get; ica_ed25519_key_get_t p_ica_ed25519_key_get; ica_ed448_key_get_t p_ica_ed448_key_get; ica_x25519_key_gen_t p_ica_x25519_key_gen; ica_x448_key_gen_t p_ica_x448_key_gen; ica_ed25519_key_gen_t p_ica_ed25519_key_gen; ica_ed448_key_gen_t p_ica_ed448_key_gen; ica_x25519_derive_t p_ica_x25519_derive; ica_x448_derive_t p_ica_x448_derive; ica_ed25519_sign_t p_ica_ed25519_sign; ica_ed448_sign_t p_ica_ed448_sign; ica_ed25519_verify_t p_ica_ed25519_verify; ica_ed448_verify_t p_ica_ed448_verify; ica_x25519_ctx_del_t p_ica_x25519_ctx_del; ica_x448_ctx_del_t p_ica_x448_ctx_del; ica_ed25519_ctx_del_t p_ica_ed25519_ctx_del; ica_ed448_ctx_del_t p_ica_ed448_ctx_del; static EVP_PKEY_METHOD *ibmca_x25519_pmeth = NULL; static EVP_PKEY_METHOD *ibmca_x448_pmeth = NULL; static EVP_PKEY_METHOD *ibmca_ed25519_pmeth = NULL; static EVP_PKEY_METHOD *ibmca_ed448_pmeth = NULL; /* X25519 */ static int ibmca_x25519_keygen(EVP_PKEY_CTX *c, EVP_PKEY *pkey) { unsigned char priv[32], pub[32], *private = NULL; ECX_KEY *key = NULL; ICA_X25519_CTX *ctx = NULL; int rc = 0; if (ica_x25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_KEYGEN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_x25519_key_gen(ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } if (ica_x25519_key_get(ctx, priv, pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } key = calloc(1, sizeof(ECX_KEY)); private = calloc(1, sizeof(priv)); if (key == NULL) { IBMCAerr(IBMCA_F_IBMCA_X25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } memcpy(private, priv, sizeof(priv)); memcpy(key, pub, sizeof(pub)); key->priv = private; EVP_PKEY_assign(pkey, NID_X25519, key); rc = 1; ret: if (rc == 0) { free(key); free(private); } if (ctx != NULL) ica_x25519_ctx_del(&ctx); return rc; } static int ibmca_x25519_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { if (type == EVP_PKEY_CTRL_PEER_KEY) return 1; return -2; } static int ibmca_x25519_derive(EVP_PKEY_CTX *pkey_ctx, unsigned char *key, size_t *keylen) { ICA_X25519_CTX *ctx = NULL; ECX_KEY *key_ecx = NULL, *peerkey_ecx = NULL; EVP_PKEY *key_pkey = NULL, *peerkey_pkey = NULL; int rc = 0; *keylen = 32; if (key == NULL) { rc = 1; goto ret; } key_pkey = EVP_PKEY_CTX_get0_pkey(pkey_ctx); peerkey_pkey = EVP_PKEY_CTX_get0_peerkey(pkey_ctx); if (key_pkey == NULL || peerkey_pkey == NULL) { IBMCAerr(IBMCA_F_IBMCA_X25519_DERIVE, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } key_ecx = EVP_PKEY_get0(key_pkey); peerkey_ecx = EVP_PKEY_get0(peerkey_pkey); if (key_ecx == NULL || peerkey_ecx == NULL) { IBMCAerr(IBMCA_F_IBMCA_X25519_DERIVE, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (ica_x25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_DERIVE, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_x25519_key_set(ctx, key_ecx->priv, NULL) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_DERIVE, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret;; } if (ica_x25519_derive(ctx, key, peerkey_ecx->pub) != 0) goto ret; rc = 1; ret: if (ctx != NULL) ica_x25519_ctx_del(&ctx); return rc; } /* X448 */ static int ibmca_x448_keygen(EVP_PKEY_CTX *c, EVP_PKEY *pkey) { unsigned char priv[56], pub[56], *private = NULL; ECX_KEY *key = NULL; ICA_X448_CTX *ctx = NULL; int rc = 0; if (ica_x448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_KEYGEN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_x448_key_gen(ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } if (ica_x448_key_get(ctx, priv, pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } key = calloc(1, sizeof(ECX_KEY)); private = calloc(1, sizeof(priv)); if (key == NULL) { IBMCAerr(IBMCA_F_IBMCA_X448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } memcpy(private, priv, sizeof(priv)); memcpy(key, pub, sizeof(pub)); key->priv = private; EVP_PKEY_assign(pkey, NID_X448, key); rc = 1; ret: if (rc == 0) { free(key); free(private); } if (ctx != NULL) ica_x448_ctx_del(&ctx); return rc; } static int ibmca_x448_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { if (type == EVP_PKEY_CTRL_PEER_KEY) return 1; return -2; } static int ibmca_x448_derive(EVP_PKEY_CTX *pkey_ctx, unsigned char *key, size_t *keylen) { ICA_X448_CTX *ctx = NULL; ECX_KEY *key_ecx = NULL, *peerkey_ecx = NULL; EVP_PKEY *key_pkey = NULL, *peerkey_pkey = NULL; int rc = 0; *keylen = 56; if (key == NULL) { rc = 1; goto ret; } key_pkey = EVP_PKEY_CTX_get0_pkey(pkey_ctx); peerkey_pkey = EVP_PKEY_CTX_get0_peerkey(pkey_ctx); if (key_pkey == NULL || peerkey_pkey == NULL) { IBMCAerr(IBMCA_F_IBMCA_X448_DERIVE, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } key_ecx = EVP_PKEY_get0(key_pkey); peerkey_ecx = EVP_PKEY_get0(peerkey_pkey); if (key_ecx == NULL || peerkey_ecx == NULL) { IBMCAerr(IBMCA_F_IBMCA_X448_DERIVE, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (ica_x448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_DERIVE, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_x448_key_set(ctx, key_ecx->priv, NULL) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_DERIVE, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret;; } if (ica_x448_derive(ctx, key, peerkey_ecx->pub) != 0) goto ret; rc = 1; ret: if (ctx != NULL) ica_x448_ctx_del(&ctx); return rc; } /* ED25519 */ static int ibmca_ed25519_copy(EVP_PKEY_CTX *to, EVP_PKEY_CTX *from) { return 1; } static int ibmca_ed25519_keygen(EVP_PKEY_CTX *c, EVP_PKEY *pkey) { unsigned char priv[32], pub[32], *private = NULL; ECX_KEY *key = NULL; ICA_ED25519_CTX *ctx = NULL; int rc = 0; if (ica_ed25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_KEYGEN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_ed25519_key_gen(ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } if (ica_ed25519_key_get(ctx, priv, pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } key = calloc(1, sizeof(ECX_KEY)); private = calloc(1, sizeof(priv)); if (key == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } memcpy(private, priv, sizeof(priv)); memcpy(key, pub, sizeof(pub)); key->priv = private; EVP_PKEY_assign(pkey, NID_ED25519, key); rc = 1; ret: if (rc == 0) { free(key); free(private); } if (ctx != NULL) ica_ed25519_ctx_del(&ctx); return rc; } static int ibmca_ed25519_sign(EVP_MD_CTX *md_ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { ICA_ED25519_CTX *ctx = NULL; ECX_KEY *key_ecx = NULL; EVP_PKEY *key_pkey = NULL; int rc = 0; if (sig == NULL) { *siglen = 2 * 32; return 1; } if (*siglen < 2 * 32) goto ret; key_pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(md_ctx)); if (key_pkey == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED25519_SIGN, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } key_ecx = EVP_PKEY_get0(key_pkey); if (key_ecx == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED25519_SIGN, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (ica_ed25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_SIGN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_ed25519_key_set(ctx, key_ecx->priv, NULL) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_SIGN, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret;; } if (ica_ed25519_sign(ctx, sig, tbs, tbslen) != 0) goto ret; *siglen = 2 * 32; rc = 1; ret: if (ctx != NULL) ica_ed25519_ctx_del(&ctx); return rc; } static int ibmca_ed25519_verify(EVP_MD_CTX *md_ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbv, size_t tbvlen) { ICA_ED25519_CTX *ctx = NULL; ECX_KEY *key_ecx = NULL; EVP_PKEY *key_pkey = NULL; int rc = 0; if (sig == NULL || siglen != 2 * 32) goto ret; key_pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(md_ctx)); if (key_pkey == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED25519_VERIFY, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } key_ecx = EVP_PKEY_get0(key_pkey); if (key_ecx == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED25519_VERIFY, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (ica_ed25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_VERIFY, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_ed25519_key_set(ctx, NULL, key_ecx->pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_VERIFY, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (ica_ed25519_verify(ctx, sig, tbv, tbvlen) != 0) goto ret; rc = 1; ret: if (ctx != NULL) ica_ed25519_ctx_del(&ctx); return rc; } /* ED448 */ static int ibmca_ed448_copy(EVP_PKEY_CTX *to, EVP_PKEY_CTX *from) { return 1; } static int ibmca_ed448_keygen(EVP_PKEY_CTX *c, EVP_PKEY *pkey) { unsigned char priv[57], pub[57], *private = NULL; ECX_KEY *key = NULL; ICA_ED448_CTX *ctx = NULL; int rc = 0; if (ica_ed448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_KEYGEN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_ed448_key_gen(ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } if (ica_ed448_key_get(ctx, priv, pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } key = calloc(1, sizeof(ECX_KEY)); private = calloc(1, sizeof(priv)); if (key == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } memcpy(private, priv, sizeof(priv)); memcpy(key, pub, sizeof(pub)); key->priv = private; EVP_PKEY_assign(pkey, NID_ED448, key); rc = 1; ret: if (rc == 0) { free(key); free(private); } if (ctx != NULL) ica_ed448_ctx_del(&ctx); return rc; } static int ibmca_ed448_sign(EVP_MD_CTX *md_ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { ICA_ED448_CTX *ctx = NULL; ECX_KEY *key_ecx = NULL; EVP_PKEY *key_pkey = NULL; int rc = 0; if (sig == NULL) { *siglen = 2 * 57; return 1; } if (*siglen < 2 * 57) goto ret; key_pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(md_ctx)); if (key_pkey == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED448_SIGN, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } key_ecx = EVP_PKEY_get0(key_pkey); if (key_ecx == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED448_SIGN, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (ica_ed448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_SIGN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_ed448_key_set(ctx, key_ecx->priv, NULL) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_SIGN, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret;; } if (ica_ed448_sign(ctx, sig, tbs, tbslen) != 0) goto ret; *siglen = 2 * 57; rc = 1; ret: if (ctx != NULL) ica_ed448_ctx_del(&ctx); return rc; } static int ibmca_ed448_verify(EVP_MD_CTX *md_ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbv, size_t tbvlen) { ICA_ED448_CTX *ctx = NULL; ECX_KEY *key_ecx = NULL; EVP_PKEY *key_pkey = NULL; int rc = 0; if (sig == NULL || siglen != 2 * 57) goto ret; key_pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(md_ctx)); if (key_pkey == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED448_VERIFY, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } key_ecx = EVP_PKEY_get0(key_pkey); if (key_ecx == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED448_VERIFY, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (ica_ed448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_VERIFY, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (ica_ed448_key_set(ctx, NULL, key_ecx->pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_VERIFY, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (ica_ed448_verify(ctx, sig, tbv, tbvlen) != 0) goto ret; rc = 1; ret: if (ctx != NULL) ica_ed448_ctx_del(&ctx); return rc; } /* Methods */ static int ibmca_ed_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { switch (type) { case EVP_PKEY_CTRL_MD: /* Only NULL allowed as digest */ if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null()) return 1; return 0; case EVP_PKEY_CTRL_DIGESTINIT: return 1; } return -2; } const EVP_PKEY_METHOD *ibmca_x25519(void) { if (ibmca_x25519_pmeth != NULL) goto ret; ibmca_x25519_pmeth = EVP_PKEY_meth_new(NID_X25519, 0); if (ibmca_x25519_pmeth == NULL) goto ret; EVP_PKEY_meth_set_ctrl(ibmca_x25519_pmeth, ibmca_x25519_ctrl, NULL); EVP_PKEY_meth_set_keygen(ibmca_x25519_pmeth, NULL, ibmca_x25519_keygen); EVP_PKEY_meth_set_derive(ibmca_x25519_pmeth, NULL, ibmca_x25519_derive); ret: return ibmca_x25519_pmeth; } const EVP_PKEY_METHOD *ibmca_x448(void) { if (ibmca_x448_pmeth != NULL) goto ret; ibmca_x448_pmeth = EVP_PKEY_meth_new(NID_X448, 0); if (ibmca_x448_pmeth == NULL) goto ret; EVP_PKEY_meth_set_ctrl(ibmca_x448_pmeth, ibmca_x448_ctrl, NULL); EVP_PKEY_meth_set_keygen(ibmca_x448_pmeth, NULL, ibmca_x448_keygen); EVP_PKEY_meth_set_derive(ibmca_x448_pmeth, NULL, ibmca_x448_derive); ret: return ibmca_x448_pmeth; } const EVP_PKEY_METHOD *ibmca_ed25519(void) { if (ibmca_ed25519_pmeth != NULL) goto ret; ibmca_ed25519_pmeth = EVP_PKEY_meth_new(NID_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM); if (ibmca_ed25519_pmeth == NULL) goto ret; EVP_PKEY_meth_set_ctrl(ibmca_ed25519_pmeth, ibmca_ed_ctrl, NULL); EVP_PKEY_meth_set_copy(ibmca_ed25519_pmeth, ibmca_ed25519_copy); EVP_PKEY_meth_set_keygen(ibmca_ed25519_pmeth, NULL, ibmca_ed25519_keygen); ibmca_ed25519_pmeth->digestsign = ibmca_ed25519_sign; ibmca_ed25519_pmeth->digestverify = ibmca_ed25519_verify; ret: return ibmca_ed25519_pmeth; } const EVP_PKEY_METHOD *ibmca_ed448(void) { if (ibmca_ed448_pmeth != NULL) goto ret; ibmca_ed448_pmeth = EVP_PKEY_meth_new(NID_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM); if (ibmca_ed448_pmeth == NULL) goto ret; EVP_PKEY_meth_set_ctrl(ibmca_ed448_pmeth, ibmca_ed_ctrl, NULL); EVP_PKEY_meth_set_copy(ibmca_ed448_pmeth, ibmca_ed448_copy); EVP_PKEY_meth_set_keygen(ibmca_ed448_pmeth, NULL, ibmca_ed448_keygen); ibmca_ed448_pmeth->digestsign = ibmca_ed448_sign; ibmca_ed448_pmeth->digestverify = ibmca_ed448_verify; ret: return ibmca_ed448_pmeth; } void ibmca_x25519_destroy(void) { if (ibmca_x25519_pmeth != NULL) { EVP_PKEY_meth_free(ibmca_x25519_pmeth); ibmca_x25519_pmeth = NULL; } } void ibmca_x448_destroy(void) { if (ibmca_x448_pmeth != NULL) { EVP_PKEY_meth_free(ibmca_x448_pmeth); ibmca_x448_pmeth = NULL; } } void ibmca_ed25519_destroy(void) { if (ibmca_ed25519_pmeth != NULL) { EVP_PKEY_meth_free(ibmca_ed25519_pmeth); ibmca_ed25519_pmeth = NULL; } } void ibmca_ed448_destroy(void) { if (ibmca_ed448_pmeth != NULL) { EVP_PKEY_meth_free(ibmca_ed448_pmeth); ibmca_ed448_pmeth = NULL; } } openssl-ibmca-2.1.0/src/ibmca_rsa.c000066400000000000000000000271631353531367100171410ustar00rootroot00000000000000/* * Copyright [2005-2018] 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 "ibmca.h" #include "e_ibmca_err.h" /* * Define compat functions for older OpenSSL versions */ #ifdef OLDER_OPENSSL void RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { if (n != NULL) *n = rsa->n; if (e != NULL) *e = rsa->e; if (d != NULL) *d = rsa->d; } void RSA_get0_factors(const RSA *rsa, const BIGNUM **p, const BIGNUM **q) { if (p != NULL) *p = rsa->p; if (q != NULL) *q = rsa->q; } void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp) { if (dmp1 != NULL) *dmp1 = rsa->dmp1; if (dmq1 != NULL) *dmq1 = rsa->dmq1; if (iqmp != NULL) *iqmp = rsa->iqmp; } #endif 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; /* * 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_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; } static int ibmca_rsa_init(RSA * rsa) { RSA_blinding_off(rsa); return 1; } 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; } /* 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); } #ifdef OLDER_OPENSSL static RSA_METHOD rsa_m = { "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 */ RSA_FLAG_FIPS_METHOD, /* flags */ NULL, /* app_data */ NULL, /* rsa_sign */ NULL, /* rsa_verify */ NULL /* rsa_keygen */ }; RSA_METHOD *ibmca_rsa(void) { /* 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! */ const RSA_METHOD *meth1 = RSA_PKCS1_SSLeay(); rsa_m.rsa_pub_enc = meth1->rsa_pub_enc; rsa_m.rsa_pub_dec = meth1->rsa_pub_dec; rsa_m.rsa_priv_enc = meth1->rsa_priv_enc; rsa_m.rsa_priv_dec = meth1->rsa_priv_dec; return &rsa_m; } #else static RSA_METHOD *rsa_m = NULL; RSA_METHOD *ibmca_rsa(void) { const RSA_METHOD *meth1; RSA_METHOD *method; if (rsa_m != NULL) goto done; if ((method = RSA_meth_new("Ibmca RSA method", 0)) == NULL || (meth1 = RSA_PKCS1_OpenSSL()) == NULL || !RSA_meth_set_pub_enc(method, RSA_meth_get_pub_enc(meth1)) || !RSA_meth_set_pub_dec(method, RSA_meth_get_pub_dec(meth1)) || !RSA_meth_set_priv_enc(method, RSA_meth_get_priv_enc(meth1)) || !RSA_meth_set_priv_dec(method, RSA_meth_get_priv_dec(meth1)) || !RSA_meth_set_mod_exp(method, ibmca_rsa_mod_exp) || !RSA_meth_set_bn_mod_exp(method, ibmca_mod_exp_mont) || !RSA_meth_set_init(method, ibmca_rsa_init) || !RSA_meth_set_flags(method, RSA_FLAG_FIPS_METHOD)) { RSA_meth_free(method); method = NULL; meth1 = NULL; } rsa_m = method; done: return rsa_m; } void ibmca_rsa_destroy(void) { RSA_meth_free(rsa_m); } #endif #endif /* endif OPENSSL_NO_RSA */ openssl-ibmca-2.1.0/src/openssl.cnf.sample000066400000000000000000000033431353531367100205020ustar00rootroot00000000000000# # 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 # # ECDSA (OpenSSL < 1.1.0) # - Elliptic Curve DSA sign and verify # # ECDH (OpenSSL < 1.1.0) # - Elliptic Curve DH key exchange # # EC (OpenSSL >= 1.1.0) # - Elliptic Curve DSA sign and verify, Elliptic Curve DH key exchange # # 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 # # PKEY_CRYPTO # - X25519, X448, ED25519, ED448 default_algorithms = ALL #default_algorithms = PKEY_CRYPTO,RAND,RSA,DH,DSA,CIPHERS,DIGESTS openssl-ibmca-2.1.0/src/test/000077500000000000000000000000001353531367100160235ustar00rootroot00000000000000openssl-ibmca-2.1.0/src/test/Makefile.linux000066400000000000000000000004701353531367100206220ustar00rootroot00000000000000PTS = -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) -o $@ $^ -lica -lcrypto clean: rm -f $(TARGETS) openssl-ibmca-2.1.0/src/test/ibmca_mechaList_test.c000066400000000000000000000262761353531367100223070ustar00rootroot00000000000000/* * Copyright [2015-2018] 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; } 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 < mech_len; j++) { if (ica_to_ssl_map[i].ica_id == pmech_list[j].mech_mode_id) { found = true; check_mech(i, j, pmech_list); break; } } assert(found); found = false; } for (i = 0; i < mech_len; i++) { if (pmech_list[i].mech_mode_id == P_RNG) { if (pmech_list[i].flags & (ICA_FLAG_SHW)) { if (!ENGINE_get_default_RAND()) { failure++; fprintf(stderr, "ERROR: Engine has no enabled PRNG support!\n"); } else { printf("PRNG Support found! SUCCESS\n"); } } else { if (ENGINE_get_default_RAND()) { failure++; fprintf(stderr, "ERROR: Engine has enabled PRNG support" ", despite no hardware support!\n"); } else { printf("PRNG Support not found! SUCCESS\n"); } } } if (pmech_list[i].mech_mode_id == RSA_ME) { if (card_loaded) { if (!ENGINE_get_default_RSA()) { failure++; fprintf(stderr, "ERROR: Engine has no enabeled RSA support!\n"); } else { printf("RSA Support found! SUCCESS\n"); } if (!ENGINE_get_default_DSA()) { failure++; fprintf(stderr, "ERROR: Engine has no enabled DSA support!\n"); } else { printf("DSA Support found! SUCCESS\n"); } if (!ENGINE_get_default_DH()) { failure++; fprintf(stderr, "ERROR: Engine has no enabled DH support!\n"); } else { printf("DH Support found! SUCCESS\n"); } } else { if (ENGINE_get_default_RSA()) { failure++; fprintf(stderr, "ERROR: Engine has enabled RSA support," "despite no hardware support!\n"); } else { printf("RSA Support not found! SUCCESS\n"); } if (ENGINE_get_default_DSA()) { failure++; fprintf(stderr, "ERROR: Engine has no enabled DSA support," "despite no hardware support!\n"); } else { printf("DSA Support not found! SUCCESS\n"); } if (ENGINE_get_default_DH()) { failure++; fprintf(stderr, "ERROR: Engine has no enabled DH support," "despite no hardware support!\n"); } else { printf("DH Support not found! SUCCESS\n"); } } } } printf("\n\n-----------------------------------------------------------\n"); printf("TEST Summary:\n" "Failure Counter: %d\n", failure); if (failure) return EXIT_FAILURE; return EXIT_SUCCESS; } openssl-ibmca-2.1.0/test/000077500000000000000000000000001353531367100152345ustar00rootroot00000000000000openssl-ibmca-2.1.0/test/3des-cbc-test.pl000077500000000000000000000001371353531367100201350ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ede3-cbc", 24, 8); openssl-ibmca-2.1.0/test/3des-cfb-test.pl000077500000000000000000000001371353531367100201400ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ede3-cfb", 24, 8); openssl-ibmca-2.1.0/test/3des-ecb-test.pl000077500000000000000000000001331353531367100201330ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ede3", 24, 0); openssl-ibmca-2.1.0/test/3des-ofb-test.pl000077500000000000000000000001371353531367100201540ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ede3-ofb", 24, 8); openssl-ibmca-2.1.0/test/Makefile.am000066400000000000000000000011541353531367100172710ustar00rootroot00000000000000TESTS = \ des-ecb-test.pl \ des-cbc-test.pl \ des-cfb-test.pl \ des-ofb-test.pl \ 3des-ecb-test.pl \ 3des-cbc-test.pl \ 3des-cfb-test.pl \ 3des-ofb-test.pl \ aes-128-ecb-test.pl \ aes-128-cbc-test.pl \ aes-128-cfb-test.pl \ aes-128-ofb-test.pl \ aes-192-ecb-test.pl \ aes-192-cbc-test.pl \ aes-192-cfb-test.pl \ aes-192-ofb-test.pl \ aes-256-ecb-test.pl \ aes-256-cbc-test.pl \ aes-256-cfb-test.pl \ aes-256-ofb-test.pl AM_TESTS_ENVIRONMENT = export IBMCA_TEST_PATH=${top_builddir}/src/.libs/ibmca.so IBMCA_OPENSSL_TEST_CONF=${srcdir}/openssl-test.cnf PERL5LIB=${srcdir}; EXTRA_DIST = ${TESTS} test.pm openssl-test.cnf openssl-ibmca-2.1.0/test/aes-128-cbc-test.pl000077500000000000000000000001371353531367100203570ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-128-cbc", 16, 16); openssl-ibmca-2.1.0/test/aes-128-cfb-test.pl000077500000000000000000000001371353531367100203620ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-128-cfb", 16, 16); openssl-ibmca-2.1.0/test/aes-128-ecb-test.pl000077500000000000000000000001361353531367100203600ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-128-ecb", 16, 0); openssl-ibmca-2.1.0/test/aes-128-ofb-test.pl000077500000000000000000000001371353531367100203760ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-128-ofb", 16, 16); openssl-ibmca-2.1.0/test/aes-192-cbc-test.pl000077500000000000000000000001371353531367100203600ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-192-cbc", 24, 16); openssl-ibmca-2.1.0/test/aes-192-cfb-test.pl000077500000000000000000000001371353531367100203630ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-192-cfb", 24, 16); openssl-ibmca-2.1.0/test/aes-192-ecb-test.pl000077500000000000000000000001361353531367100203610ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-192-ecb", 24, 0); openssl-ibmca-2.1.0/test/aes-192-ofb-test.pl000077500000000000000000000001371353531367100203770ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-192-ofb", 24, 16); openssl-ibmca-2.1.0/test/aes-256-cbc-test.pl000077500000000000000000000001371353531367100203610ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-256-cbc", 32, 16); openssl-ibmca-2.1.0/test/aes-256-cfb-test.pl000077500000000000000000000001371353531367100203640ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-256-cfb", 32, 16); openssl-ibmca-2.1.0/test/aes-256-ecb-test.pl000077500000000000000000000001361353531367100203620ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-256-ecb", 32, 0); openssl-ibmca-2.1.0/test/aes-256-ofb-test.pl000077500000000000000000000001371353531367100204000ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-256-ofb", 32, 16); openssl-ibmca-2.1.0/test/des-cbc-test.pl000077500000000000000000000001311353531367100200440ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-cbc", 8, 8); openssl-ibmca-2.1.0/test/des-cfb-test.pl000077500000000000000000000001311353531367100200470ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-cfb", 8, 8); openssl-ibmca-2.1.0/test/des-ecb-test.pl000077500000000000000000000001311353531367100200460ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ecb", 8, 0); openssl-ibmca-2.1.0/test/des-ofb-test.pl000077500000000000000000000001311353531367100200630ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ofb", 8, 8); openssl-ibmca-2.1.0/test/openssl-test.cnf000066400000000000000000000006541353531367100203710ustar00rootroot00000000000000openssl_conf = openssl_def [openssl_def] engines = engine_section [engine_section] ibmca = ibmca_section [ibmca_section] dynamic_path = $ENV::IBMCA_TEST_PATH engine_id = ibmca init = 1 # OpenSSL < 1.1.0 # ALL = RSA,DSA,DH,RAND,CIPHERS,DIGESTS,PKEY,ECDH,ECDSA # PKEY = PKEY_CRYPTO,PKEY_ASN1 # OpenSSL >= 1.1.0 # ALL = RSA,DSA,DH,RAND,CIPHERS,DIGESTS,PKEY,EC # PKEY = PKEY_CRYPTO,PKEY_ASN1 default_algorithms = ALL openssl-ibmca-2.1.0/test/test.pm000066400000000000000000000021101353531367100165430ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; package test; sub cipher { my $tests = 50; my $max_file_size = 1024; my $eng = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF}"; my @hex = ("a".."f", "0".."9"); my ($cipher,$keylen,$ivlen) = @_; # skip if engine not loaded exit(77) unless (`$eng openssl engine -c` =~ m/ibmca/); for my $i (1..$tests) { my $bytes = 1 + int(rand($max_file_size)); my $key = ""; $key .= $hex[rand(@hex)] for (1..$keylen); my $iv = ""; if ($ivlen > 0) { $iv .= $hex[rand(@hex)] for (1..$ivlen); $iv = "-iv $iv"; } # engine enc, no-engine dec `openssl rand $bytes > data.in`; `$eng openssl $cipher -e -K $key $iv -in data.in -out data.enc`; `openssl $cipher -d -K $key $iv -in data.enc -out data.dec`; `cmp data.in data.dec`; exit(1) if ($?); # no-engine enc, engine dec `openssl rand $bytes > data.in`; `openssl $cipher -e -K $key $iv -in data.in -out data.enc`; `$eng openssl $cipher -d -K $key $iv -in data.enc -out data.dec`; `cmp data.in data.dec`; exit(1) if ($?); } `rm -f data.in data.enc data.dec`; } 1;