pax_global_header00006660000000000000000000000064145027640730014522gustar00rootroot0000000000000052 comment=727304ae0190dada506fb4f36fd277ac56f396e1 openssl-ibmca-2.4.1/000077500000000000000000000000001450276407300142625ustar00rootroot00000000000000openssl-ibmca-2.4.1/.gitignore000066400000000000000000000003111450276407300162450ustar00rootroot00000000000000build-aux autom4te.cache .deps .libs *.m4 *.lo *.la *.o *.tar.gz ibmca-engine-opensslconfig ibmca_mechaList_test Makefile Makefile.in Makefile.linux config.status config.log configure libtool cscope.* openssl-ibmca-2.4.1/.travis.yml000066400000000000000000000021741450276407300163770ustar00rootroot00000000000000os: linux dist: focal language: c before_install: - sudo apt-get -qq update - sudo apt-get install -y libica3 libica-dev jobs: include: - name: "linux-s390x-gcc" os: linux arch: s390x compiler: gcc env: CONFIG_OPTS="--enable-engine --enable-provider" before_script: - git clone https://github.com/openssl/openssl.git - pushd openssl - git checkout master - ./config -w - make -j 5 -s - export OPENSSL_DIR=$PWD - export PATH=$OPENSSL_DIR/apps/:$PATH - export LD_LIBRARY_PATH=$OPENSSL_DIR/:$LD_LIBRARY_PATH - popd - openssl version - git clone https://github.com/opencryptoki/libica.git - pushd libica - ./bootstrap.sh - ./configure CFLAGS="-I$OPENSSL_DIR/include -L$OPENSSL_DIR" - make -j 5 V=0 - export LIBICA_DIR=$PWD - export LD_LIBRARY_PATH=$LIBICA_DIR/src/.libs:$LD_LIBRARY_PATH - popd - $LIBICA_DIR/src/icainfo script: - ./bootstrap.sh - ./configure CFLAGS="-I$OPENSSL_DIR/include -L$OPENSSL_DIR -I$LIBICA_DIR/include -L$LIBICA_DIR/src/.libs" $CONFIG_OPTS - make -j 5 V=0 - make check V=0 openssl-ibmca-2.4.1/AUTHORS000066400000000000000000000000441450276407300153300ustar00rootroot00000000000000Mike Halcrow openssl-ibmca-2.4.1/CONTRIBUTING.md000066400000000000000000000052271450276407300165210ustar00rootroot00000000000000# 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.4.1/ChangeLog000066400000000000000000000064511450276407300160420ustar00rootroot00000000000000* openssl-ibmca 2.4.1 - Provider: Change the default log directory to /tmp - Bug fixes * openssl-ibmca 2.4.0 - Provider: Adjustments for OpenSSL versions 3.1 and 3.2 - Provider: Support RSA blinding - Provider: Constant-time fixes for RSA PKCS#1 v1.5 and OAEP padding - Provider: Support "implicit rejection" option for RSA PKCS#1 v1.5 padding - Provider: Adjustments in OpenSSL config generator and example configs - Engine: EC: Cache ICA key in EC_KEY object (performance improvement) - Engine: Enable RSA blinding * openssl-ibmca 2.3.1 - Adjustments for libica 4.1.0 * openssl-ibmca 2.3.0 - First version including the provider - Fix for engine build without OpenSSL 3.0 sources * openssl-ibmca 2.2.3 - Fix PKEY segfault with OpenSSL 3.0 * openssl-ibmca 2.2.2 - Fix tests with OpenSSL 3.0 - Build against libica 4.0 * openssl-ibmca 2.2.1 - Bug fixes * openssl-ibmca 2.2.0 - Implement fallbacks based on OpenSSL - Disable software fallbacks from libica - Allow to specify default library (libica vs. libica-cex) to use - Provide "libica" engine ctrl to switch library at load time - Update README.md - Remove libica link dependency - Generate sample configuration files from system configuration - Restructure registration global data * openssl-ibmca 2.1.3 - Bug fix * openssl-ibmca 2.1.2 - Bug fixes * openssl-ibmca 2.1.1 - Bug fixes * 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.4.1/LICENSE000066400000000000000000000220311450276407300152650ustar00rootroot00000000000000Apache 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.4.1/Makefile.am000066400000000000000000000002001450276407300163060ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src test EXTRA_DIST = openssl-ibmca.spec openssl-ibmca-provider.spec bootstrap.sh cleanup.sh openssl-ibmca-2.4.1/README.md000066400000000000000000000157761450276407300155610ustar00rootroot00000000000000# OpenSSL-ibmca OpenSSL engine and provider that uses the libica library under s390x to accelerate cryptographic operations. ## Requirements The build requirements are: * openssl-devel >= 0.9.8 * openssl-devel >= 3.0.0 for building the IBMCA provider * libica-devel >= 3.3.0 * libica-devel >= 3.6.0 or >= 4.0.1 for building the IBMCA provider * autoconf * automake * libtool * openssl * perl The runtime requirements are: * openssl >= 0.9.8 * openssl-devel >= 3.0.0 for using the IBMCA provider * libica >= 3.3.0 * libica >= 3.6.0 or >= 4.0.1 for using the IBMCA provider ## Installing ``` $ ./configure [--enable-debug] [--disable-engine] [--disable-provider] $ 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 engine ibmca.so and the provider ibmca-provider.so will be installed in `/usr/local/lib/` by default. If you want to install it anywhere else, run "configure" passing the new location via prefix argument, for example: ``` $ ./configure --prefix=/usr --disable-provider --libdir=/usr/lib64/openssl/engines ``` or ``` $ ./configure --prefix=/usr --disable-engine --libdir=/usr/lib64/ossl-modules ``` Additionally, at configure time, you can specify to build the engine against the libica-cex version via the `--with-libica-cex` feature switch. If this switch is not specified, the engine will use the full version of libica by default. To specify the version of libica for the engine, use `--with-libica-version=`. The default version is version 4 of libica. To build the engine against version 3 of libica, specify `--with-libica-version=3` at configure time. The provider uses the libica-cex version of libica by default. To build the provider against the full version of libica specify the `--with-provider-libica-full` feature switch. There is no functional difference when the provider is built against the full version of libica. The provider requires libica version 4, it can not be built with an older libica version. The provider requires OpenSSL 3.0 or later to be built. If OpenSSL 3.0 is not availale, then the provider is automatically disabled. When OpenSSL 3.0 is available, by default both, the engine as well as the provider are built. You can disable the engine or the provider with the `----disable-engine` or `----disable-provider` switch. There are 2 RPM spec files contained in this package: `openssl-ibmca.spec` and `openssl-ibmca-provider.spec`. The first one builds only the engine and installs it into OpenSSL's engine directory. The second one builds only the provider and install it into OpenSSL's modules directory. We leave it to the distributions to produce an RPM that contains both, engine and provider, if wanted. You can only specify one installation directory with the `--libdir` configure option, but providers and engines need to be installed into different locations. To achieve this, the engine and provider shared objects must be moved by subsequent commands to the correct location after `make install` has been performed. ## Enabling IBMCA Apps with compiled-in OpenSSL config support can enable the engine or provider via an OpenSSL configuration file. Refer to config(5). Sample OpenSSL configuration files (`openssl.cnf.sample` and `openssl.cnf.provider.sample`) are 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] $ ``` If the provider is configured properly, the command below should return the IBMCA provider. ``` $ openssl list -providers Providers: default name: OpenSSL Default Provider version: 3.1.0 status: active ibmca name: ibmca version: 1.1.0 status: active $ ``` You can list the cryptographic methods implemented by the activated providers as follows: ``` $ openssl list -key-managers ... Name: IBMCA RSA implementation Type: Provider Algorithm IDs: { 1.2.840.113549.1.1.1, 2.5.8.1.1, RSA, rsaEncryption } @ ibmca Name: IBMCA DH implementation Type: Provider Algorithm IDs: { 1.2.840.113549.1.3.1, DH, dhKeyAgreement } @ ibmca Name: IBMCA EC implementation Type: Provider Algorithm IDs: { 1.2.840.10045.2.1, EC, id-ecPublicKey } @ ibmca Name: IBMCA RSA-PSS implementation Type: Provider Algorithm IDs: { 1.2.840.113549.1.1.10, RSA-PSS, RSASSA-PSS, rsassaPss } @ ibmca Name: IBMCA DHX implementation Type: Provider Algorithm IDs: { 1.2.840.10046.2.1, dhpublicnumber, DHX, X9.42 DH } @ ibmca ... $ openssl list -signature-algorithms ... { 1.2.840.113549.1.1.1, 2.5.8.1.1, RSA, rsaEncryption } @ ibmca ECDSA @ ibmca ... $ openssl list -asymcipher-algorithms ... { 1.2.840.113549.1.1.1, 2.5.8.1.1, RSA, rsaEncryption } @ ibmca ... $ openssl list -key-exchange-algorithms ... { 1.2.840.113549.1.3.1, DH, dhKeyAgreement } @ ibmca ECDH @ ibmca .... $ ``` ## Configuring OpenSSL-ibmca Since libica 3.8.0, libica provides two libraries. The basic libica.so.3 contains all the features listed above and is the default library unless the `configure` switch `--with-libica-cex` is provided. In that case, libica-cex.so.4 becomes the default library. If both versions of the library are installed on a system, OpenSSL-ibmca can be configured to use either of these two. To use `libica.so.4`, with OpenSSL-ibmca, simply add the directive `libica = libica.so.4` to your OpenSSL configuration file in the engine section before `init = 1`. Similarly, to use `libica-cex.so.4`, add the line `libica = libica-cex.so.4`. The build process of OpenSSL-ibmca will produce the scripts `ibmca-engine-opensslconfig` and `ibmca-provider-opensslconfig` which can be used to update an existing OpenSSL configuration to enable the OpenSSL-ibmca engine or provider. By default, these scripts are not installed. We leave it to the distributions to find the correct place for these scripts (or not use them at all). ## 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 * OpenSSL package version * steps to reproduce the bug Regarding technical or usage questions, also submit a [ticket](https://github.com/opencryptoki/openssl-ibmca/issues). ## Limitations The ibmca engine's cipher and digest implementations do not support the processing of messages in arbitrary chunk sizes. All chunks, except the final one, are required to be a multiple of the primitive's block size. ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md). openssl-ibmca-2.4.1/bootstrap.sh000077500000000000000000000012451450276407300166400ustar00rootroot00000000000000#!/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 --force --install --verbose --warnings=all openssl-ibmca-2.4.1/cleanup.sh000077500000000000000000000016021450276407300162470ustar00rootroot00000000000000#!/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.4.1/configure.ac000066400000000000000000000126321450276407300165540ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # See autoconf and autoscan online documentation for details. AC_INIT([openssl-ibmca], [2.4.1], [https://github.com/opencryptoki/openssl-ibmca/issues],[],[https://github.com/opencryptoki/openssl-ibmca]) AC_CONFIG_SRCDIR([src/engine/e_ibmca.c]) # sanity check AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign]) AC_PATH_PROG([CHMOD], [chmod], [/bin/chmod]) logdir=/tmp AC_SUBST(logdir) # 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 AC_ARG_ENABLE([engine], [AS_HELP_STRING([--enable-engine], [build IBMCA engine (OpenSSL 1.1.1, default is yes)])], [if test "x$enableval" = "xyes" ; then enable_engine="yes" else enable_engine="no" fi], [enable_engine="yes"]) AC_ARG_ENABLE([provider], [AS_HELP_STRING([--enable-provider], [build IBMCA provider (OpenSSL >= 3.0, default is yes if built against OpenSSL 3.0 or later, else the default is false)])], [if test "x$enableval" = "xyes" ; then enable_provider="yes" else enable_provider="no" fi], [enable_provider="check"]) # Checks for programs. AC_DISABLE_STATIC AC_PROG_CC LT_INIT dnl --- check for perl AC_PATH_PROG(PERL, perl) if test -z "$PERL" ; then AC_MSG_ERROR([Please install perl]) fi AC_MSG_CHECKING([if perl module 'FindBin' is installed]) (echo "use FindBin;" ; echo "exit(0);") | $PERL > /dev/null 2>&1 if test $? != 0 ; then AC_MSG_RESULT(no) AC_MSG_ERROR([Please install perl-FindBin]) fi AC_MSG_RESULT(yes) # Checks for libraries. AC_CHECK_LIB([crypto], [RAND_add], [], AC_MSG_ERROR([*** openssl >= 1.1.1 is required ***])) AC_CHECK_LIB([crypto], [OSSL_LIB_CTX_new], [openssl_3_0="yes"], [openssl_3_0="no"]) # 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.6.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,DES_ECB], [], AC_MSG_ERROR([*** libica-devel >= 3.6.0 are required ***]), [#include ]) AC_CHECK_DECLS([OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION], [openssl_implicit_rejection="yes"], [openssl_implicit_rejection="no"], [#include ]) AM_CONDITIONAL([OPENSSL_IMPLICIT_REJECTION], [test "x$openssl_implicit_rejection" = xyes]) AC_ARG_WITH([libica-cex], [AS_HELP_STRING([--with-libica-cex],[Use libica-cex as default library for the IBMCA engine])], [usecexonly=${withval}], []) AC_ARG_WITH([libica-version], [AS_HELP_STRING([--with-libica-version],[Use specified libica major version (defaults to 4)])], [libicaversion=${withval}], [libicaversion=4]) if test "x$usecexonly" = xyes; then defaultlib="libica-cex.so.$libicaversion" ica="ica-cex" else defaultlib="libica.so.$libicaversion" ica="ica" fi # In cex-only mode, testing the ciphers does not make any sense since # they will fall back to OpenSSL without the engine. So remove these # tests from that build. AM_CONDITIONAL([FULL_LIBICA], [test "x$usecexonly" != xyes]) AC_ARG_WITH([provider-libica-full], [AS_HELP_STRING([--with-provider-libica-full],[Use the full libica as library for the IBMCA provider])], [useproviderfulllibica=${withval}], []) AM_CONDITIONAL([PROVIDER_FULL_LIBICA], [test "x$useproviderfulllibica" = xyes]) # If compiled against OpenSSL 3.0 or later, build the provider unless # explicitely disabled. # If build against OpenSSL 1.1.1, we can not build the provider. if test "x$openssl_3_0" = xyes; then if test "x$enable_provider" != xno; then enable_provider=yes fi else if test "x$enable_provider" = xyes; then AC_MSG_ERROR([*** openssl >= 3.0 is required to build the IBMCA provider ***]); fi enable_provider=no fi AM_CONDITIONAL([IBMCA_ENGINE], [test "x$enable_engine" == xyes]) AM_CONDITIONAL([IBMCA_PROVIDER], [test "x$enable_provider" == xyes]) AC_DEFINE_UNQUOTED([LIBICA_SHARED_LIB],["$defaultlib"]) AC_SUBST([ICA],["$ica"]) AC_CHECK_PROG([openssl_var],[openssl],[yes],[no]) if test "x$openssl_var" != xyes; then AC_MSG_ERROR([openssl binary required]); fi if test "x$enable_provider" = xyes; then AC_CHECK_DECLS([ica_fips_status], [], AC_MSG_ERROR([*** libica >= 4.0 is required to build the IBMCA provider ***]), [#include ]) fi AC_CHECK_DECLS([ica_cleanup],,,[#include ]) AC_CONFIG_FILES([ Makefile src/Makefile src/engine/Makefile src/engine/test/Makefile.linux src/engine/doc/Makefile src/provider/Makefile src/provider/doc/Makefile test/Makefile test/engine/Makefile test/provider/Makefile]) AC_OUTPUT echo "CFLAGS=$CFLAGS" echo "IBMCA engine: $enable_engine" echo " default library: $defaultlib" echo "IBMCA provider: $enable_provider" if test "x$useproviderfulllibica" = xyes; then echo " libica library: libica" else echo " libica library: libica-cex" fi openssl-ibmca-2.4.1/docs/000077500000000000000000000000001450276407300152125ustar00rootroot00000000000000openssl-ibmca-2.4.1/docs/coding_style.md000066400000000000000000000074201450276407300202220ustar00rootroot00000000000000# 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.4.1/m4/000077500000000000000000000000001450276407300146025ustar00rootroot00000000000000openssl-ibmca-2.4.1/m4/.dont_remove000066400000000000000000000002221450276407300171200ustar00rootroot00000000000000REQUIRED 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.4.1/openssl-ibmca-provider.spec000066400000000000000000000075311450276407300215300ustar00rootroot00000000000000%global modulesdir %(openssl version -m | grep -o '".*"' | tr -d '"') # Above can be replaced by the following once OpenSSL commit # https://github.com/openssl/openssl/commit/7fde39de848f062d6db45bf9e69439db2100b9bb # has been included into the distribution: # %global modulesdir %(pkg-config --variable=modulesdir libcrypto) Name: openssl-ibmca Version: 2.4.1 Release: 1%{?dist} Summary: An IBMCA OpenSSL dynamic provider 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 >= 3.0.0 libica >= 4.0.1 BuildRequires: openssl-devel >= 3.0.0 libica-devel >= 4.0.1 openssl >= 3.0.0 BuildRequires: autoconf automake libtool perl ExclusiveArch: s390 s390x %description This package contains a shared object OpenSSL dynamic provider which interfaces to libica-cex, a library enabling the IBM s390x crypto instructions. %prep %setup -q -n %{name}-%{version} ./bootstrap.sh %build %configure --libdir=%{modulesdir} --disable-engine --enable-provider %make_build %install %make_install rm -f $RPM_BUILD_ROOT%{modulesdir}/ibmca-provider.la mv -f src/provider/openssl.cnf.sample src/provider/openssl.cnf.sample.%{_arch} %files %license LICENSE %doc ChangeLog README.md src/provider/openssl.cnf.sample.%{_arch} src/provider/ibmca-provider-opensslconfig %{modulesdir}/ibmca-provider.so %{_mandir}/man5/ibmca-provider.5* %dir %attr(777,root,root) %{_localstatedir}/log/ibmca %changelog * Thu Mar 30 2023 Ingo Franzki 2.4.0 - Update Version * Fri Sep 30 2022 Juergen Christ 2.3.1 - Adjust to libica 4.1.0 * Fri Mar 25 2022 Juergen Christ 2.3.0 - First version including the provider - Fix for engine build without OpenSSL 3.0 sources * Wed March 3 2022 Ingo Franzki - Add provider support * Thu Mar 10 2022 Juergen Christ 2.2.3 - Update Version * Thu Jan 27 2022 Juergen Christ 2.2.2 - Update Version * Mon Sep 13 2021 Juergen Christ 2.2.1 - Update Version * Wed May 19 2021 Juergen Christ 2.2.0 - Update Version * Wed May 19 2021 Juergen Christ 2.1.3 - Update Version * Wed Apr 28 2021 Juergen Christ 2.1.2 - Update Version * Tue May 05 2020 Patrick Steuer 2.1.1 - Update Version * 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.4.1/openssl-ibmca.spec000066400000000000000000000067121450276407300177000ustar00rootroot00000000000000%global enginesdir %(pkg-config --variable=enginesdir libcrypto) Name: openssl-ibmca Version: 2.4.1 Release: 1%{?dist} Summary: An IBMCA OpenSSL dynamic engine License: ASL 2.0 URL: https://github.com/opencryptoki/openssl-ibmca Source0: https://github.com/opencryptoki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz Requires: openssl >= 1.1.1 libica >= 3.6.0 BuildRequires: openssl-devel >= 1.1.1 libica-devel >= 3.6.0 openssl >= 1.1.1 BuildRequires: autoconf automake libtool perl 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} --disable-provider %make_build %install %make_install rm -f $RPM_BUILD_ROOT%{enginesdir}/ibmca.la pushd src/engine 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/engine/openssl.cnf.sample.%{_arch} src/engine/ibmca-engine-opensslconfig %{enginesdir}/ibmca.so %{_mandir}/man5/ibmca.5* %changelog * Thu Mar 30 2023 Ingo Franzki 2.4.0 - Update Version * Fri Sep 30 2022 Juergen Christ 2.3.1 - Adjust to libica 4.1.0 * Fri Mar 25 2022 Juergen Christ 2.3.0 - First version including the provider - Fix for engine build without OpenSSL 3.0 sources * Thu Mar 10 2022 Juergen Christ 2.2.3 - Update Version * Thu Jan 27 2022 Juergen Christ 2.2.2 - Update Version * Mon Sep 13 2021 Juergen Christ 2.2.1 - Update Version * Wed May 19 2021 Juergen Christ 2.2.0 - Update Version * Wed May 19 2021 Juergen Christ 2.1.3 - Update Version * Wed Apr 28 2021 Juergen Christ 2.1.2 - Update Version * Tue May 05 2020 Patrick Steuer 2.1.1 - Update Version * 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.4.1/src/000077500000000000000000000000001450276407300150515ustar00rootroot00000000000000openssl-ibmca-2.4.1/src/Makefile.am000066400000000000000000000001351450276407300171040ustar00rootroot00000000000000SUBDIRS= if IBMCA_ENGINE SUBDIRS += engine endif if IBMCA_PROVIDER SUBDIRS += provider endif openssl-ibmca-2.4.1/src/engine/000077500000000000000000000000001450276407300163165ustar00rootroot00000000000000openssl-ibmca-2.4.1/src/engine/Makefile.am000066400000000000000000000015271450276407300203570ustar00rootroot00000000000000VERSION = 2:4:1 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 openssl-compat.h EXTRA_DIST = openssl.cnf.sample ibmca.map test/ibmca_mechaList_test.c ACLOCAL_AMFLAGS = -I m4 SUBDIRS = doc ibmca-engine-opensslconfig: ibmca-engine-opensslconfig.in $(AM_V_GEN)@SED@ -e s!\@libdir\@!@libdir@!g < $< > $@-t && \ chmod a+x $@-t && \ $(am__mv) $@-t $@ noinst_SCRIPTS = ibmca-engine-opensslconfig EXTRA_DIST += ibmca-engine-opensslconfig.in CLEANFILES = ibmca-engine-opensslconfig openssl-ibmca-2.4.1/src/engine/doc/000077500000000000000000000000001450276407300170635ustar00rootroot00000000000000openssl-ibmca-2.4.1/src/engine/doc/Makefile.am000066400000000000000000000000641450276407300211170ustar00rootroot00000000000000man5_MANS = ibmca.man dist_man5_MANS = $(man5_MANS) openssl-ibmca-2.4.1/src/engine/doc/ibmca.man000066400000000000000000000041771450276407300206440ustar00rootroot00000000000000.\" 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 | EC | PKEY_CRYPTO | RAND .PP Only all CIPHERS and/or DIGESTS can be de/activated. Algorithms like AES can not be de/activated independently. .PP .B Note: Algorithms denoted by CIPHERS, DIGESTS, EC (since IBM z15 for certain curves), and PKEY are already accelerated by OpenSSL itself using CPACF. Therefore, do not accelerate them using the IBMCA engine. This would actually make them slower. .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.4.1/src/engine/e_ibmca.c000066400000000000000000001017551450276407300200520ustar00rootroot00000000000000/* * Copyright [2005-2021] 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 AP_PATH "/sys/devices/ap" /* * The default library name. The macro LIBICA_SHARED_LIB is provided * via configure at the command line. */ static const char *LIBICA_NAME = LIBICA_SHARED_LIB; /* * If a ctrl command is used to set libica name, we have to strdup the * argument since the config parser will free and clear the element at * the end of parsing. If the engine is not loaded during * configuration, we will not be able to use the string provided by * the ctrl command since it is cleared. Remember if we strdup'ed the * string such that we free it at the end. */ static int LIBICA_NAME_allocated; /* 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 ica_cleanup_t p_ica_cleanup; /* 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 registration_helper { int rsa_enabled; int ec_enabled; int ec_kgen_switch; int ec_dh_switch; int ec_dsa_sign_switch; int ec_dsa_verify_switch; int x25519_keygen_switch; int x25519_derive_switch; int x448_keygen_switch; int x448_derive_switch; int ed25519_keygen_switch; int ed25519_sign_switch; int ed25519_verify_switch; int ed448_keygen_switch; int ed448_sign_switch; int ed448_verify_switch; int x25519_switch; int x448_switch; int ed25519_switch; int ed448_switch; } ibmca_registration; static CRYPTO_ONCE bindcountlockinitonce = CRYPTO_ONCE_STATIC_INIT; static CRYPTO_RWLOCK *bindcountlock = NULL; static int bindcount = 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); static void bindcountlockinit(void) { bindcountlock = CRYPTO_THREAD_lock_new(); } /* 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 #define IBMCA_CMD_LIBICA (ENGINE_CMD_BASE + 1) 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}, {IBMCA_CMD_LIBICA, "libica", "Specifies the path to the 'libica' shared library", ENGINE_CMD_FLAG_STRING}, {0, NULL, NULL, 0} }; /* Destructor (complements the "ENGINE_ibmca()" constructor) */ static int ibmca_destroy(ENGINE *e) { int newbindcount; CRYPTO_atomic_add(&bindcount, -1, &newbindcount, bindcountlock); if (newbindcount) return 1; /* 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). */ ERR_unload_IBMCA_strings(); return 1; } inline static int set_RSA_prop(ENGINE *e) { if (ibmca_registration.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; ibmca_registration.rsa_enabled = 1; return 1; } #ifndef OPENSSL_NO_EC static int set_EC_prop(ENGINE *e) { int (*keygen_sw)(EC_KEY *key) = NULL; if (ibmca_registration.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(); /* * 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; } ibmca_ec = EC_KEY_METHOD_new(ibmca_ec); EC_KEY_METHOD_set_keygen(ibmca_ec, keygen_sw); 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 ibmca_registration.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) { 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: ibmca_registration.ec_kgen_switch = 1; break; case EC_DH: ibmca_registration.ec_dh_switch = 1; break; case EC_DSA_SIGN: ibmca_registration.ec_dsa_sign_switch = 1; break; case EC_DSA_VERIFY: ibmca_registration.ec_dsa_verify_switch = 1; break; #endif case ED25519_KEYGEN: ibmca_registration.ed25519_keygen_switch = 1; break; case ED25519_SIGN: ibmca_registration.ed25519_sign_switch = 1; break; case ED25519_VERIFY: ibmca_registration.ed25519_verify_switch = 1; break; case ED448_KEYGEN: ibmca_registration.ed448_keygen_switch = 1; break; case ED448_SIGN: ibmca_registration.ed448_sign_switch = 1; break; case ED448_VERIFY: ibmca_registration.ed448_verify_switch = 1; break; case X25519_KEYGEN: ibmca_registration.x25519_keygen_switch = 1; break; case X25519_DERIVE: ibmca_registration.x25519_derive_switch = 1; break; case X448_KEYGEN: ibmca_registration.x448_keygen_switch = 1; break; case X448_DERIVE: ibmca_registration.x448_derive_switch = 1; break; default: break; /* do nothing */ } #ifndef OPENSSL_NO_EC if (ibmca_registration.ec_kgen_switch && ibmca_registration.ec_dh_switch && ibmca_registration.ec_dsa_sign_switch && ibmca_registration.ec_dsa_verify_switch) { if (!set_EC_prop(e)) return 0; } #endif if (ibmca_registration.x25519_keygen_switch && ibmca_registration.x25519_derive_switch && !ibmca_registration.x25519_switch) { ibmca_registration.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 (ibmca_registration.x448_keygen_switch && ibmca_registration.x448_derive_switch && !ibmca_registration.x448_switch) { ibmca_registration.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 (ibmca_registration.ed25519_keygen_switch && ibmca_registration.ed25519_sign_switch && ibmca_registration.ed25519_verify_switch && !ibmca_registration.ed25519_switch) { ibmca_registration.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 (ibmca_registration.ed448_keygen_switch && ibmca_registration.ed448_sign_switch && ibmca_registration.ed448_verify_switch && !ibmca_registration.ed448_switch) { ibmca_registration.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; if (!ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL)) goto out; rc = 1; out: free(pmech_list); return rc; } __attribute__((constructor)) static void ibmca_constructor(void) { DEBUG_PRINTF(">%s\n", __func__); } __attribute__((destructor)) static void ibmca_destructor(void) { if (bindcountlock) CRYPTO_THREAD_lock_free(bindcountlock); if (LIBICA_NAME_allocated) free((void *)LIBICA_NAME); } static void do_ica_cleanup(void) { if (p_ica_cleanup) p_ica_cleanup(); if (ibmca_dso && dlclose(ibmca_dso)) { IBMCAerr(IBMCA_F_IBMCA_FINISH, IBMCA_R_DSO_FAILURE); return; } 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 p_ica_x25519_ctx_new = NULL; p_ica_x448_ctx_new = NULL; p_ica_ed25519_ctx_new = NULL; p_ica_ed448_ctx_new = NULL; p_ica_x25519_key_set = NULL; p_ica_x448_key_set = NULL; p_ica_ed25519_key_set = NULL; p_ica_ed448_key_set = NULL; p_ica_x25519_key_get = NULL; p_ica_x448_key_get = NULL; p_ica_ed25519_key_get = NULL; p_ica_ed448_key_get = NULL; p_ica_x25519_key_gen = NULL; p_ica_x448_key_gen = NULL; p_ica_ed25519_key_gen = NULL; p_ica_ed448_key_gen = NULL; p_ica_x25519_derive = NULL; p_ica_x448_derive = NULL; p_ica_ed25519_sign = NULL; p_ica_ed448_sign = NULL; p_ica_ed25519_verify = NULL; p_ica_ed448_verify = NULL; p_ica_x25519_ctx_del = NULL; p_ica_x448_ctx_del = NULL; p_ica_ed25519_ctx_del = NULL; p_ica_ed448_ctx_del = NULL; p_ica_cleanup = NULL; } static int ibmca_init(ENGINE *e) { ibmca_dso = dlopen(LIBICA_NAME, RTLD_NOW); if (ibmca_dso == NULL) { DEBUG_PRINTF("%s: dlopen(%s) failed\n", __func__, LIBICA_NAME); 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 BIND(ibmca_dso, ica_x25519_ctx_new); BIND(ibmca_dso, ica_x448_ctx_new); BIND(ibmca_dso, ica_ed25519_ctx_new); BIND(ibmca_dso, ica_ed448_ctx_new); BIND(ibmca_dso, ica_x25519_key_set); BIND(ibmca_dso, ica_x448_key_set); BIND(ibmca_dso, ica_ed25519_key_set); BIND(ibmca_dso, ica_ed448_key_set); BIND(ibmca_dso, ica_x25519_key_get); BIND(ibmca_dso, ica_x448_key_get); BIND(ibmca_dso, ica_ed25519_key_get); BIND(ibmca_dso, ica_ed448_key_get); BIND(ibmca_dso, ica_x25519_key_gen); BIND(ibmca_dso, ica_x448_key_gen); BIND(ibmca_dso, ica_ed25519_key_gen); BIND(ibmca_dso, ica_ed448_key_gen); BIND(ibmca_dso, ica_x25519_derive); BIND(ibmca_dso, ica_x448_derive); BIND(ibmca_dso, ica_ed25519_sign); BIND(ibmca_dso, ica_ed448_sign); BIND(ibmca_dso, ica_ed25519_verify); BIND(ibmca_dso, ica_ed448_verify); BIND(ibmca_dso, ica_x25519_ctx_del); BIND(ibmca_dso, ica_x448_ctx_del); BIND(ibmca_dso, ica_ed25519_ctx_del); BIND(ibmca_dso, ica_ed448_ctx_del); /* ica_cleanup is not always present and only needed for newer libraries */ p_ica_cleanup = (ica_cleanup_t)dlsym(ibmca_dso, "ica_cleanup"); /* disable fallbacks on Libica */ if (BIND(ibmca_dso, ica_set_fallback_mode)) p_ica_set_fallback_mode(0); if (p_ica_open_adapter(&ibmca_handle)) { IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_UNIT_FAILURE); goto err; } #ifndef NO_EC if (!ibmca_ec_init()) goto err; #endif if (!set_supported_meths(e)) goto err; return 1; err: do_ica_cleanup(); return 0; } static int ibmca_finish(ENGINE *e) { #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 if (p_ica_close_adapter) p_ica_close_adapter(ibmca_handle); do_ica_cleanup(); memset(&ibmca_registration, 0, sizeof(ibmca_registration)); return 1; } static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) ()) { char *tmp; 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; } return 1; case IBMCA_CMD_LIBICA: 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; } tmp = strdup((const char *) p); if (!tmp) { IBMCAerr(IBMCA_F_IBMCA_CTRL, ERR_R_MALLOC_FAILURE); return 0; } if (LIBICA_NAME_allocated) free((void *)LIBICA_NAME); LIBICA_NAME = tmp; LIBICA_NAME_allocated = 1; 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) { int ignored; CRYPTO_THREAD_run_once(&bindcountlockinitonce, bindcountlockinit); CRYPTO_atomic_add(&bindcount, 1, &ignored, bindcountlock); 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; 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.4.1/src/engine/e_ibmca_err.c000066400000000000000000000135341450276407300207170ustar00rootroot00000000000000/* * 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.4.1/src/engine/e_ibmca_err.h000066400000000000000000000075751450276407300207340ustar00rootroot00000000000000/* * 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.4.1/src/engine/ibmca-engine-opensslconfig.in000066400000000000000000000106331450276407300240360ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright 2022 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. # # # Generate openssl.cnf from the system config file with added engine section # for ibmca engine. # # USE WITH CARE: No automation can replace human knowledge and understanding # of the desired configuration! # use strict; use warnings; sub generate() { my ($osslconfpath); my ($tmp, $ih, $line, $oh, $defaultcnfsect, $indefaultsect, $enginesect); $osslconfpath = `openssl version -d` || die "Please install openssl binary"; $osslconfpath =~ s/OPENSSLDIR: \"([^\"]*)\"$/$1/ || die "Failed to extract OpenSSL configuration directory"; chomp $osslconfpath; open($ih, "<", "$osslconfpath/openssl.cnf") or die "Cannot open $osslconfpath/openssl.cnf"; open($oh, ">", "openssl.cnf.ibmca") or die "Cannot open openssl.cnf.ibmca"; $defaultcnfsect = undef; $indefaultsect = 0; $enginesect = undef; while ($line = <$ih>) { if ($line =~ /openssl_conf\s*=\s*(.*)/) { $defaultcnfsect = $1; chomp $defaultcnfsect; } if ($indefaultsect) { if ($line =~ /\[\s*\w+\s*\]/) { if (!$enginesect) { print $oh "engines = engine_section\n" } $indefaultsect = 0; } elsif ($line =~ /^\s*engines\s*=\s*(\w+)\s*/) { $enginesect = $1; chomp $enginesect; } } print $oh "$line"; if ($defaultcnfsect && $line =~ /\[\s*$defaultcnfsect\s*\]/) { $indefaultsect = 1; } if ($enginesect && $line =~ /\[\s*$enginesect\s*\]/) { print $oh "ibmca = ibmca_section\n" } } if (!$defaultcnfsect) { print $oh, qq| openssl_conf = openssl_init [openssl_init] engines = engine_section |; } if (!$enginesect) { print $oh qq| [engine_section] ibmca = ibmca_section |; } print $oh qq| [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 = @libdir@/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. # # Note: Algorithms denoted by CIPHERS, DIGESTS, EC (since IBM z15 for certain # curves), and PKEY are already accelerated by OpenSSL itself using CPACF. # Therefore, do not accelerate them using the IBMCA engine. This would actually # make them slower. # # Moreover, ibmca's CIPHER and DIGEST implementations do not # support the processing of messages in arbitrary chunk sizes. # All chunks, except the final one, are required to be a multiple # of the primitive's block size. # # 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 = RSA,DH,DSA,RAND |; close($ih); close($oh); print qq| Successfully generated openssl.cnf.ibmca file. Please review this configuration and, if you are happy with the changes, replace $osslconfpath/openssl.cnf with this file. |; } generate(); openssl-ibmca-2.4.1/src/engine/ibmca.h000066400000000000000000000656621450276407300175610ustar00rootroot00000000000000/* * 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(...) fprintf(stderr, __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 int ibmca_ec_init(void); 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_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); typedef void (*ica_cleanup_t)(void); /* 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; extern ica_cleanup_t p_ica_cleanup; openssl-ibmca-2.4.1/src/engine/ibmca.map000066400000000000000000000001651450276407300200720ustar00rootroot00000000000000IBMCA_2.0.0 { global: v_check; bind_engine; ENGINE_load_ibmca; local: *; }; openssl-ibmca-2.4.1/src/engine/ibmca_cipher.c000066400000000000000000001145731450276407300211020ustar00rootroot00000000000000/* * Copyright [2005-2021] 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 0; 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); if (rv) return 0; return 1; } 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_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.4.1/src/engine/ibmca_dh.c000066400000000000000000000055331450276407300202160ustar00rootroot00000000000000/* * 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 #ifndef OPENSSL_NO_DH static int (*ibmca_mod_exp_dh_backup)(DH const *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* 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) { if (!ibmca_mod_exp(r, a, p, m, ctx) && ibmca_mod_exp_dh_backup) return ibmca_mod_exp_dh_backup(dh, r, a, p, m, ctx, m_ctx); return 1; } #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(); ibmca_mod_exp_dh_backup = meth1->bn_mod_exp; 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 || (ibmca_mod_exp_dh_backup = DH_meth_get_bn_mod_exp(meth1)) == 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.4.1/src/engine/ibmca_digest.c000066400000000000000000000563201450276407300211020ustar00rootroot00000000000000/* * 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.4.1/src/engine/ibmca_dsa.c000066400000000000000000000105041450276407300203640ustar00rootroot00000000000000/* * Copyright [2005-2021] 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); if (!to_return) return BN_mod_exp2_mont(rr, a1, p1, a2, p2, m, ctx, in_mont); 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 { if (!ibmca_mod_exp(r, a, p, m, ctx)) return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); return 1; } #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); dsa_m = NULL; } #endif #endif /* endif OPENSSL_NO_DSA */ openssl-ibmca-2.4.1/src/engine/ibmca_ec.c000066400000000000000000000733101450276407300202100ustar00rootroot00000000000000/* * 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 "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; int ec_ex_data_index = -1; pthread_mutex_t ec_ex_data_mutex = PTHREAD_MUTEX_INITIALIZER; struct ibmca_ec_ex_data { ICA_EC_KEY *ica_key; int nid; unsigned int privlen; }; void ibmca_ec_ex_data_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp) { struct ibmca_ec_ex_data *data = ptr; if (data == NULL) return; p_ica_ec_key_free(data->ica_key); OPENSSL_free(data); } int ibmca_ec_ex_data_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, #ifdef OPENSSL_VERSION_PREREQ void **pptr, int idx, long argl, void *argp) #else void *from_d, int idx, long argl, void *argp) #endif { #ifndef OPENSSL_VERSION_PREREQ void **pptr = (void **)from_d; #endif struct ibmca_ec_ex_data *from_data; struct ibmca_ec_ex_data *to_data; unsigned char Q[2 * IBMCA_EC_MAX_D_LEN]; unsigned char D[IBMCA_EC_MAX_D_LEN]; unsigned int len; int rc; if (pptr == NULL) return 0; from_data = (struct ibmca_ec_ex_data *)*pptr; if (from_data == NULL) return 0; to_data = OPENSSL_zalloc(sizeof(*to_data)); if (to_data == NULL) { return 0; } to_data->nid = from_data->nid; to_data->ica_key = p_ica_ec_key_new(to_data->nid, &to_data->privlen); if (to_data->ica_key == NULL) { IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_ICA_EC_KEY_INIT); goto error; } if (p_ica_ec_key_get_private_key(from_data->ica_key, D, &len) == 0) { rc = p_ica_ec_key_init(NULL, NULL, D, to_data->ica_key); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); goto error; } } if (p_ica_ec_key_get_public_key(from_data->ica_key, Q, &len) == 0) { rc = p_ica_ec_key_init(Q, Q + to_data->privlen, NULL, to_data->ica_key); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); goto error; } } *pptr = to_data; return 1; error: if (to_data->ica_key != NULL) p_ica_ec_key_free(to_data->ica_key); OPENSSL_free(to_data); return 0; } static ICA_EC_KEY *ibmca_ec_make_ica_key(EC_KEY *ec_key, int *nid, unsigned int *privlen) { ICA_EC_KEY *icakey; const EC_GROUP *group; const EC_POINT *q; const BIGNUM *bn_d; BIGNUM *bn_x = NULL, *bn_y = NULL; unsigned char D[IBMCA_EC_MAX_D_LEN]; unsigned char X[IBMCA_EC_MAX_D_LEN]; unsigned char Y[IBMCA_EC_MAX_D_LEN]; int rc, n; /* Get group */ if ((group = EC_KEY_get0_group(ec_key)) == NULL) { IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INVALID_PARM); return NULL; } /* Get curve nid */ *nid = EC_GROUP_get_curve_name(group); if (*nid <= 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_UNSUPPORTED_CURVE); return NULL; } /* Create ICA_EC_KEY object */ icakey = p_ica_ec_key_new(*nid, privlen); if (icakey == NULL) { IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_ICA_EC_KEY_INIT); return NULL; } /* Get private (D) value from EC_KEY (if available) */ bn_d = EC_KEY_get0_private_key(ec_key); if (bn_d != NULL) { /* 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 error; } } /* Get public (X and Y) values from EC_KEY (if available) */ q = EC_KEY_get0_public_key(ec_key); if (q != NULL) { /* Provide public key (X,Y) */ bn_x = BN_new(); bn_y = BN_new(); if (!EC_POINT_get_affine_coordinates_GFp(group, q, bn_x, bn_y, NULL)) { IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR); goto error; } /* Format (X) as char array with leading nulls 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 nulls if necessary */ n = *privlen - BN_num_bytes(bn_y); memset(Y, 0, n); BN_bn2bin(bn_y, &Y[n]); /* Initialize public ICA_EC_KEY */ rc = p_ica_ec_key_init(X, Y, NULL, icakey); if (rc != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc); goto error; } } out: BN_clear_free(bn_x); BN_clear_free(bn_y); return icakey; error: p_ica_ec_key_free(icakey); icakey = NULL; goto out; } static ICA_EC_KEY *ibmca_ec_make_and_cache_ica_key(EC_KEY *ec_key, unsigned int *privlen) { struct ibmca_ec_ex_data *data, *data2; data = OPENSSL_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->ica_key = ibmca_ec_make_ica_key(ec_key, &data->nid, &data->privlen); if (data->ica_key == NULL) { OPENSSL_free(data); return NULL; } /* * Note that another thread could have allocated and set the ex_data for * that key after the caller of this function has checked if there is * already ex_data available for the key. So once we have the lock, we * check again, and if there now is ex_data available, we return the * ICA key from the ex_data, and free the one just created. */ if (pthread_mutex_lock(&ec_ex_data_mutex) != 0) { IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR); return NULL; } data2 = EC_KEY_get_ex_data(ec_key, ec_ex_data_index); if (data2 != NULL) { pthread_mutex_unlock(&ec_ex_data_mutex); p_ica_ec_key_free(data->ica_key); OPENSSL_free(data); *privlen = data2->privlen; return data2->ica_key; } if (EC_KEY_set_ex_data(ec_key, ec_ex_data_index, data) != 1) { IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR); pthread_mutex_unlock(&ec_ex_data_mutex); OPENSSL_free(data); return NULL; } pthread_mutex_unlock(&ec_ex_data_mutex); *privlen = data->privlen; return data->ica_key; } int ibmca_ec_init(void) { #ifdef OLDER_OPENSSL return 0; #else ec_ex_data_index = EC_KEY_get_ex_new_index(0, NULL, NULL, ibmca_ec_ex_data_dup, ibmca_ec_ex_data_free); if (ec_ex_data_index < 0) { IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_EC_INTERNAL_ERROR); return 0; } return 1; #endif } 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 (ec_ex_data_index >= 0) { CRYPTO_free_ex_index(CRYPTO_EX_INDEX_EC_KEY, ec_ex_data_index); ec_ex_data_index = -1; } 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_x = NULL, *bn_y = NULL; unsigned int n, privlen; unsigned char X[IBMCA_EC_MAX_D_LEN]; unsigned char Y[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 struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(ecdh, ec_ex_data_index); /* 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_UNSUPPORTED_CURVE); return 0; } if (data != NULL) { ica_privkey = data->ica_key; privlen = data->privlen; goto do_derive; } /* Create ICA_EC_KEY object for private key */ ica_privkey = ibmca_ec_make_and_cache_ica_key((EC_KEY*)ecdh, &privlen); if (ica_privkey == 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 } do_derive: /* 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; } /* 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); 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; unsigned int privlen; BIGNUM *r, *s, *kinv; unsigned char sigret[IBMCA_EC_MAX_SIG_LEN]; int 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; struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(eckey, ec_ex_data_index); /* 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; } /* 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 if (data != NULL) { icakey = data->ica_key; privlen = data->privlen; goto do_sign; } /* Create ICA_EC_KEY object */ icakey = ibmca_ec_make_and_cache_ica_key(eckey, &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; } do_sign: /* 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(); #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: 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) { 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; 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; struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(eckey, ec_ex_data_index); /* 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 if (data != NULL) { icakey = data->ica_key; privlen = data->privlen; goto do_verify; } /* Create ICA_EC_KEY object */ icakey = ibmca_ec_make_and_cache_ica_key(eckey, &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); } do_verify: /* 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: 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; /** * 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.4.1/src/engine/ibmca_pkey.c000066400000000000000000000435531450276407300205770ustar00rootroot00000000000000/* * Copyright 2019-2021 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" #include "openssl-compat.h" 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 (p_ica_x25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_KEYGEN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_x25519_key_gen(ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } if (p_ica_x25519_key_get(ctx, priv, pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } key = ossl_ecx_key_new_simple(ECX_KEY_TYPE_X25519); private = calloc(1, sizeof(priv)); if (key == NULL || private == NULL) { IBMCAerr(IBMCA_F_IBMCA_X25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } memcpy(private, priv, sizeof(priv)); ossl_ecx_copypubkey(key, pub, sizeof(pub)); ossl_ecx_set0_privkey(key, private); EVP_PKEY_assign(pkey, NID_X25519, key); rc = 1; ret: if (rc == 0) { free(key); free(private); } if (ctx != NULL) p_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 (p_ica_x25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_DERIVE, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_x25519_key_set(ctx, ossl_ecx_get0_privkey(key_ecx), NULL) != 0) { IBMCAerr(IBMCA_F_IBMCA_X25519_DERIVE, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (p_ica_x25519_derive(ctx, key, ossl_ecx_get0_pubkey(peerkey_ecx)) != 0) goto ret; rc = 1; ret: if (ctx != NULL) p_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 (p_ica_x448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_KEYGEN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_x448_key_gen(ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } if (p_ica_x448_key_get(ctx, priv, pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } key = ossl_ecx_key_new_simple(ECX_KEY_TYPE_X448); private = calloc(1, sizeof(priv)); if (key == NULL || private == NULL) { IBMCAerr(IBMCA_F_IBMCA_X448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } memcpy(private, priv, sizeof(priv)); ossl_ecx_copypubkey(key, pub, sizeof(pub)); ossl_ecx_set0_privkey(key, private); EVP_PKEY_assign(pkey, NID_X448, key); rc = 1; ret: if (rc == 0) { free(key); free(private); } if (ctx != NULL) p_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 (p_ica_x448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_DERIVE, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_x448_key_set(ctx, ossl_ecx_get0_privkey(key_ecx), NULL) != 0) { IBMCAerr(IBMCA_F_IBMCA_X448_DERIVE, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (p_ica_x448_derive(ctx, key, ossl_ecx_get0_pubkey(peerkey_ecx)) != 0) goto ret; rc = 1; ret: if (ctx != NULL) p_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 (p_ica_ed25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_KEYGEN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_ed25519_key_gen(ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } if (p_ica_ed25519_key_get(ctx, priv, pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } key = ossl_ecx_key_new_simple(ECX_KEY_TYPE_ED25519); private = calloc(1, sizeof(priv)); if (key == NULL || private == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED25519_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } memcpy(private, priv, sizeof(priv)); ossl_ecx_copypubkey(key, pub, sizeof(pub)); ossl_ecx_set0_privkey(key, private); EVP_PKEY_assign(pkey, NID_ED25519, key); rc = 1; ret: if (rc == 0) { free(key); free(private); } if (ctx != NULL) p_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 (p_ica_ed25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_SIGN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_ed25519_key_set(ctx, ossl_ecx_get0_privkey(key_ecx), NULL) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_SIGN, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (p_ica_ed25519_sign(ctx, sig, tbs, tbslen) != 0) goto ret; *siglen = 2 * 32; rc = 1; ret: if (ctx != NULL) p_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 (p_ica_ed25519_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_VERIFY, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_ed25519_key_set(ctx, NULL, ossl_ecx_get0_pubkey(key_ecx)) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED25519_VERIFY, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (p_ica_ed25519_verify(ctx, sig, tbv, tbvlen) != 0) goto ret; rc = 1; ret: if (ctx != NULL) p_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 (p_ica_ed448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_KEYGEN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_ed448_key_gen(ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } if (p_ica_ed448_key_get(ctx, priv, pub) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } key = ossl_ecx_key_new_simple(ECX_KEY_TYPE_ED448); private = calloc(1, sizeof(priv)); if (key == NULL || private == NULL) { IBMCAerr(IBMCA_F_IBMCA_ED448_KEYGEN, IBMCA_R_PKEY_KEYGEN_FAILED); goto ret; } memcpy(private, priv, sizeof(priv)); ossl_ecx_copypubkey(key, pub, sizeof(pub)); ossl_ecx_set0_privkey(key, private); EVP_PKEY_assign(pkey, NID_ED448, key); rc = 1; ret: if (rc == 0) { free(key); free(private); } if (ctx != NULL) p_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 (p_ica_ed448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_SIGN, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_ed448_key_set(ctx, ossl_ecx_get0_privkey(key_ecx), NULL) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_SIGN, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (p_ica_ed448_sign(ctx, sig, tbs, tbslen) != 0) goto ret; *siglen = 2 * 57; rc = 1; ret: if (ctx != NULL) p_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 (p_ica_ed448_ctx_new(&ctx) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_VERIFY, IBMCA_R_PKEY_INTERNAL_ERROR); goto ret; } if (p_ica_ed448_key_set(ctx, NULL, ossl_ecx_get0_pubkey(key_ecx)) != 0) { IBMCAerr(IBMCA_F_IBMCA_ED448_VERIFY, IBMCA_R_PKEY_KEYS_NOT_SET); goto ret; } if (p_ica_ed448_verify(ctx, sig, tbv, tbvlen) != 0) goto ret; rc = 1; ret: if (ctx != NULL) p_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); EVP_PKEY_meth_set_digestsign(ibmca_ed25519_pmeth, ibmca_ed25519_sign); EVP_PKEY_meth_set_digestverify(ibmca_ed25519_pmeth, 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); EVP_PKEY_meth_set_digestsign(ibmca_ed448_pmeth, ibmca_ed448_sign); EVP_PKEY_meth_set_digestverify(ibmca_ed448_pmeth, 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.4.1/src/engine/ibmca_rsa.c000066400000000000000000000314601450276407300204060ustar00rootroot00000000000000/* * Copyright [2005-2021] 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" #include /* * 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) { /* * Ensure that the MONT_CTXs for public and private keys are cached. * This enables that ibmca_mod_exp_mont() is also called during * (re-)setup of the RSA blinding factors. */ RSA_set_flags(rsa, RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); return 1; } static int (*ibmca_rsa_mod_exp_backup)(BIGNUM * r0, const BIGNUM * I, RSA * rsa, BN_CTX * ctx); static int ibmca_rsa_mod_exp(BIGNUM * r0, const BIGNUM * I, RSA * rsa, BN_CTX * ctx) { int to_return = 0, usebackup = 1; 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); usebackup = 0; 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: if (!to_return && usebackup && ibmca_rsa_mod_exp_backup) return ibmca_rsa_mod_exp_backup(r0, I, rsa, ctx); return to_return; } static int (*ibmca_mod_exp_mont_backup)(BIGNUM * r, const BIGNUM * a, const BIGNUM * p, const BIGNUM * m, BN_CTX * ctx, BN_MONT_CTX * m_ctx); /* 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) { if (!ibmca_mod_exp(r, a, p, m, ctx)) { if (ibmca_mod_exp_mont_backup) return ibmca_mod_exp_mont_backup(r, a, p, m, ctx, m_ctx); return 0; } return 1; } #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(); ibmca_rsa_mod_exp_backup = meth1->rsa_mod_exp; ibmca_mod_exp_mont_backup = meth1->bn_mod_exp; 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 || (ibmca_rsa_mod_exp_backup = RSA_meth_get_mod_exp(meth1)) == NULL || (ibmca_mod_exp_mont_backup = RSA_meth_get_bn_mod_exp(meth1)) == 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); rsa_m = NULL; } #endif #endif /* endif OPENSSL_NO_RSA */ openssl-ibmca-2.4.1/src/engine/openssl-compat.h000066400000000000000000000064271450276407300214440ustar00rootroot00000000000000/* * Copyright 2022 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 IBMCA_OPENSSL_COMPAT_H #define IBMCA_OPENSSL_COMPAT_H #include typedef enum { ECX_KEY_TYPE_X25519, ECX_KEY_TYPE_X448, ECX_KEY_TYPE_ED25519, ECX_KEY_TYPE_ED448 } ECX_KEY_TYPE; #ifdef OPENSSL_VERSION_PREREQ /* This is 3.x */ # define X25519_KEYLEN 32 # define X448_KEYLEN 56 # define ED25519_KEYLEN 32 # define ED448_KEYLEN 57 # define MAX_KEYLEN ED448_KEYLEN typedef int CRYPTO_REF_COUNT; typedef struct ecx_key_st { OSSL_LIB_CTX *libctx; char *propq; unsigned int haspubkey:1; unsigned char pubkey[MAX_KEYLEN]; unsigned char *privkey; size_t keylen; ECX_KEY_TYPE type; CRYPTO_REF_COUNT references; CRYPTO_RWLOCK *lock; } ECX_KEY; static inline ECX_KEY *ossl_ecx_key_new_simple(ECX_KEY_TYPE type) { ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) return NULL; ret->libctx = NULL; ret->haspubkey = 0; switch (type) { case ECX_KEY_TYPE_X25519: ret->keylen = X25519_KEYLEN; break; case ECX_KEY_TYPE_X448: ret->keylen = X448_KEYLEN; break; case ECX_KEY_TYPE_ED25519: ret->keylen = ED25519_KEYLEN; break; case ECX_KEY_TYPE_ED448: ret->keylen = ED448_KEYLEN; break; } ret->type = type; ret->references = 1; ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) goto err; return ret; err: OPENSSL_free(ret); return NULL; } static inline void ossl_ecx_set0_privkey(ECX_KEY *key, unsigned char *privkey) { key->privkey = privkey; } static inline unsigned char *ossl_ecx_get0_privkey(ECX_KEY *key) { return key->privkey; } static inline unsigned char *ossl_ecx_get0_pubkey(ECX_KEY *key) { return key->pubkey; } static inline void ossl_ecx_copypubkey(ECX_KEY *key, unsigned char *pubkey, size_t len) { memcpy(key->pubkey, pubkey, len); key->haspubkey = 1; } #else /* This is 1.1.x */ #include /* * copied from evp_int.h: * missing set/get methods for opaque types. */ typedef struct { unsigned char pub[57]; unsigned char *priv; } ECX_KEY; static inline ECX_KEY *ossl_ecx_key_new_simple(ECX_KEY_TYPE type) { return calloc(1, sizeof(ECX_KEY)); } static inline void ossl_ecx_set0_privkey(ECX_KEY *key, unsigned char *privkey) { key->priv = privkey; } static inline unsigned char *ossl_ecx_get0_privkey(ECX_KEY *key) { return key->priv; } static inline unsigned char *ossl_ecx_get0_pubkey(ECX_KEY *key) { return key->pub; } static inline void ossl_ecx_copypubkey(ECX_KEY *key, unsigned char *pubkey, size_t len) { memcpy(key->pub, pubkey, len); } #endif #endif openssl-ibmca-2.4.1/src/engine/openssl.cnf.sample000066400000000000000000000042161450276407300217540ustar00rootroot00000000000000# # 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. # # Note: Algorithms denoted by CIPHERS, DIGESTS, EC (since IBM z15 for certain # curves), and PKEY are already accelerated by OpenSSL itself using CPACF. # Therefore, do not accelerate them using the IBMCA engine. This would actually # make them slower. # # Moreover, ibmca's CIPHER and DIGEST implementations do not # support the processing of messages in arbitrary chunk sizes. # All chunks, except the final one, are required to be a multiple # of the primitive's block size. # # 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 = RSA,DH,DSA,RAND openssl-ibmca-2.4.1/src/engine/test/000077500000000000000000000000001450276407300172755ustar00rootroot00000000000000openssl-ibmca-2.4.1/src/engine/test/Makefile.linux.in000066400000000000000000000004721450276407300225030ustar00rootroot00000000000000PTS = -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 $@ $^ -l@ICA@ -lcrypto clean: rm -f $(TARGETS) openssl-ibmca-2.4.1/src/engine/test/ibmca_mechaList_test.c000066400000000000000000000262761450276407300235610ustar00rootroot00000000000000/* * 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.4.1/src/provider/000077500000000000000000000000001450276407300167035ustar00rootroot00000000000000openssl-ibmca-2.4.1/src/provider/Makefile.am000066400000000000000000000015771450276407300207510ustar00rootroot00000000000000VERSION = 2:4:1 VERSION_STR = 2.4.1 lib_LTLIBRARIES=ibmca-provider.la ibmca_provider_la_SOURCES=p_ibmca.c p_key.c p_context.c \ rsa_keymgmt.c rsa_asym_cipher.c rsa_padding.c \ rsa_signature.c ec_keymgmt.c ec_signature.c ec_keyexch.c \ dh_keymgmt.c dh_keyexch.c rsa_blinding.c rsa_sup_mul.c dist_ibmca_provider_la_SOURCES=p_ibmca.h constant_time.h ibmca_provider_la_CFLAGS=-DIBMCA_VERSION=\"${VERSION_STR}\" -DIBMCA_LOGDIR=\"$(logdir)\" if PROVIDER_FULL_LIBICA ibmca_provider_la_LIBADD=-ldl -lica else ibmca_provider_la_LIBADD=-ldl -lica-cex endif ibmca_provider_la_LDFLAGS=-module -version-number ${VERSION} -shared -no-undefined \ -avoid-version -Wl,--version-script=${srcdir}/ibmca-provider.map EXTRA_DIST = openssl.cnf.provider.sample ibmca-provider-opensslconfig \ ibmca-provider.map ACLOCAL_AMFLAGS = -I m4 SUBDIRS = doc noinst_SCRIPTS = ibmca-provider-opensslconfig openssl-ibmca-2.4.1/src/provider/constant_time.h000066400000000000000000000315741450276407300217350ustar00rootroot00000000000000/* * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2023 International Business Machines Corp. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html * * Copied from OpenSSL include/internal/constant_time.h * The only changes are to add this notice and the copyright statement above. */ #ifndef OSSL_INTERNAL_CONSTANT_TIME_H # define OSSL_INTERNAL_CONSTANT_TIME_H # pragma once # include # include # include /* For 'ossl_inline' */ /*- * The boolean methods return a bitmask of all ones (0xff...f) for true * and 0 for false. This is useful for choosing a value based on the result * of a conditional in constant time. For example, * if (a < b) { * c = a; * } else { * c = b; * } * can be written as * unsigned int lt = constant_time_lt(a, b); * c = constant_time_select(lt, a, b); */ /* Returns the given value with the MSB copied to all the other bits. */ static ossl_inline unsigned int constant_time_msb(unsigned int a); /* Convenience method for uint32_t. */ static ossl_inline uint32_t constant_time_msb_32(uint32_t a); /* Convenience method for uint64_t. */ static ossl_inline uint64_t constant_time_msb_64(uint64_t a); /* Returns 0xff..f if a < b and 0 otherwise. */ static ossl_inline unsigned int constant_time_lt(unsigned int a, unsigned int b); /* Convenience method for getting an 8-bit mask. */ static ossl_inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b); /* Convenience method for uint64_t. */ static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b); /* Returns 0xff..f if a >= b and 0 otherwise. */ static ossl_inline unsigned int constant_time_ge(unsigned int a, unsigned int b); /* Convenience method for getting an 8-bit mask. */ static ossl_inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b); /* Returns 0xff..f if a == 0 and 0 otherwise. */ static ossl_inline unsigned int constant_time_is_zero(unsigned int a); /* Convenience method for getting an 8-bit mask. */ static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a); /* Convenience method for getting a 32-bit mask. */ static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a); /* Returns 0xff..f if a == b and 0 otherwise. */ static ossl_inline unsigned int constant_time_eq(unsigned int a, unsigned int b); /* Convenience method for getting an 8-bit mask. */ static ossl_inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b); /* Signed integers. */ static ossl_inline unsigned int constant_time_eq_int(int a, int b); /* Convenience method for getting an 8-bit mask. */ static ossl_inline unsigned char constant_time_eq_int_8(int a, int b); /*- * Returns (mask & a) | (~mask & b). * * When |mask| is all 1s or all 0s (as returned by the methods above), * the select methods return either |a| (if |mask| is nonzero) or |b| * (if |mask| is zero). */ static ossl_inline unsigned int constant_time_select(unsigned int mask, unsigned int a, unsigned int b); /* Convenience method for unsigned chars. */ static ossl_inline unsigned char constant_time_select_8(unsigned char mask, unsigned char a, unsigned char b); /* Convenience method for uint32_t. */ static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a, uint32_t b); /* Convenience method for uint64_t. */ static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a, uint64_t b); /* Convenience method for signed integers. */ static ossl_inline int constant_time_select_int(unsigned int mask, int a, int b); static ossl_inline unsigned int constant_time_msb(unsigned int a) { return 0 - (a >> (sizeof(a) * 8 - 1)); } static ossl_inline uint32_t constant_time_msb_32(uint32_t a) { return 0 - (a >> 31); } static ossl_inline uint64_t constant_time_msb_64(uint64_t a) { return 0 - (a >> 63); } static ossl_inline size_t constant_time_msb_s(size_t a) { return 0 - (a >> (sizeof(a) * 8 - 1)); } static ossl_inline unsigned int constant_time_lt(unsigned int a, unsigned int b) { return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); } static ossl_inline size_t constant_time_lt_s(size_t a, size_t b) { return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b))); } static ossl_inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b) { return (unsigned char)constant_time_lt(a, b); } static ossl_inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b) { return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b))); } static ossl_inline unsigned int constant_time_ge(unsigned int a, unsigned int b) { return ~constant_time_lt(a, b); } static ossl_inline size_t constant_time_ge_s(size_t a, size_t b) { return ~constant_time_lt_s(a, b); } static ossl_inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b) { return (unsigned char)constant_time_ge(a, b); } static ossl_inline unsigned char constant_time_ge_8_s(size_t a, size_t b) { return (unsigned char)constant_time_ge_s(a, b); } static ossl_inline unsigned int constant_time_is_zero(unsigned int a) { return constant_time_msb(~a & (a - 1)); } static ossl_inline size_t constant_time_is_zero_s(size_t a) { return constant_time_msb_s(~a & (a - 1)); } static ossl_inline unsigned char constant_time_is_zero_8(unsigned int a) { return (unsigned char)constant_time_is_zero(a); } static ossl_inline uint32_t constant_time_is_zero_32(uint32_t a) { return constant_time_msb_32(~a & (a - 1)); } static ossl_inline uint64_t constant_time_is_zero_64(uint64_t a) { return constant_time_msb_64(~a & (a - 1)); } static ossl_inline unsigned int constant_time_eq(unsigned int a, unsigned int b) { return constant_time_is_zero(a ^ b); } static ossl_inline size_t constant_time_eq_s(size_t a, size_t b) { return constant_time_is_zero_s(a ^ b); } static ossl_inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b) { return (unsigned char)constant_time_eq(a, b); } static ossl_inline unsigned char constant_time_eq_8_s(size_t a, size_t b) { return (unsigned char)constant_time_eq_s(a, b); } static ossl_inline unsigned int constant_time_eq_int(int a, int b) { return constant_time_eq((unsigned)(a), (unsigned)(b)); } static ossl_inline unsigned char constant_time_eq_int_8(int a, int b) { return constant_time_eq_8((unsigned)(a), (unsigned)(b)); } /* * Returns the value unmodified, but avoids optimizations. * The barriers prevent the compiler from narrowing down the * possible value range of the mask and ~mask in the select * statements, which avoids the recognition of the select * and turning it into a conditional load or branch. */ static ossl_inline unsigned int value_barrier(unsigned int a) { #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) unsigned int r; __asm__("" : "=r"(r) : "0"(a)); #else volatile unsigned int r = a; #endif return r; } /* Convenience method for uint32_t. */ static ossl_inline uint32_t value_barrier_32(uint32_t a) { #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) uint32_t r; __asm__("" : "=r"(r) : "0"(a)); #else volatile uint32_t r = a; #endif return r; } /* Convenience method for uint64_t. */ static ossl_inline uint64_t value_barrier_64(uint64_t a) { #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) uint64_t r; __asm__("" : "=r"(r) : "0"(a)); #else volatile uint64_t r = a; #endif return r; } /* Convenience method for size_t. */ static ossl_inline size_t value_barrier_s(size_t a) { #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) size_t r; __asm__("" : "=r"(r) : "0"(a)); #else volatile size_t r = a; #endif return r; } static ossl_inline unsigned int constant_time_select(unsigned int mask, unsigned int a, unsigned int b) { return (value_barrier(mask) & a) | (value_barrier(~mask) & b); } static ossl_inline size_t constant_time_select_s(size_t mask, size_t a, size_t b) { return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b); } static ossl_inline unsigned char constant_time_select_8(unsigned char mask, unsigned char a, unsigned char b) { return (unsigned char)constant_time_select(mask, a, b); } static ossl_inline int constant_time_select_int(unsigned int mask, int a, int b) { return (int)constant_time_select(mask, (unsigned)(a), (unsigned)(b)); } static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b) { return (int)constant_time_select((unsigned)mask, (unsigned)(a), (unsigned)(b)); } static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a, uint32_t b) { return (value_barrier_32(mask) & a) | (value_barrier_32(~mask) & b); } static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a, uint64_t b) { return (value_barrier_64(mask) & a) | (value_barrier_64(~mask) & b); } /* * mask must be 0xFFFFFFFF or 0x00000000. * * if (mask) { * uint32_t tmp = *a; * * *a = *b; * *b = tmp; * } */ static ossl_inline void constant_time_cond_swap_32(uint32_t mask, uint32_t *a, uint32_t *b) { uint32_t xor = *a ^ *b; xor &= mask; *a ^= xor; *b ^= xor; } /* * mask must be 0xFFFFFFFF or 0x00000000. * * if (mask) { * uint64_t tmp = *a; * * *a = *b; * *b = tmp; * } */ static ossl_inline void constant_time_cond_swap_64(uint64_t mask, uint64_t *a, uint64_t *b) { uint64_t xor = *a ^ *b; xor &= mask; *a ^= xor; *b ^= xor; } /* * mask must be 0xFF or 0x00. * "constant time" is per len. * * if (mask) { * unsigned char tmp[len]; * * memcpy(tmp, a, len); * memcpy(a, b); * memcpy(b, tmp); * } */ static ossl_inline void constant_time_cond_swap_buff(unsigned char mask, unsigned char *a, unsigned char *b, size_t len) { size_t i; unsigned char tmp; for (i = 0; i < len; i++) { tmp = a[i] ^ b[i]; tmp &= mask; a[i] ^= tmp; b[i] ^= tmp; } } /* * table is a two dimensional array of bytes. Each row has rowsize elements. * Copies row number idx into out. rowsize and numrows are not considered * private. */ static ossl_inline void constant_time_lookup(void *out, const void *table, size_t rowsize, size_t numrows, size_t idx) { size_t i, j; const unsigned char *tablec = (const unsigned char *)table; unsigned char *outc = (unsigned char *)out; unsigned char mask; memset(out, 0, rowsize); /* Note idx may underflow - but that is well defined */ for (i = 0; i < numrows; i++, idx--) { mask = (unsigned char)constant_time_is_zero_s(idx); for (j = 0; j < rowsize; j++) *(outc + j) |= constant_time_select_8(mask, *(tablec++), 0); } } /* * Expected usage pattern is to unconditionally set error and then * wipe it if there was no actual error. |clear| is 1 or 0. */ void err_clear_last_constant_time(int clear); #endif /* OSSL_INTERNAL_CONSTANT_TIME_H */ openssl-ibmca-2.4.1/src/provider/dh_keyexch.c000066400000000000000000000632601450276407300211710ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include #include "p_ibmca.h" static OSSL_FUNC_keyexch_newctx_fn ibmca_keyexch_dh_newctx; static OSSL_FUNC_keyexch_init_fn ibmca_keyexch_dh_init; static OSSL_FUNC_keyexch_set_peer_fn ibmca_keyexch_dh_set_peer; static OSSL_FUNC_keyexch_derive_fn ibmca_keyexch_dh_derive; static OSSL_FUNC_keyexch_set_ctx_params_fn ibmca_keyexch_dh_set_ctx_params; static OSSL_FUNC_keyexch_settable_ctx_params_fn ibmca_keyexch_dh_settable_ctx_params; static OSSL_FUNC_keyexch_get_ctx_params_fn ibmca_keyexch_dh_get_ctx_params; static OSSL_FUNC_keyexch_gettable_ctx_params_fn ibmca_keyexch_dh_gettable_ctx_params; static void ibmca_keyexch_dh_free_cb(struct ibmca_op_ctx *ctx); static int ibmca_keyexch_dh_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx); static int ibmca_keyexch_dh_set_ctx_params(void *vctx, const OSSL_PARAM params[]); static void *ibmca_keyexch_dh_newctx(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; struct ibmca_op_ctx *opctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); opctx = ibmca_op_newctx(provctx, NULL, EVP_PKEY_DH, ibmca_keyexch_dh_free_cb, ibmca_keyexch_dh_dup_cb); if (opctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_op_newctx failed"); return NULL; } ibmca_debug_ctx(provctx, "opctx: %p", opctx); return opctx; } static void ibmca_keyexch_dh_free_cb(struct ibmca_op_ctx *ctx) { if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->dh.derive.peer_key != NULL) ibmca_keymgmt_free(ctx->dh.derive.peer_key); ctx->dh.derive.peer_key = NULL; ctx->dh.derive.pad = false; ctx->dh.derive.kdf_type = EVP_PKEY_DH_KDF_NONE; if (ctx->dh.derive.kdf_md != NULL) EVP_MD_free(ctx->dh.derive.kdf_md); ctx->dh.derive.kdf_md = NULL; ctx->dh.derive.kdf_outlen = 0; if (ctx->dh.derive.kdf_ukm != NULL) P_CLEAR_FREE(ctx->provctx, ctx->dh.derive.kdf_ukm, ctx->dh.derive.kdf_ukmlen); ctx->dh.derive.kdf_ukm = NULL; ctx->dh.derive.kdf_ukmlen = 0; if (ctx->dh.derive.kdf_cekalg != NULL) P_FREE(ctx->provctx, ctx->dh.derive.kdf_cekalg); ctx->dh.derive.kdf_cekalg = NULL; } static int ibmca_keyexch_dh_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p new_ctx: %p", ctx, new_ctx); if (ctx->dh.derive.peer_key != NULL) { new_ctx->dh.derive.peer_key = ctx->dh.derive.peer_key; ibmca_keymgmt_upref(new_ctx->dh.derive.peer_key); } new_ctx->dh.derive.pad = ctx->dh.derive.pad; new_ctx->dh.derive.kdf_type = ctx->dh.derive.kdf_type; new_ctx->dh.derive.kdf_md = ctx->dh.derive.kdf_md; if (new_ctx->dh.derive.kdf_md != NULL) { if (EVP_MD_up_ref(new_ctx->dh.derive.kdf_md) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_up_ref failed"); return 0; } } new_ctx->dh.derive.kdf_outlen = ctx->dh.derive.kdf_outlen; if (ctx->dh.derive.kdf_ukm != NULL && ctx->dh.derive.kdf_ukmlen > 0) { new_ctx->dh.derive.kdf_ukm = P_MEMDUP(ctx->provctx, ctx->dh.derive.kdf_ukm, ctx->dh.derive.kdf_ukmlen); if (new_ctx->dh.derive.kdf_ukm == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_MALLOC_FAILED, "P_MEMDUP failed"); return 0; } new_ctx->dh.derive.kdf_ukmlen = ctx->dh.derive.kdf_ukmlen; } if (ctx->dh.derive.kdf_cekalg != NULL) { new_ctx->dh.derive.kdf_cekalg = P_STRDUP(ctx->provctx, ctx->dh.derive.kdf_cekalg); if (new_ctx->dh.derive.kdf_cekalg == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_MALLOC_FAILED, "P_STRDUP failed"); return 0; } } return 1; } static int ibmca_keyexch_dh_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; const OSSL_PARAM *p; if (ctx == NULL || key == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); if (ibmca_op_init(ctx, key, EVP_PKEY_OP_DERIVE) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_init failed"); return 0; } /* Set up defaults for this context */ ibmca_keyexch_dh_free_cb(ctx); if (params != NULL) { if (ibmca_keyexch_dh_set_ctx_params(ctx, params) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_dh_set_ctx_params failed"); return 0; } } return 1; } static int ibmca_keyexch_dh_set_peer(void *vctx, void *vkey) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; if (ctx == NULL || key == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key); if (key->type != ctx->key->type) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Peer key is not an DH or DHX key"); return 0; } if (ctx->key->match(ctx->key, key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Peer key uses a different DH parameters"); return 0; } if (key->has(key, OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Peer key does not contain a public DH key"); return 0; } if (ctx->dh.derive.peer_key != NULL) ibmca_keymgmt_free(ctx->dh.derive.peer_key); ctx->dh.derive.peer_key = key; ibmca_keymgmt_upref(key); return 1; } static int ibmca_keyexch_dh_derive_plain_fallback(struct ibmca_op_ctx *ctx, unsigned char *secret, size_t outlen) { EVP_PKEY *pkey = NULL; EVP_PKEY *peer = NULL; EVP_PKEY_CTX *pctx = NULL; size_t keylen; int rc = 0; ibmca_debug_op_ctx(ctx, "ctx: %p secret: %p outlen: %lu", ctx, secret, outlen); pkey = ibmca_new_fallback_pkey(ctx->key); if (pkey == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } peer = ibmca_new_fallback_pkey(ctx->dh.derive.peer_key); if (peer == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(ctx->provctx, pkey, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_derive_init(pctx) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_derive_init failed"); goto out; } if (ibmca_check_fallback_provider(ctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } if (EVP_PKEY_derive_set_peer(pctx, peer) != 1 || EVP_PKEY_CTX_set_dh_pad(pctx, 1) != 1 || EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_NONE) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_derive_set_peer/EVP_PKEY_CTX_set_dh_pad/EVP_PKEY_CTX_set_dh_kdf_type failed"); goto out; } keylen = outlen; if (EVP_PKEY_derive(pctx, secret, &keylen) != 1 || keylen != outlen) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_derive failed"); goto out; } rc = 1; out: if (pkey != NULL) EVP_PKEY_free(pkey); if (peer != NULL) EVP_PKEY_free(peer); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); return rc; } static int ibmca_keyexch_dh_derive_plain(struct ibmca_op_ctx *ctx, unsigned char *secret, size_t *secretlen, size_t outlen, bool pad) { int rc = 0; unsigned char *buf, *pub; bool use_tbuf = false; size_t prime_size, i; ica_rsa_key_mod_expo_t mod_exp; BIGNUM *z = NULL, *pminus1 = NULL; ibmca_debug_op_ctx(ctx, "ctx: %p secret: %p outlen: %lu pad: %d", ctx, secret, outlen, pad); prime_size = ctx->key->get_max_param_size(ctx->key); if (secret == NULL) { *secretlen = prime_size; rc = 1; goto out; } *secretlen = outlen < prime_size ? outlen : prime_size; if (ibmca_op_alloc_tbuf(ctx, 4 * prime_size) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); goto out; } if (*secretlen == prime_size) { buf = secret; } else { buf = ctx->tbuf; use_tbuf = true; } /* Z = pub_key^priv_key mod p */ mod_exp.key_length = prime_size; mod_exp.modulus = ctx->tbuf + prime_size; mod_exp.exponent = ctx->tbuf + 2 * prime_size; pub = ctx->tbuf + 3 * prime_size; if (BN_bn2binpad(ctx->key->dh.ffc_params.p, mod_exp.modulus, prime_size) <= 0 || BN_bn2binpad(ctx->key->dh.priv, mod_exp.exponent, prime_size) <= 0 || BN_bn2binpad(ctx->dh.derive.peer_key->dh.pub, pub, prime_size) <= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); goto out; } rc = ica_rsa_mod_expo(ctx->provctx->ica_adapter, pub, &mod_exp, buf); if (rc == 0) { z = BN_secure_new(); if (z == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto out; } z = BN_bin2bn(buf, prime_size, z); pminus1 = BN_new(); if (z == NULL || pminus1 == NULL || BN_copy(pminus1, ctx->key->dh.ffc_params.p) == NULL || BN_sub_word(pminus1, 1) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn/BN_copy/BN_sub_word failed"); goto out; } /* Error if z <= 1 or z = p - 1 */ if (BN_cmp(z, BN_value_one()) <= 0 || BN_cmp(z, pminus1) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "invalid secret"); goto out; } } else { ibmca_debug_op_ctx(ctx, "ica_rsa_mod_expo failed with: %s", strerror(rc)); rc = ibmca_keyexch_dh_derive_plain_fallback(ctx, buf, prime_size); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_dh_derive_plain_fallback failed"); rc = 0; goto out; } } if (use_tbuf) memcpy(secret, ctx->tbuf, *secretlen); if (pad == false) { for (i = 0; i < *secretlen && secret[i] == 0; i++) ; if (i > 0 && i < *secretlen) { memmove(secret, secret + i, *secretlen - i); P_CLEANSE(ctx->provctx, secret + *secretlen - i, i); *secretlen = *secretlen - i; } } rc = 1; out: if (rc != 1) *secretlen = 0; if (use_tbuf && ctx->tbuf != NULL) P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); if (z != NULL) BN_clear_free(z); if (pminus1 != NULL) BN_free(pminus1); ibmca_debug_op_ctx(ctx, "secretlen: %lu", *secretlen); return rc; } static int ibmca_keyexch_dh_kdf_x942(const struct ibmca_prov_ctx *provctx, const unsigned char *z, size_t z_len, EVP_MD *md, const unsigned char *ukm, size_t ukm_len, const char *cek_alg, unsigned char *out, size_t outlen) { int rc = 0; OSSL_PARAM params[5]; OSSL_PARAM *p; EVP_KDF *kdf = NULL; EVP_KDF_CTX *kctx = NULL; kdf = EVP_KDF_fetch(provctx->libctx, OSSL_KDF_NAME_X942KDF_ASN1, NULL); if (kdf == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to fetch KDF '%s'", OSSL_KDF_NAME_X942KDF_ASN1); goto out; } kctx = EVP_KDF_CTX_new(kdf); if (kctx == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_KDF_CTX_new failed"); goto out; } p = params; *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, (char *)EVP_MD_get0_name(md), 0); *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)z, z_len); *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, (void *)ukm, ukm_len); *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CEK_ALG, (char *)cek_alg, 0); *p = OSSL_PARAM_construct_end(); rc = EVP_KDF_derive(kctx, out, outlen, params); if (rc <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_KDF_derive failed"); goto out; } rc = 1; out: if (kctx != NULL) EVP_KDF_CTX_free(kctx); if (kdf != NULL) EVP_KDF_free(kdf); return rc; } static int ibmca_keyexch_dh_derive_x942_kdf(struct ibmca_op_ctx *ctx, unsigned char *secret, size_t *secretlen, size_t outlen) { int rc = 0; size_t len, prime_size; ibmca_debug_op_ctx(ctx, "ctx: %p secret: %p outlen: %lu", ctx, secret, outlen); *secretlen = ctx->dh.derive.kdf_outlen; if (secret == NULL) { rc = 1; goto out; } if (outlen < *secretlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); goto out; } prime_size = ctx->key->get_max_param_size(ctx->key); if (ibmca_op_alloc_tbuf(ctx, prime_size * 4) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); goto out; } rc = ibmca_keyexch_dh_derive_plain(ctx, ctx->tbuf, &len, prime_size, true); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_dh_derive_plain failed"); goto out; } rc = ibmca_keyexch_dh_kdf_x942(ctx->provctx, ctx->tbuf, len, ctx->dh.derive.kdf_md, ctx->dh.derive.kdf_ukm, ctx->dh.derive.kdf_ukmlen, ctx->dh.derive.kdf_cekalg, secret, ctx->dh.derive.kdf_outlen); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_dh_kdf_x942 failed"); goto out; } rc = 1; out: if (rc != 1) *secretlen = 0; ibmca_debug_op_ctx(ctx, "secretlen: %lu", *secretlen); if (ctx->tbuf != NULL) P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); return rc; } static int ibmca_keyexch_dh_derive(void *vctx, unsigned char *secret, size_t *secretlen, size_t outlen) { struct ibmca_op_ctx *ctx = vctx; if (ctx == NULL || secretlen == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p secret: %p outlen: %lu", ctx, secret, outlen); switch (ctx->dh.derive.kdf_type) { case EVP_PKEY_DH_KDF_X9_42: return ibmca_keyexch_dh_derive_x942_kdf(ctx, secret, secretlen, outlen); case EVP_PKEY_DH_KDF_NONE: default: return ibmca_keyexch_dh_derive_plain(ctx, secret, secretlen, outlen, ctx->dh.derive.pad); } return 0; } static int ibmca_keyexch_dh_get_ctx_params(void *vctx, OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; OSSL_PARAM *p; const char *name; int rc; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_EXCHANGE_PARAM_KDF_TYPE */ switch (ctx->dh.derive.kdf_type) { case EVP_PKEY_DH_KDF_X9_42: name = OSSL_KDF_NAME_X942KDF_ASN1; break; case EVP_PKEY_DH_KDF_NONE: default: name = ""; break; } rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_KDF_TYPE, name); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_DIGEST */ if (ctx->dh.derive.kdf_md != NULL) name = EVP_MD_get0_name(ctx->dh.derive.kdf_md); else name = ""; rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_KDF_DIGEST, name); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_OUTLEN */ rc = ibmca_param_build_set_size_t(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN, ctx->dh.derive.kdf_outlen); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_UKM */ rc = ibmca_param_build_set_octet_ptr(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_KDF_UKM, ctx->dh.derive.kdf_ukm, ctx->dh.derive.kdf_ukmlen); if (rc == 0) return 0; /* OSSL_KDF_PARAM_CEK_ALG */ rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_KDF_PARAM_CEK_ALG, ctx->dh.derive.kdf_cekalg); if (rc == 0) return 0; return 1; } static int ibmca_keyexch_dh_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; const OSSL_PARAM *p; const char *name, *props = NULL; unsigned int value; int rc; void *ukm = NULL; size_t ukmlen; EVP_MD *md; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_EXCHANGE_PARAM_PAD */ rc = ibmca_param_get_uint(ctx->provctx, params, OSSL_EXCHANGE_PARAM_PAD, &value); if (rc == 0) return 0; if (rc > 0) ctx->dh.derive.pad = (value != 0); /* OSSL_EXCHANGE_PARAM_KDF_TYPE */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_TYPE, &name); if (rc == 0) return 0; if (rc > 0) { if (name[0] == '\0') { ctx->dh.derive.kdf_type = EVP_PKEY_DH_KDF_NONE; } else if (strcmp(name, OSSL_KDF_NAME_X942KDF_ASN1) == 0) { ctx->dh.derive.kdf_type = EVP_PKEY_DH_KDF_X9_42; } else { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "DH '%s': '%s' is not supported", OSSL_EXCHANGE_PARAM_KDF_TYPE, name); return 0; } } /* OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, &props); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_DIGEST */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_DIGEST, &name); if (rc == 0) return 0; if (rc > 0) { md = EVP_MD_fetch(ctx->provctx->libctx, name, props != NULL ? props : ctx->propq); if (md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "DH '%s': '%s' could not be fetched", OSSL_EXCHANGE_PARAM_KDF_DIGEST, name); return 0; } if (ctx->dh.derive.kdf_md != NULL) EVP_MD_free(ctx->dh.derive.kdf_md); ctx->dh.derive.kdf_md = md; } /* OSSL_EXCHANGE_PARAM_KDF_OUTLEN */ rc = ibmca_param_get_size_t(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN, &ctx->dh.derive.kdf_outlen); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_UKM */ rc = ibmca_param_get_octet_string(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_UKM, &ukm, &ukmlen); if (rc == 0) return 0; if (rc > 0) { if (ctx->dh.derive.kdf_ukm != NULL) P_CLEAR_FREE(ctx->provctx, ctx->dh.derive.kdf_ukm, ctx->dh.derive.kdf_ukmlen); ctx->dh.derive.kdf_ukm = ukm; ctx->dh.derive.kdf_ukmlen = ukmlen; } /* OSSL_KDF_PARAM_CEK_ALG */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_KDF_PARAM_CEK_ALG, &name); if (rc == 0) return 0; if (rc > 0) { ctx->dh.derive.kdf_cekalg = P_STRDUP(ctx->provctx, name); if (ctx->dh.derive.kdf_cekalg == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_MALLOC_FAILED, "P_STRDUP failed"); return 0; } } return 1; } static const OSSL_PARAM ibmca_keyexch_dh_gettable_params[] = { OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0), OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keyexch_dh_gettable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; ibmca_debug_ctx(provctx, "ctx: %p", ctx); for (p = ibmca_keyexch_dh_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_keyexch_dh_gettable_params; } static const OSSL_PARAM ibmca_keyexch_dh_settable_params[] = { OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0), OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keyexch_dh_settable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; ibmca_debug_ctx(provctx, "ctx: %p", ctx); for (p = ibmca_keyexch_dh_settable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_keyexch_dh_settable_params; } static const OSSL_DISPATCH ibmca_dh_keyexch_functions[] = { /* Context management */ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))ibmca_keyexch_dh_newctx }, { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ibmca_op_freectx }, { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ibmca_op_dupctx }, /* Shared secret derivation */ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ibmca_keyexch_dh_init }, { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ibmca_keyexch_dh_set_peer }, { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ibmca_keyexch_dh_derive }, /* Key Exchange parameters */ { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))ibmca_keyexch_dh_set_ctx_params }, { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, (void (*)(void))ibmca_keyexch_dh_settable_ctx_params }, { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ibmca_keyexch_dh_get_ctx_params }, { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS, (void (*)(void))ibmca_keyexch_dh_gettable_ctx_params }, { 0, NULL } }; const OSSL_ALGORITHM ibmca_dh_keyexch[] = { { "DH:dhKeyAgreement:1.2.840.113549.1.3.1", NULL, ibmca_dh_keyexch_functions, "IBMCA DH key exchange implementation" }, { NULL, NULL, NULL, NULL } }; openssl-ibmca-2.4.1/src/provider/dh_keymgmt.c000066400000000000000000002163431450276407300212100ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include #include #include #include "p_ibmca.h" static OSSL_FUNC_keymgmt_new_fn ibmca_keymgmt_dh_new; static OSSL_FUNC_keymgmt_new_fn ibmca_keymgmt_dhx_new; static OSSL_FUNC_keymgmt_gen_init_fn ibmca_keymgmt_dh_gen_init; static OSSL_FUNC_keymgmt_gen_init_fn ibmca_keymgmt_dhx_gen_init; static OSSL_FUNC_keymgmt_gen_set_template_fn ibmca_keymgmt_dh_gen_set_template; static OSSL_FUNC_keymgmt_gen_set_params_fn ibmca_keymgmt_dh_gen_set_params; static OSSL_FUNC_keymgmt_gen_settable_params_fn ibmca_keymgmt_dh_gen_settable_params; static OSSL_FUNC_keymgmt_gen_fn ibmca_keymgmt_dh_gen; static OSSL_FUNC_keymgmt_has_fn ibmca_keymgmt_dh_has; static OSSL_FUNC_keymgmt_match_fn ibmca_keymgmt_dh_match; static OSSL_FUNC_keymgmt_validate_fn ibmca_keymgmt_dh_validate; static OSSL_FUNC_keymgmt_query_operation_name_fn ibmca_keymgmt_dh_query_operation_name; static OSSL_FUNC_keymgmt_get_params_fn ibmca_keymgmt_dh_get_params; static OSSL_FUNC_keymgmt_gettable_params_fn ibmca_keymgmt_dh_gettable_params; static OSSL_FUNC_keymgmt_set_params_fn ibmca_keymgmt_dh_set_params; static OSSL_FUNC_keymgmt_settable_params_fn ibmca_keymgmt_dh_settable_params; static OSSL_FUNC_keymgmt_export_fn ibmca_keymgmt_dh_export; static OSSL_FUNC_keymgmt_export_types_fn ibmca_keymgmt_dh_imexport_types; static OSSL_FUNC_keymgmt_import_fn ibmca_keymgmt_dh_import; static void ibmca_keymgmt_dh_free_cb(struct ibmca_key *key); static int ibmca_keymgmt_dh_dup_cb(const struct ibmca_key *key, struct ibmca_key *new_key); static size_t ibmca_keymgmt_dh_get_prime_size(const struct ibmca_key *key); static struct ibmca_key *ibmca_keymgmt_dh_new_type( const struct ibmca_prov_ctx *provctx, int type, const char *algorithm) { struct ibmca_key *key; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p type: %d algorithm: '%s'", provctx, type, algorithm); key = ibmca_keymgmt_new(provctx, type, algorithm, ibmca_keymgmt_dh_free_cb, ibmca_keymgmt_dh_dup_cb, ibmca_keymgmt_dh_get_prime_size, ibmca_keymgmt_dh_export, ibmca_keymgmt_dh_import, ibmca_keymgmt_dh_has, ibmca_keymgmt_dh_match); if (key == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_new failed"); return NULL; } key->dh.ffc_params.group_nid = NID_undef; key->dh.ffc_params.length = 0; key->dh.ffc_params.seed = NULL; key->dh.ffc_params.seed_len = 0; key->dh.ffc_params.gindex = -1; key->dh.ffc_params.pcounter = -1; key->dh.ffc_params.hindex = 0; key->dh.ffc_params.validate_pq = true; key->dh.ffc_params.validate_g = true; key->dh.ffc_params.validate_legacy = false; return key; } static void *ibmca_keymgmt_dh_new(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; return ibmca_keymgmt_dh_new_type(provctx, EVP_PKEY_DH, "DH"); } static void *ibmca_keymgmt_dhx_new(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; return ibmca_keymgmt_dh_new_type(provctx, EVP_PKEY_DHX, "DHX"); } static void ibmca_keymgmt_dh_free_cb(struct ibmca_key *key) { if (key == NULL) return; ibmca_debug_key(key, "key: %p", key); if (key->dh.priv != NULL) BN_clear_free(key->dh.priv); key->dh.priv = NULL; if (key->dh.pub != NULL) BN_free(key->dh.pub); key->dh.pub = NULL; if (key->dh.ffc_params.p != NULL) BN_free(key->dh.ffc_params.p); key->dh.ffc_params.p = NULL; if (key->dh.ffc_params.q != NULL) BN_free(key->dh.ffc_params.q); key->dh.ffc_params.q = NULL; if (key->dh.ffc_params.g != NULL) BN_free(key->dh.ffc_params.g); key->dh.ffc_params.g = NULL; if (key->dh.ffc_params.cofactor != NULL) BN_free(key->dh.ffc_params.cofactor); key->dh.ffc_params.cofactor = NULL; if (key->dh.ffc_params.seed != NULL) P_FREE(key->provctx, key->dh.ffc_params.seed); key->dh.ffc_params.seed = NULL; key->dh.ffc_params.seed_len = 0; if (key->dh.ffc_params.mdname != NULL) P_FREE(key->provctx, (char *)key->dh.ffc_params.mdname); key->dh.ffc_params.mdname = NULL; if (key->dh.ffc_params.mdprops != NULL) P_FREE(key->provctx, (char *)key->dh.ffc_params.mdprops); key->dh.ffc_params.mdprops = NULL; key->dh.ffc_params.group_nid = NID_undef; key->dh.ffc_params.length = 0; key->dh.ffc_params.gindex = -1; key->dh.ffc_params.pcounter = -1; key->dh.ffc_params.hindex = 0; key->dh.ffc_params.validate_pq = true; key->dh.ffc_params.validate_g = true; key->dh.ffc_params.validate_legacy = false; } static int ibmca_keymgmt_dh_dup_params(const struct ibmca_key *key, struct ibmca_key *new_key) { if (key == NULL || new_key == NULL) return 0; ibmca_debug_key(key, "key: %p new_key: %p", key, new_key); if (key->dh.ffc_params.p != NULL) { new_key->dh.ffc_params.p = BN_dup(key->dh.ffc_params.p); if (new_key->dh.ffc_params.p == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); return 0; } } if (key->dh.ffc_params.q != NULL) { new_key->dh.ffc_params.q = BN_dup(key->dh.ffc_params.q); if (new_key->dh.ffc_params.q == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); return 0; } } if (key->dh.ffc_params.g != NULL) { new_key->dh.ffc_params.g = BN_dup(key->dh.ffc_params.g); if (new_key->dh.ffc_params.g == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); return 0; } } if (key->dh.ffc_params.cofactor != NULL) { new_key->dh.ffc_params.cofactor = BN_dup(key->dh.ffc_params.cofactor); if (new_key->dh.ffc_params.cofactor == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); return 0; } } if (key->dh.ffc_params.seed != NULL && key->dh.ffc_params.seed_len > 0) { new_key->dh.ffc_params.seed = P_MEMDUP(key->provctx, key->dh.ffc_params.seed, key->dh.ffc_params.seed_len); if (new_key->dh.ffc_params.seed == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); return 0; } new_key->dh.ffc_params.seed_len = key->dh.ffc_params.seed_len; } new_key->dh.ffc_params.group_nid = key->dh.ffc_params.group_nid; new_key->dh.ffc_params.length = key->dh.ffc_params.length; new_key->dh.ffc_params.gindex = key->dh.ffc_params.gindex; new_key->dh.ffc_params.pcounter = key->dh.ffc_params.pcounter; new_key->dh.ffc_params.hindex = key->dh.ffc_params.hindex; new_key->dh.ffc_params.validate_pq = key->dh.ffc_params.validate_pq; new_key->dh.ffc_params.validate_g = key->dh.ffc_params.validate_g; new_key->dh.ffc_params.validate_legacy = key->dh.ffc_params.validate_legacy; return 1; } static int ibmca_keymgmt_dh_dup_cb(const struct ibmca_key *key, struct ibmca_key *new_key) { if (key == NULL || new_key == NULL) return 0; ibmca_debug_key(key, "key: %p new_key: %p", key, new_key); if (key->dh.priv != NULL) { new_key->dh.priv = BN_dup(key->dh.priv); if (new_key->dh.priv == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); return 0; } } if (key->dh.pub != NULL) { new_key->dh.pub = BN_dup(key->dh.pub); if (new_key->dh.pub == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); return 0; } } return ibmca_keymgmt_dh_dup_params(key, new_key); } static size_t ibmca_keymgmt_dh_get_prime_bits(const struct ibmca_key *key) { if (key->dh.ffc_params.p != NULL) return BN_num_bits(key->dh.ffc_params.p); put_error_key(key, IBMCA_ERR_INVALID_PARAM, "No DH parameters available"); return 0; } static size_t ibmca_keymgmt_dh_get_prime_size(const struct ibmca_key *key) { return (ibmca_keymgmt_dh_get_prime_bits(key) + 7) / 8; } static int ibmca_keymgmt_dh_get_security_bits(const struct ibmca_key *key) { int n; if (key->dh.ffc_params.p != NULL) n = BN_num_bits(key->dh.ffc_params.p); else n = key->dh.ffc_params.length; if (n == 0) n = -1; if (key->dh.ffc_params.p != NULL) return BN_security_bits(BN_num_bits(key->dh.ffc_params.p), n); put_error_key(key, IBMCA_ERR_INVALID_PARAM, "No DH parameters available"); return -1; } static void ibmca_keymgmt_dh_gen_free_cb(struct ibmca_op_ctx *ctx) { if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->dh.gen.pctx != NULL) EVP_PKEY_CTX_free(ctx->dh.gen.pctx); ctx->dh.gen.pctx = NULL; ctx->dh.gen.selection = 0; ctx->dh.gen.priv_len = 0; } static int ibmca_keymgmt_dh_gen_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p new_ctx: %p", ctx, new_ctx); if (ctx->dh.gen.pctx != NULL) { new_ctx->dh.gen.pctx = EVP_PKEY_CTX_dup(ctx->dh.gen.pctx); if (new_ctx->dh.gen.pctx == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_CTX_dup failed"); return 0; } } new_ctx->dh.gen.selection = ctx->dh.gen.selection; new_ctx->dh.gen.priv_len = ctx->dh.gen.priv_len; return 1; } static int ibmca_keymgmt_dh_gen_init_pctx(struct ibmca_op_ctx *genctx, int operation, EVP_PKEY *templ_pkey) { const char *algorithm = NULL; ibmca_debug_op_ctx(genctx, "genctx: %p operation: %d templ_pkey: %p", genctx, operation, templ_pkey); switch (genctx->type) { case EVP_PKEY_DH: algorithm = "DH"; break; case EVP_PKEY_DHX: algorithm = "DHX"; break; default: put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid context type"); return 0; } genctx->dh.gen.pctx = ibmca_new_fallback_pkey_ctx(genctx->provctx, templ_pkey, algorithm); if (genctx->dh.gen.pctx == NULL) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_new_fallback_pkey_ctx failed"); return 0; } switch (operation) { case EVP_PKEY_OP_KEYGEN: if (EVP_PKEY_keygen_init(genctx->dh.gen.pctx) != 1) { put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_keygen_init failed"); goto error; } break; case EVP_PKEY_OP_PARAMGEN: if (EVP_PKEY_paramgen_init(genctx->dh.gen.pctx) != 1) { put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_paramgen_init failed"); goto error; } break; default: put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid operation type"); goto error; } if (ibmca_check_fallback_provider(genctx->provctx, genctx->dh.gen.pctx) != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_check_fallback_provider failed"); return 0; } return 1; error: EVP_PKEY_CTX_free(genctx->dh.gen.pctx); genctx->dh.gen.pctx = NULL; return 0; } static struct ibmca_op_ctx *ibmca_keymgmt_dh_gen_init_type( const struct ibmca_prov_ctx *provctx, int selection, const OSSL_PARAM params[], int type) { struct ibmca_op_ctx *ctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p selection: 0x%x type: %d", provctx, selection, type); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0) return NULL; ctx = ibmca_keymgmt_gen_init(provctx, type, ibmca_keymgmt_dh_gen_free_cb, ibmca_keymgmt_dh_gen_dup_cb); if (ctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_gen_init failed"); return NULL; } ibmca_keymgmt_dh_gen_free_cb(ctx); ctx->dh.gen.selection = selection; if (ibmca_keymgmt_dh_gen_init_pctx(ctx, EVP_PKEY_OP_PARAMGEN, NULL) != 1) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_dh_gen_init_pctx failed"); goto error; } if (params != NULL) { if (ibmca_keymgmt_dh_gen_set_params(ctx, params) == 0) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_dh_gen_set_params failed"); goto error; } } return ctx; error: ibmca_op_freectx(ctx); return NULL; } static void *ibmca_keymgmt_dh_gen_init(void *vprovctx, int selection, const OSSL_PARAM params[]) { const struct ibmca_prov_ctx *provctx = vprovctx; return ibmca_keymgmt_dh_gen_init_type(provctx, selection, params, EVP_PKEY_DH); } static void *ibmca_keymgmt_dhx_gen_init(void *vprovctx, int selection, const OSSL_PARAM params[]) { const struct ibmca_prov_ctx *provctx = vprovctx; return ibmca_keymgmt_dh_gen_init_type(provctx, selection, params, EVP_PKEY_DHX); } static int ibmca_keymgmt_dh_gen_set_template(void *vgenctx, void *vtempl) { struct ibmca_op_ctx *genctx = vgenctx; struct ibmca_key *templ = vtempl; if (genctx == NULL || templ == NULL) return 0; ibmca_debug_op_ctx(genctx, "genctx: %p templ: %p", genctx, templ); if (genctx->type != templ->type) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "invalid template key type"); return 0; } /* Don't generate DH parameters */ if (genctx->dh.gen.pctx != NULL) EVP_PKEY_CTX_free(genctx->dh.gen.pctx); genctx->dh.gen.pctx = NULL; ibmca_keymgmt_upref(templ); genctx->key = templ; return 1; } static int ibmca_keymgmt_dh_gen_set_params(void *vgenctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *genctx = vgenctx; const OSSL_PARAM *p; int rc; if (genctx == NULL) return 0; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(genctx, "param: %s", p->key); if (genctx->dh.gen.pctx == NULL) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "Can not set parameters when template is used"); return 0; } if (EVP_PKEY_CTX_set_params(genctx->dh.gen.pctx, params) != 1) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "EVP_PKEY_CTX_set_params failed"); return 0; } /* OSSL_PKEY_PARAM_DH_PRIV_LEN */ rc = ibmca_param_get_int(genctx->provctx, params, OSSL_PKEY_PARAM_DH_PRIV_LEN, &genctx->dh.gen.priv_len); if (rc == 0) return 0; return 1; } static const OSSL_PARAM *ibmca_keymgmt_dh_gen_settable_params(void *vgenctx, void *vprovctx) { const struct ibmca_op_ctx *genctx = vgenctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p, *params; UNUSED(genctx); if (provctx == NULL) return NULL; if (genctx->dh.gen.pctx == NULL) return NULL; params = EVP_PKEY_CTX_settable_params(genctx->dh.gen.pctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return params; } static int ibmca_keymgmt_dh_gen_fallback(struct ibmca_op_ctx *genctx, struct ibmca_key *key, OSSL_CALLBACK *osslcb, void *cbarg) { struct ibmca_keygen_cb_data cbdata; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY *params = NULL; int rc = 0; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); params = ibmca_new_fallback_pkey(key); if (params == NULL) { ibmca_debug_op_ctx(genctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(genctx->provctx, params, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_keygen_init(pctx) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_keygen_init failed"); goto out; } if (ibmca_check_fallback_provider(genctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } if (osslcb != NULL) { cbdata.osslcb = osslcb; cbdata.cbarg = cbarg; EVP_PKEY_CTX_set_cb(pctx, ibmca_keygen_cb); EVP_PKEY_CTX_set_app_data(pctx, &cbdata); } if (EVP_PKEY_generate(pctx, &pkey) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_generate failed"); goto out; } rc = ibmca_import_from_fallback_pkey(key, pkey, OSSL_KEYMGMT_SELECT_ALL); if (rc != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_import_from_fallback_pkey failed"); goto out; } rc = 1; out: if (pctx != NULL) EVP_PKEY_CTX_free(pctx); if (params != NULL) EVP_PKEY_free(params); if (pkey != NULL) EVP_PKEY_free(pkey); return rc; } static int ibmca_keymgmt_dh_gen_priv_key(struct ibmca_key *key, BN_CTX *bn_ctx, int priv_len, int strength) { int rc = 0, qbits = BN_num_bits(key->dh.ffc_params.q); BIGNUM *m, *two_powN = NULL; ibmca_debug_key(key, "key: %p priv_len: %d strength: %d", key, priv_len, strength); /* Generate a private key in the interval [1, min(2 ^ N - 1, q - 1)]. */ if (priv_len == 0) priv_len = qbits; if (strength == 0) strength = priv_len / 2; if (priv_len < 2 * strength || priv_len > qbits) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "priv_len is invalid"); return 0; } two_powN = BN_new(); if (two_powN == NULL || BN_lshift(two_powN, BN_value_one(), priv_len) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_new/BN_lshift failed"); goto out; } m = (BN_cmp(two_powN, key->dh.ffc_params.q) > 0) ? key->dh.ffc_params.q : two_powN; key->dh.priv = BN_secure_new(); if (key->dh.priv == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto out; } do { if (BN_priv_rand_range_ex(key->dh.priv, two_powN, 0, bn_ctx) != 1 || BN_add_word(key->dh.priv, 1) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_priv_rand_range_ex/BN_add_word failed"); goto out; } if (BN_cmp(key->dh.priv, m) < 0) break; } while (1); rc = 1; out: if (two_powN != NULL) BN_free(two_powN); if (rc != 1 && key->dh.priv != NULL) { BN_clear_free(key->dh.priv); key->dh.priv = NULL; } return rc; } static int ibmca_keymgmt_dh_gen_libica(struct ibmca_key *key, int priv_len, OSSL_CALLBACK *osslcb, void *cbarg) { OSSL_PARAM cb_params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; int rc = 0, p, n, max_strength, len; ica_rsa_key_mod_expo_t mod_exp; BN_CTX *bn_ctx = NULL; size_t prime_size = 0; unsigned char *buf = NULL, *pub; ibmca_debug_key(key, "key: %p priv_len: %d", key, priv_len); cb_params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); cb_params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); if (ibmca_keymgmt_dh_has(key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "required DH parameters not available"); return 0; } ibmca_debug_key(key, "group_nid: %d", key->dh.ffc_params.group_nid); /* Generate private key */ p = 0; n = 0; if (osslcb != NULL && osslcb(cb_params, cbarg) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "osslcb failed"); goto out; } bn_ctx = BN_CTX_new_ex(key->provctx->libctx); if (bn_ctx == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_CTX_new_ex failed"); return 0; } if (key->dh.priv != NULL) BN_free(key->dh.priv); key->dh.priv = NULL; if (key->dh.pub != NULL) BN_free(key->dh.pub); key->dh.pub = NULL; if (key->dh.ffc_params.group_nid != NID_undef) { /* named group */ if (key->dh.ffc_params.q == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "required DH parameters not available"); goto out; } if (priv_len > BN_num_bits(key->dh.ffc_params.q)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "priv_len too large"); goto out; } max_strength = ibmca_keymgmt_dh_get_security_bits(key); if (ibmca_keymgmt_dh_gen_priv_key(key, bn_ctx, priv_len, max_strength) != 1) { ibmca_debug_key(key, "ERROR: ibmca_keymgmt_dh_gen_priv_key failed"); goto out; } } else if (key->dh.ffc_params.q == NULL) { /* secret exponent length, must satisfy 2^(l-1) <= p */ if (priv_len >= BN_num_bits(key->dh.ffc_params.p)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "priv_len too large"); goto out; } len = priv_len > 0 ? priv_len : BN_num_bits(key->dh.ffc_params.p) - 1; key->dh.priv = BN_secure_new(); if (key->dh.priv == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto out; } if (BN_priv_rand_ex(key->dh.priv, len, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY, 0, bn_ctx) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_priv_rand_ex failed"); BN_clear_free(key->dh.priv); key->dh.priv = NULL; goto out; } /* * Check for one known case where g is a quadratic non-residue: * for g = 2: p % 8 == 3 */ if (BN_is_word(key->dh.ffc_params.g, DH_GENERATOR_2) && !BN_is_bit_set(key->dh.ffc_params.p, 2)) { /* clear bit 0, since it won't be a secret anyway */ if (BN_clear_bit(key->dh.priv, 0) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_clear_bit failed"); BN_clear_free(key->dh.priv); key->dh.priv = NULL; goto out; } } } else { if (ibmca_keymgmt_dh_gen_priv_key(key, bn_ctx, BN_num_bits(key->dh.ffc_params.q), key->provctx->fips ? 112 : 80) != 1) { ibmca_debug_key(key, "ERROR: ibmca_keymgmt_dh_gen_priv_key failed"); goto out; } } /* Generate public key */ p = 1; n = 0; if (osslcb != NULL && osslcb(cb_params, cbarg) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "osslcb failed"); goto out; } prime_size = ibmca_keymgmt_dh_get_prime_size(key); buf = P_SECURE_ZALLOC(key->provctx, prime_size * 4); if (buf == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate mod-expo buffer"); goto out; } /* pub_key = g^priv_key mod p */ mod_exp.key_length = prime_size; mod_exp.modulus = buf + prime_size; mod_exp.exponent = buf + 2 * prime_size; pub = buf + 3 * prime_size; if (BN_bn2binpad(key->dh.ffc_params.p, mod_exp.modulus, prime_size) <= 0 || BN_bn2binpad(key->dh.priv, mod_exp.exponent, prime_size) <= 0 || BN_bn2binpad(key->dh.ffc_params.g, buf, prime_size) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); goto out; } rc = ica_rsa_mod_expo(key->provctx->ica_adapter, buf, &mod_exp, pub); if (rc != 0) { ibmca_debug_key(key, "ica_rsa_mod_expo failed with: %s", strerror(rc)); rc = 0; goto out; } key->dh.pub = BN_bin2bn(pub, prime_size, NULL); if (key->dh.pub == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); goto out; } p = 3; n = 0; if (osslcb != NULL && osslcb(cb_params, cbarg) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "osslcb failed"); goto out; } rc = 1; out: if (bn_ctx != NULL) BN_CTX_free(bn_ctx); if (buf != NULL) P_CLEAR_FREE(key->provctx, buf, prime_size * 4); return rc; } static void *ibmca_keymgmt_dh_gen(void *vgenctx, OSSL_CALLBACK *osslcb, void *cbarg) { struct ibmca_op_ctx *genctx = vgenctx; struct ibmca_key *key = NULL; struct ibmca_keygen_cb_data cbdata; EVP_PKEY *pkey = NULL; int rc; if (genctx == NULL) return NULL; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); key = ibmca_keymgmt_new(genctx->provctx, genctx->type, genctx->type == EVP_PKEY_DHX ? "DHX" : "DH", ibmca_keymgmt_dh_free_cb, ibmca_keymgmt_dh_dup_cb, ibmca_keymgmt_dh_get_prime_size, ibmca_keymgmt_dh_export, ibmca_keymgmt_dh_import, ibmca_keymgmt_dh_has, ibmca_keymgmt_dh_match); if (key == NULL) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_keymgmt_new failed"); return NULL; } if (genctx->dh.gen.pctx != NULL) { /* Generate DH parameters only */ if (osslcb != NULL) { cbdata.osslcb = osslcb; cbdata.cbarg = cbarg; EVP_PKEY_CTX_set_cb(genctx->dh.gen.pctx, ibmca_keygen_cb); EVP_PKEY_CTX_set_app_data(genctx->dh.gen.pctx, &cbdata); } if (EVP_PKEY_generate(genctx->dh.gen.pctx, &pkey) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_generate failed"); goto error; } rc = ibmca_import_from_fallback_pkey(key, pkey, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); if (rc != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_import_from_fallback_pkey failed"); goto error; } } else if (genctx->key != NULL) { /* Copy parameters from template key */ if (ibmca_keymgmt_dh_dup_params(genctx->key, key) != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_keymgmt_dh_dup_params failed"); goto error; } } else { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "Neither parmagen context nor template key available"); goto error; } if (genctx->dh.gen.selection & OSSL_KEYMGMT_SELECT_KEYPAIR) { if (ibmca_keymgmt_dh_gen_libica(key, genctx->dh.gen.priv_len, osslcb, cbarg) != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_keymgmt_dh_gen_libica failed"); if (ibmca_keymgmt_dh_gen_fallback(genctx, key, osslcb, cbarg) != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_keymgmt_dh_gen_fallback failed"); goto error; } } } goto out; error: ibmca_keymgmt_free(key); key = NULL; out: if (pkey != NULL) EVP_PKEY_free(pkey); return key; } static int ibmca_keymgmt_dh_has(const void *vkey, int selection) { const struct ibmca_key *key = vkey; int ok = 1; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) ok = ok && (key->dh.pub != NULL); if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) ok = ok && (key->dh.priv != NULL); if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { ok = ok && (key->dh.ffc_params.p != NULL && key->dh.ffc_params.g != NULL); if (key->type == EVP_PKEY_DHX) ok = ok && (key->dh.ffc_params.q != NULL); } ibmca_debug_key(key, "ok: %d", ok); return ok; } static int ibmca_keymgmt_dh_match(const void *vkey1, const void *vkey2, int selection) { const struct ibmca_key *key1 = vkey1; const struct ibmca_key *key2 = vkey2; int ok = 1, checked = 0; if (key1 == NULL || key2 == NULL) return 0; ibmca_debug_key(key1, "key1: %p key2: %p selection: 0x%x", key1, key2, selection); if (ibmca_keymgmt_match(key1, key2) == 0) return 0; if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { if (key1->dh.pub != NULL || key2->dh.pub != NULL) { ok = ok && (BN_cmp(key1->dh.pub, key2->dh.pub) == 0); checked = 1; } } if (!checked && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { if (key1->dh.priv != NULL || key2->dh.priv != NULL) { ok = ok && (BN_cmp(key1->dh.priv, key2->dh.priv) == 0); checked = 1; } } ok = ok && checked; } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { ok = ok && (BN_cmp(key1->dh.ffc_params.p, key2->dh.ffc_params.p) == 0); ok = ok && (BN_cmp(key1->dh.ffc_params.g, key2->dh.ffc_params.g) == 0); if (key1->type == EVP_PKEY_DHX) ok = ok && (BN_cmp(key1->dh.ffc_params.q, key2->dh.ffc_params.q) == 0); } ibmca_debug_key(key1, "ok: %d", ok); return ok; } static int ibmca_keymgmt_dh_validate(const void *vkey, int selection, int checktype) { struct ibmca_key *key = (struct ibmca_key *)vkey; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; int rc = 0; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x checktype: 0x%x", key, selection, checktype); pkey = ibmca_new_fallback_pkey(key); if (pkey == NULL) goto out; pctx = ibmca_new_fallback_pkey_ctx(key->provctx, pkey, NULL); if (pctx == NULL) goto out; if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR) { rc = EVP_PKEY_check(pctx); } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { rc = EVP_PKEY_public_check(pctx); } else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { rc = EVP_PKEY_param_check(pctx); } out: ibmca_debug_key(key, "valid: %d", rc); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); if (pkey != NULL) EVP_PKEY_free(pkey); return rc; } static const char *ibmca_keymgmt_dh_query_operation_name(int operation_id) { switch (operation_id) { case OSSL_OP_KEYEXCH: return "DH"; /* DHX also uses "DH" as operation name for KEYEXCH */ } return NULL; } static const OSSL_PARAM ibmca_dh_gettable_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_dh_gettable_params(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; for (p = ibmca_dh_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_dh_gettable_params; } static int ibmca_keymgmt_dh_get_params(void *vkey, OSSL_PARAM params[]) { struct ibmca_key *key = vkey; OSSL_PARAM *parm; const char *name; unsigned char *enc = NULL; size_t size; int rc; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p", key); for (parm = params; parm != NULL && parm->key != NULL; parm++) ibmca_debug_key(key, "param: %s", parm->key); /* OSSL_PKEY_PARAM_BITS */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS) != NULL) { size = ibmca_keymgmt_dh_get_prime_bits(key); if (size == 0) return 0; rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_BITS, size); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_SECURITY_BITS */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS) != NULL) { size = ibmca_keymgmt_dh_get_security_bits(key); if (size == 0) return 0; rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_SECURITY_BITS, size); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_MAX_SIZE */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE) != NULL) { size = ibmca_keymgmt_dh_get_prime_size(key); if (size == 0) return 0; rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_MAX_SIZE, size); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY) != NULL && key->dh.pub != NULL) { size = ibmca_keymgmt_dh_get_prime_size(key); if (size == 0) return 0; enc = P_ZALLOC(key->provctx, size); if (enc == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate encoded pubkey buffer"); return 0; } if (BN_bn2binpad(key->dh.pub, enc, size) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); P_FREE(key->provctx, enc); return 0; } rc = ibmca_param_build_set_octet_ptr(key->provctx, NULL, params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, enc, size); P_FREE(key->provctx, enc); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_PRIV_KEY */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY) != NULL && key->dh.priv != NULL) { rc = ibmca_param_build_set_bn(key->provctx, NULL, params, OSSL_PKEY_PARAM_PRIV_KEY, key->dh.priv); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_PUB_KEY */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY) != NULL && key->dh.pub != NULL) { rc = ibmca_param_build_set_bn(key->provctx, NULL, params, OSSL_PKEY_PARAM_PUB_KEY, key->dh.pub); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_P */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_P) != NULL && key->dh.ffc_params.p != NULL) { rc = ibmca_param_build_set_bn(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_P, key->dh.ffc_params.p); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_Q */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_Q) != NULL && key->dh.ffc_params.q != NULL) { rc = ibmca_param_build_set_bn(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_Q, key->dh.ffc_params.q); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_G */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_G) != NULL && key->dh.ffc_params.g != NULL) { rc = ibmca_param_build_set_bn(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_G, key->dh.ffc_params.g); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_COFACTOR */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_COFACTOR) != NULL && key->dh.ffc_params.cofactor != NULL) { rc = ibmca_param_build_set_bn(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_COFACTOR, key->dh.ffc_params.cofactor); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_GINDEX */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_GINDEX) != NULL) { rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_GINDEX, key->dh.ffc_params.gindex); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_PCOUNTER */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_PCOUNTER) != NULL) { rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_PCOUNTER, key->dh.ffc_params.pcounter); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_H */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_H) != NULL) { rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_H, key->dh.ffc_params.hindex); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_SEED */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_SEED) != NULL && key->dh.ffc_params.seed != NULL && key->dh.ffc_params.seed_len > 0) { rc = ibmca_param_build_set_octet_ptr(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_SEED, key->dh.ffc_params.seed, key->dh.ffc_params.seed_len); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_GROUP_NAME */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_GROUP_NAME) != NULL && key->dh.ffc_params.group_nid != NID_undef) { name = OBJ_nid2sn(key->dh.ffc_params.group_nid); rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_GROUP_NAME, name); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_VALIDATE_PQ */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_VALIDATE_PQ) != NULL) { rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_VALIDATE_PQ, key->dh.ffc_params.validate_pq); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_VALIDATE_G */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_VALIDATE_G) != NULL) { rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_VALIDATE_G, key->dh.ffc_params.validate_g); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY) != NULL) { rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY, key->dh.ffc_params.validate_legacy); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_DIGEST */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_DIGEST) != NULL && key->dh.ffc_params.mdname != NULL) { rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_DIGEST, key->dh.ffc_params.mdname); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_FFC_DIGEST_PROPS */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS) != NULL && key->dh.ffc_params.mdname != NULL) { rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, key->dh.ffc_params.mdprops); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_DH_PRIV_LEN */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_PRIV_LEN) != NULL && key->dh.ffc_params.length > 0) { rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_DH_PRIV_LEN, key->dh.ffc_params.length); if (rc == 0) return 0; } return 1; } static const OSSL_PARAM ibmca_dh_settable_params[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_dh_settable_params(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; for (p = ibmca_dh_settable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_dh_settable_params; } static int ibmca_keymgmt_dh_set_params(void *vkey, const OSSL_PARAM params[]) { struct ibmca_key *key = vkey; const OSSL_PARAM *parm; unsigned char *enc = NULL; size_t size = 0; int rc; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p", key); for (parm = params; parm != NULL && parm->key != NULL; parm++) ibmca_debug_key(key, "param: %s", parm->key); /* OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY */ rc = ibmca_param_get_octet_string(key->provctx, params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, (void **)&enc, &size); if (rc == 0) return 0; if (rc > 0) { if (key->dh.pub != NULL) BN_free(key->dh.pub); key->dh.pub = BN_bin2bn(enc, size, NULL); if (key->dh.pub == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); return 0; } /* public key must be same size as p */ if (BN_is_zero(key->dh.pub) || size != ibmca_keymgmt_dh_get_prime_size(key)) { BN_free(key->dh.pub); key->dh.pub = NULL; put_error_key(key, IBMCA_ERR_INVALID_PARAM, "DH '%s' invalid public key", OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); return 0; } ibmca_clean_fallback_pkey_cache(key); } return 1; } static const OSSL_PARAM ibmca_keymgmt_dh_imexport_dom_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_dh_imexport_priv_key_dom_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_dh_imexport_pub_key_dom_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_dh_imexport_key_pair_dom_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_dh_imexport_key_pair[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_dh_imexport_public_key[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_dh_imexport_private_key[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_dh_imexport_types(int selection) { selection &= (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS); switch (selection) { case OSSL_KEYMGMT_SELECT_PRIVATE_KEY: return ibmca_keymgmt_dh_imexport_private_key; case OSSL_KEYMGMT_SELECT_PUBLIC_KEY: return ibmca_keymgmt_dh_imexport_public_key; case OSSL_KEYMGMT_SELECT_KEYPAIR: return ibmca_keymgmt_dh_imexport_key_pair; case OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: return ibmca_keymgmt_dh_imexport_dom_params; case OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: return ibmca_keymgmt_dh_imexport_priv_key_dom_params; case OSSL_KEYMGMT_SELECT_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: return ibmca_keymgmt_dh_imexport_pub_key_dom_params; case OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: return ibmca_keymgmt_dh_imexport_key_pair_dom_params; } return NULL; } static int ibmca_keymgmt_dh_export(void *vkey, int selection, OSSL_CALLBACK *param_callback, void *cbarg) { struct ibmca_key *key = vkey; OSSL_PARAM_BLD *bld; OSSL_PARAM *params = NULL; const char *name; int rc = 1; if (key == NULL || param_callback == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); bld = OSSL_PARAM_BLD_new(); if (bld == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "OSSL_PARAM_BLD_new failed"); return 0; } /* Domain parameters are required when exporting public or private key */ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { /* OSSL_PKEY_PARAM_PUB_KEY */ if (key->dh.pub != NULL) { rc = ibmca_param_build_set_bn(key->provctx, bld, NULL, OSSL_PKEY_PARAM_PUB_KEY, key->dh.pub); if (rc == 0) goto error; } } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { /* OSSL_PKEY_PARAM_PRIV_KEY */ if (key->dh.priv != NULL) { rc = ibmca_param_build_set_bn(key->provctx, bld, NULL, OSSL_PKEY_PARAM_PRIV_KEY, key->dh.priv); if (rc == 0) goto error; } } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { /* OSSL_PKEY_PARAM_FFC_P */ if (key->dh.ffc_params.p != NULL) { rc = ibmca_param_build_set_bn(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_P, key->dh.ffc_params.p); if (rc == 0) goto error; } /* OSSL_PKEY_PARAM_FFC_Q */ if (key->dh.ffc_params.q != NULL) { rc = ibmca_param_build_set_bn(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_Q, key->dh.ffc_params.q); if (rc == 0) goto error; } /* OSSL_PKEY_PARAM_FFC_G */ if (key->dh.ffc_params.g != NULL) { rc = ibmca_param_build_set_bn(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_G, key->dh.ffc_params.g); if (rc == 0) goto error; } /* OSSL_PKEY_PARAM_FFC_COFACTOR */ if (key->dh.ffc_params.cofactor != NULL) { rc = ibmca_param_build_set_bn(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_COFACTOR, key->dh.ffc_params.cofactor); if (rc == 0) goto error; } /* OSSL_PKEY_PARAM_FFC_GINDEX */ rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_GINDEX, key->dh.ffc_params.gindex); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_FFC_PCOUNTER */ rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_PCOUNTER, key->dh.ffc_params.pcounter); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_FFC_H */ rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_H, key->dh.ffc_params.hindex); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_FFC_SEED */ if (key->dh.ffc_params.seed != NULL && key->dh.ffc_params.seed_len > 0) { rc = ibmca_param_build_set_octet_ptr(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_SEED, key->dh.ffc_params.seed, key->dh.ffc_params.seed_len); if (rc == 0) goto error; } /* OSSL_PKEY_PARAM_GROUP_NAME */ if (key->dh.ffc_params.group_nid != NID_undef) { name = OBJ_nid2sn(key->dh.ffc_params.group_nid); rc = ibmca_param_build_set_utf8(key->provctx, bld, NULL, OSSL_PKEY_PARAM_GROUP_NAME, name); if (rc == 0) goto error; } /* OSSL_PKEY_PARAM_FFC_VALIDATE_PQ */ rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_VALIDATE_PQ, key->dh.ffc_params.validate_pq); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_FFC_VALIDATE_G */ rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_VALIDATE_G, key->dh.ffc_params.validate_g); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY */ rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY, key->dh.ffc_params.validate_legacy); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_FFC_DIGEST */ if (key->dh.ffc_params.mdname != NULL) { rc = ibmca_param_build_set_utf8(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_DIGEST, key->dh.ffc_params.mdname); if (rc == 0) goto error; } /* OSSL_PKEY_PARAM_FFC_DIGEST_PROPS */ if (key->dh.ffc_params.mdname != NULL) { rc = ibmca_param_build_set_utf8(key->provctx, bld, NULL, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, key->dh.ffc_params.mdprops); if (rc == 0) goto error; } /* OSSL_PKEY_PARAM_DH_PRIV_LEN */ if (key->dh.ffc_params.length > 0) { rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_DH_PRIV_LEN, key->dh.ffc_params.length); if (rc == 0) goto error; } } params = OSSL_PARAM_BLD_to_param(bld); if (params == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "OSSL_PARAM_BLD_to_param failed"); rc = 0; goto error; } rc = param_callback(params, cbarg); OSSL_PARAM_free(params); error: OSSL_PARAM_BLD_free(bld); return rc; } static int ibmca_keymgmt_dh_import(void *vkey, int selection, const OSSL_PARAM params[]) { struct ibmca_key *key = vkey; const OSSL_PARAM *parm; const char *name; int rc = 0, val; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); for (parm = params; parm != NULL && parm->key != NULL; parm++) ibmca_debug_key(key, "param: %s", parm->key); if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "Nothing to import"); return 0; } /* Clear any already existing key components */ ibmca_keymgmt_dh_free_cb(key); ibmca_clean_fallback_pkey_cache(key); if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { /* OSSL_PKEY_PARAM_PUB_KEY */ rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_PUB_KEY, &key->dh.pub); if (rc == 0) return 0; } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { /* OSSL_PKEY_PARAM_PRIV_KEY */ key->dh.priv = BN_secure_new(); if (key->dh.priv == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); return 0; } rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_PRIV_KEY, &key->dh.priv); if (rc <= 0) { BN_clear_free(key->dh.priv); key->dh.priv = NULL; } if (rc == 0) return 0; } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { /* OSSL_PKEY_PARAM_FFC_P */ rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_FFC_P, &key->dh.ffc_params.p); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_FFC_Q */ rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_FFC_Q, &key->dh.ffc_params.q); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_FFC_G */ rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_FFC_G, &key->dh.ffc_params.g); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_FFC_COFACTOR */ rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_FFC_COFACTOR, &key->dh.ffc_params.cofactor); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_FFC_GINDEX */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_FFC_GINDEX, &key->dh.ffc_params.gindex); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_FFC_PCOUNTER */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_FFC_PCOUNTER, &key->dh.ffc_params.pcounter); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_FFC_H */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_FFC_H, &key->dh.ffc_params.hindex); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_FFC_SEED */ rc = ibmca_param_get_octet_string(key->provctx, params, OSSL_PKEY_PARAM_FFC_SEED, (void **)&key->dh.ffc_params.seed, &key->dh.ffc_params.seed_len); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_GROUP_NAME */ rc = ibmca_param_get_utf8(key->provctx, params, OSSL_PKEY_PARAM_GROUP_NAME, &name); if (rc == 0) return 0; if (rc > 0) { key->dh.ffc_params.group_nid = OBJ_sn2nid(name); if (key->dh.ffc_params.group_nid == NID_undef) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "DH '%s': '%s' is an unsupported group", OSSL_PKEY_PARAM_GROUP_NAME, name); return 0; } ibmca_debug_key(key, "group_nid: %d", key->dh.ffc_params.group_nid); } /* OSSL_PKEY_PARAM_FFC_VALIDATE_PQ */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_FFC_VALIDATE_PQ, &val); if (rc == 0) return 0; if (rc > 0) key->dh.ffc_params.validate_pq = val; /* OSSL_PKEY_PARAM_FFC_VALIDATE_G */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_FFC_VALIDATE_G, &val); if (rc == 0) return 0; if (rc > 0) key->dh.ffc_params.validate_g = val; /* OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_FFC_VALIDATE_LEGACY, &val); if (rc == 0) return 0; if (rc > 0) key->dh.ffc_params.validate_legacy = val; /* OSSL_PKEY_PARAM_FFC_DIGEST */ rc = ibmca_param_get_utf8(key->provctx, params, OSSL_PKEY_PARAM_FFC_DIGEST, &name); if (rc == 0) return 0; if (rc > 0) { key->dh.ffc_params.mdname = P_STRDUP(key->provctx, name); if (key->dh.ffc_params.mdname == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "P_STRDUP failed"); return 0; } } /* OSSL_PKEY_PARAM_FFC_DIGEST_PROPS */ rc = ibmca_param_get_utf8(key->provctx, params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, &name); if (rc == 0) return 0; if (rc > 0) { key->dh.ffc_params.mdprops = P_STRDUP(key->provctx, name); if (key->dh.ffc_params.mdprops == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "P_STRDUP failed"); return 0; } } /* OSSL_PKEY_PARAM_DH_PRIV_LEN */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_DH_PRIV_LEN, &key->dh.ffc_params.length); if (rc == 0) return 0; } return 1; } static const OSSL_DISPATCH ibmca_dh_keymgmt_functions[] = { /* Constructor, destructor */ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ibmca_keymgmt_dh_new }, { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ibmca_keymgmt_free }, { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ibmca_keymgmt_dup }, /* Key generation and loading */ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ibmca_keymgmt_dh_gen_init }, { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))ibmca_keymgmt_dh_gen_set_template }, { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ibmca_keymgmt_dh_gen_set_params }, { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))ibmca_keymgmt_dh_gen_settable_params }, { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ibmca_keymgmt_dh_gen }, { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ibmca_keymgmt_gen_cleanup }, { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ibmca_keymgmt_load }, /* Key object checking */ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ibmca_keymgmt_dh_has }, { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ibmca_keymgmt_dh_match }, { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ibmca_keymgmt_dh_validate }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ibmca_keymgmt_dh_query_operation_name }, /* Key object information */ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ibmca_keymgmt_dh_get_params }, { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ibmca_keymgmt_dh_gettable_params }, { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ibmca_keymgmt_dh_set_params }, { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ibmca_keymgmt_dh_settable_params }, /* Import and export routines */ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ibmca_keymgmt_dh_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ibmca_keymgmt_dh_imexport_types }, { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ibmca_keymgmt_dh_import }, { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ibmca_keymgmt_dh_imexport_types }, { 0, NULL } }; static const OSSL_DISPATCH ibmca_dhx_keymgmt_functions[] = { /* Constructor, destructor */ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ibmca_keymgmt_dhx_new }, { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ibmca_keymgmt_free }, { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ibmca_keymgmt_dup }, /* Key generation and loading */ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ibmca_keymgmt_dhx_gen_init }, { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))ibmca_keymgmt_dh_gen_set_template }, { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ibmca_keymgmt_dh_gen_set_params }, { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))ibmca_keymgmt_dh_gen_settable_params }, { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ibmca_keymgmt_dh_gen }, { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ibmca_keymgmt_gen_cleanup }, { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ibmca_keymgmt_load }, /* Key object checking */ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ibmca_keymgmt_dh_has }, { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ibmca_keymgmt_dh_match }, { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ibmca_keymgmt_dh_validate }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ibmca_keymgmt_dh_query_operation_name }, /* Key object information */ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ibmca_keymgmt_dh_get_params }, { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ibmca_keymgmt_dh_gettable_params }, { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ibmca_keymgmt_dh_set_params }, { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ibmca_keymgmt_dh_settable_params }, /* Import and export routines */ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ibmca_keymgmt_dh_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ibmca_keymgmt_dh_imexport_types }, { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ibmca_keymgmt_dh_import }, { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ibmca_keymgmt_dh_imexport_types }, { 0, NULL } }; const OSSL_ALGORITHM ibmca_dh_keymgmt[] = { { "DH:dhKeyAgreement:1.2.840.113549.1.3.1", NULL, ibmca_dh_keymgmt_functions, "IBMCA DH implementation" }, { "DHX:X9.42 DH:dhpublicnumber:1.2.840.10046.2.1", NULL, ibmca_dhx_keymgmt_functions, "IBMCA DHX implementation" }, { NULL, NULL, NULL, NULL } }; struct ibmca_tls_group_constants { unsigned int group_id; unsigned int secbits; int mintls; int maxtls; int mindtls; int maxdtls; }; #define IBMCA_TLS_GROUP_ID_ffdhe2048 256 #define IBMCA_TLS_GROUP_ID_ffdhe3072 257 #define IBMCA_TLS_GROUP_ID_ffdhe4096 258 #define IBMCA_TLS_GROUP_ID_ffdhe6144 259 #define IBMCA_TLS_GROUP_ID_ffdhe8192 260 static const struct ibmca_tls_group_constants ibmca_tls_group_consts[5] = { { IBMCA_TLS_GROUP_ID_ffdhe2048, 112, TLS1_3_VERSION, 0, -1, -1 }, { IBMCA_TLS_GROUP_ID_ffdhe3072, 128, TLS1_3_VERSION, 0, -1, -1 }, { IBMCA_TLS_GROUP_ID_ffdhe4096, 128, TLS1_3_VERSION, 0, -1, -1 }, { IBMCA_TLS_GROUP_ID_ffdhe6144, 128, TLS1_3_VERSION, 0, -1, -1 }, { IBMCA_TLS_GROUP_ID_ffdhe8192, 192, TLS1_3_VERSION, 0, -1, -1 }, }; #define IBMCA_TLS_GROUP_ENTRY(tlsname, realname, algorithm, idx) \ { \ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, \ tlsname, sizeof(tlsname)), \ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, \ realname, sizeof(realname)), \ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, \ algorithm, sizeof(algorithm)), \ OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, \ (unsigned int *)&ibmca_tls_group_consts[idx].group_id), \ OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, \ (unsigned int *)&ibmca_tls_group_consts[idx].secbits), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, \ (unsigned int *)&ibmca_tls_group_consts[idx].mintls), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, \ (unsigned int *)&ibmca_tls_group_consts[idx].maxtls), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, \ (unsigned int *)&ibmca_tls_group_consts[idx].mindtls), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, \ (unsigned int *)&ibmca_tls_group_consts[idx].maxdtls), \ OSSL_PARAM_END \ } static const OSSL_PARAM ibmca_dh_ffdhe2048[] = IBMCA_TLS_GROUP_ENTRY("ffdhe2048", "ffdhe2048", "DH", 0); static const OSSL_PARAM ibmca_dh_ffdhe3072[] = IBMCA_TLS_GROUP_ENTRY("ffdhe3072", "ffdhe3072", "DH", 1); static const OSSL_PARAM ibmca_dh_ffdhe4096[] = IBMCA_TLS_GROUP_ENTRY("ffdhe4096", "ffdhe4096", "DH", 2); static const OSSL_PARAM ibmca_dh_ffdhe6144[] = IBMCA_TLS_GROUP_ENTRY("ffdhe6144", "ffdhe6144", "DH", 3); static const OSSL_PARAM ibmca_dh_ffdhe8192[] = IBMCA_TLS_GROUP_ENTRY("ffdhe8192", "ffdhe8192", "DH", 4); static const OSSL_PARAM *ibmca_dh_tls_group[] = { ibmca_dh_ffdhe2048, ibmca_dh_ffdhe3072, ibmca_dh_ffdhe4096, ibmca_dh_ffdhe6144, ibmca_dh_ffdhe8192, NULL }; const struct ibmca_mech_capability ibmca_dh_capabilities[] = { { "TLS-GROUP", ibmca_dh_tls_group }, { NULL, NULL } }; openssl-ibmca-2.4.1/src/provider/doc/000077500000000000000000000000001450276407300174505ustar00rootroot00000000000000openssl-ibmca-2.4.1/src/provider/doc/Makefile.am000066400000000000000000000000751450276407300215060ustar00rootroot00000000000000man5_MANS = ibmca-provider.man dist_man5_MANS = $(man5_MANS) openssl-ibmca-2.4.1/src/provider/doc/ibmca-provider.man000066400000000000000000000201441450276407300230510ustar00rootroot00000000000000.\" .\" Copyright [2021-2022] 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. .\" .\" Process this file with .\" groff -man -Tascii ibmca-provider.5 .TH IBMCA-PROVIDER 5 February 2022 IBM "IBMCA-PROVIDER user manual" .SH NAME IBMCA-PROVIDER \- IBMCA-PROVIDER is an OpenSSL provider that uses the libica library under s390x to accelerate cryptographic operations. .SH DESCRIPTION IBMCA-PROVIDER accelerates cryptographic operations of applications that use OpenSSL. The provider can be configured by the OpenSSL configuration file. .P The IBMCA-PROVIDER links the \fBlibica-cex\fP library that can accelerate RSA, EC, and DH operations. Other (e.g. symmetric or digest) operations are not supported by the IBMCA-PROVIDER. Those are provided by the OpenSSL default provider (or others). Operations such as the AES cipher, as well as digest oprations are accelerated by CPACF by the OpenSSL default provider already. There is no need to use another provider for accelerating those. .SS openssl.cnf The OpenSSL configuration file can have a section for the IBMCA provider. This section includes the identity (i.e. name) of the provider (i.e. ibmca), the module implementing the provider (ibmca-provider.so), provider parameters, and if it is to be activated automatically. For a description of the provider parameter, see below. .P Additionally, the OpenSSL configuration file can have a \fBalg_section\fP section. There, the default property query can be specified. To prefer using the IBMCA provider, but fall back to other providers (i.e. the default provider) specify: .P \fBdefault_properties = ?provider=ibmca\fP. .SH OPTIONS .SS openssl.cnf Options for the IBMCA provider section in openssl.cnf: .PP identity = .I ibmca .RS Set the name of the IBMCA provider. The name of the provider is used in the property query string used to fetch the provider for an operation. If no identity is specified, the name from the provider section of the OpenSSL config file is used, e.g. for an entry like \fBibmca_provider = ibmca_sect\fP in the provider section, the name would be \fBibmca_provider\fP. .RE .PP module = .I ibmca-provider.so .RS Set the name and optionally the path to the IBMCA provider shared object file allowing OpenSSL to find the file. Usually, providers are loaded from the OpenSSL \fBMODULESDIR\fP. Use \fBopenssl version -m\fP to display the MODULESDIR used by OpenSSL. Set environment variable \fBOPENSSL_MODULES\fP to override the OpenSSL modules directory (ignored in set-user-ID and set-group-ID programs). .RE .IP "activate = 1" .RS OpenSSL will activate the provider if this option is set to 1. .RE .PP algorithms = ALL | .I mechanisms .RS Redirect all cryptographic operations through the provider or disable types of mechanisms that the provider supports. If ALL is not used, the algorithms consist of a comma separated list of .I mechanisms : \fBRSA\fP | \fBEC\fP | \fBDH\fP. If this option is not specified, \fBALL\fP is the default. .PP .B Note: Depending on the hardware level (IBM z15), EC is already accelerated implicitly by OpenSSL for certain curves. Therefore, do not accelerate EC using the IBMCA provider if you are on an IBM z15 or later. This would actually make it slower. .RE .PP .IP "debug = yes | no | stderr" .RS Enables debug output for the IBMCA provider. If this option is not specified, no debugging output is produced. If \fBdebug = stderr\fP is specified, debugging messages are printed to stderr. Otherwise the debug output is written into a trace file in \fB/trace-.\fP, where is the path name of a directory to where the debug files are written (default: \fB/tmp\fP), is the name of the IBMCA provider from the identity option, and is the process ID of the current process. You can also enable debugging by setting the environment variable \fBIBMCA_DEBUG\fP to \fBon\fP or \fBstderr\fP. .RE .PP .IP "debug-path = /dir/to/debug/directory" .RS Sets the directory path to where debug files are written when debug is enabled via \fBdebug = yes\fP or via environment variable \fBIBMCA_DEBUG=on\fP. You can also set the debug path by setting the environment variable \fBIBMCA_DEBUG_PATH\fP to the directory path. It must be ensured that the user under which the application that uses the IBMCA provider runs has write access to that directory. If this option is not specified, the default debug path is \fB/tmp\fP. .RE .PP .IP "fips = yes | no" .RS Enables FIPS mode for the IBMCA provider. If FIPS is enabled, it is ensured that the \fBlibica-cex\fP library is built with FIPS enabled, and the system is running in FIPS mode. If that's not the case, the IBMCA provider initialization fails, and a syslog message is issued. If the fips option is not specified, it is auto-detected if the \fBlibica-cex\fP library is built with FIPS enabled, and the system is running in FIPS mode. If both is true, then the FIPS mode is enabled for the IBMCA provider. If FIPS is enabled (either explicitly configured or due to auto-detection), the IBMCA provider registers its algorithm with \fBfips=yes\fP, thus the IBMCA algorithms may be fetched using a property query string containing \fBfips=yes\fP. .PP .B Note: The IBMCA provider is currently not FIPS certified. It does not itself perform any FIPS self tests nor an integrity check which would be required to be FIPS certifiable. It is only ensured that \fBlibica-cex\fP library has successfully performed its self tests and integrity checks when FIPS mode is enabled. If you do not want that the IBMCA provider is used for property queries that include \fBfips=yes\fP, then disable FIPS mode of the IBMCA provider by setting \fBfips = no\fP in the provider configuration. .RE .PP fallback-properties = .I property-query-string .RS A property query string that is used to fetch algorithms for fallback purposes. Fallbacks take place when the \fBlibica-cex\fP library does not support a certain key size or EC curve, or if the \fBlibica-cex\fP library fails to perform a crypto operation for whatever reason. If this option is not specified, a fallback property query string is built automatically as follows: \fBprovider!=[,fips=yes]\fP. Clause \fBfips=yes\fP is included if FIPS mode is enabled for the IBMCA provider (either explicitly configured or due to auto-detection). Note that the IBMCA provider itself can not be used as fallback provider. Thus, the fallback property query string must either select a certain provider explicitly (e.g. \fBprovider=default\fP), or must exclude the IBMCA provider (\fBprovider!=\fP). If FIPS mode is enabled for the IBMCA provider, the fallback provider should also be FIPS-enabled. Include \fBfips=yes\fP into the fallback property query string, or explicitly select the FIPS provider (\fBprovider=fips\fP). .RE .PP .SH ENVIRONMENT .TP .BR IBMCA_DEBUG If .B $IBMCA_DEBUG is set to \fBstderr\fP debug output to stderr for the IBMCA provider is enabled. If it is set to \fBon\fP the debug output is written into a trace file in \fB/trace-.\fP, where is the path name of a directory to where the debug files are written (default: \fB/tmp\fP), is the name of the IBMCA provider from the identity option, and is the process ID of the current process. .PP .TP .BR IBMCA_DEBUG_PATH Sets the directory path to where debug files are written when debug is enabled via \fBdebug = yes\fP configuration option or via environment variable \fBIBMCA_DEBUG=on\fP. It must be ensured that the user under which the application that uses the IBMCA provider runs has write access to that directory. .PP .SH SEE ALSO .B provider(1) .B config(5)openssl-ibmca-2.4.1/src/provider/ec_keyexch.c000066400000000000000000000566431450276407300211740ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include #include "p_ibmca.h" static OSSL_FUNC_keyexch_newctx_fn ibmca_keyexch_ec_newctx; static OSSL_FUNC_keyexch_init_fn ibmca_keyexch_ec_init; static OSSL_FUNC_keyexch_set_peer_fn ibmca_keyexch_ec_set_peer; static OSSL_FUNC_keyexch_derive_fn ibmca_keyexch_ec_derive; static OSSL_FUNC_keyexch_set_ctx_params_fn ibmca_keyexch_ec_set_ctx_params; static OSSL_FUNC_keyexch_settable_ctx_params_fn ibmca_keyexch_ec_settable_ctx_params; static OSSL_FUNC_keyexch_get_ctx_params_fn ibmca_keyexch_ec_get_ctx_params; static OSSL_FUNC_keyexch_gettable_ctx_params_fn ibmca_keyexch_ec_gettable_ctx_params; static void ibmca_keyexch_ec_free_cb(struct ibmca_op_ctx *ctx); static int ibmca_keyexch_ec_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx); static int ibmca_keyexch_ec_set_ctx_params(void *vctx, const OSSL_PARAM params[]); static void *ibmca_keyexch_ec_newctx(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; struct ibmca_op_ctx *opctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); opctx = ibmca_op_newctx(provctx, NULL, EVP_PKEY_EC, ibmca_keyexch_ec_free_cb, ibmca_keyexch_ec_dup_cb); if (opctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_op_newctx failed"); return NULL; } ibmca_debug_ctx(provctx, "opctx: %p", opctx); return opctx; } static void ibmca_keyexch_ec_free_cb(struct ibmca_op_ctx *ctx) { if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->ec.derive.peer_key != NULL) ibmca_keymgmt_free(ctx->ec.derive.peer_key); ctx->ec.derive.peer_key = NULL; ctx->ec.derive.kdf_type = EVP_PKEY_ECDH_KDF_NONE; if (ctx->ec.derive.kdf_md != NULL) EVP_MD_free(ctx->ec.derive.kdf_md); ctx->ec.derive.kdf_md = NULL; ctx->ec.derive.kdf_outlen = 0; if (ctx->ec.derive.kdf_ukm != NULL) P_CLEAR_FREE(ctx->provctx, ctx->ec.derive.kdf_ukm, ctx->ec.derive.kdf_ukmlen); ctx->ec.derive.kdf_ukm = NULL; ctx->ec.derive.kdf_ukmlen = 0; } static int ibmca_keyexch_ec_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p new_ctx: %p", ctx, new_ctx); if (ctx->ec.derive.peer_key != NULL) { new_ctx->ec.derive.peer_key = ctx->ec.derive.peer_key; ibmca_keymgmt_upref(new_ctx->ec.derive.peer_key); } new_ctx->ec.derive.kdf_type = ctx->ec.derive.kdf_type; new_ctx->ec.derive.kdf_md = ctx->ec.derive.kdf_md; if (new_ctx->ec.derive.kdf_md != NULL) { if (EVP_MD_up_ref(new_ctx->ec.derive.kdf_md) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_up_ref failed"); return 0; } } new_ctx->ec.derive.kdf_outlen = ctx->ec.derive.kdf_outlen; if (ctx->ec.derive.kdf_ukm != NULL && ctx->ec.derive.kdf_ukmlen > 0) { new_ctx->ec.derive.kdf_ukm = P_MEMDUP(ctx->provctx, ctx->ec.derive.kdf_ukm, ctx->ec.derive.kdf_ukmlen); if (new_ctx->ec.derive.kdf_ukm == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_MALLOC_FAILED, "P_MEMDUP failed"); return 0; } new_ctx->ec.derive.kdf_ukmlen = ctx->ec.derive.kdf_ukmlen; } return 1; } static int ibmca_keyexch_ec_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; const OSSL_PARAM *p; if (ctx == NULL || key == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); if (ibmca_op_init(ctx, key, EVP_PKEY_OP_DERIVE) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_init failed"); return 0; } /* Setup defaults for this context */ ibmca_keyexch_ec_free_cb(ctx); if (params != NULL) { if (ibmca_keyexch_ec_set_ctx_params(ctx, params) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_ec_set_ctx_params failed"); return 0; } } return 1; } static int ibmca_keyexch_ec_set_peer(void *vctx, void *vkey) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; if (ctx == NULL || key == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key); if (key->type != EVP_PKEY_EC) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Peer key is not an EC key"); return 0; } if (ctx->key->match(ctx->key, key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Peer key uses a different EC curve"); return 0; } if (key->has(key, OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Peer key does not contain a public EC key"); return 0; } ibmca_keymgmt_upref(key); if (ctx->ec.derive.peer_key != NULL) ibmca_keymgmt_free(ctx->ec.derive.peer_key); ctx->ec.derive.peer_key = key; return 1; } static int ibmca_keyexch_ec_derive_plain_fallback(struct ibmca_op_ctx *ctx, unsigned char *secret, size_t outlen) { EVP_PKEY *pkey = NULL; EVP_PKEY *peer = NULL; EVP_PKEY_CTX *pctx = NULL; size_t keylen; int rc = 0; ibmca_debug_op_ctx(ctx, "ctx: %p secret: %p outlen: %lu", ctx, secret, outlen); pkey = ibmca_new_fallback_pkey(ctx->key); if (pkey == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } peer = ibmca_new_fallback_pkey(ctx->ec.derive.peer_key); if (peer == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(ctx->provctx, pkey, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_derive_init(pctx) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_derive_init failed"); goto out; } if (ibmca_check_fallback_provider(ctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } if (EVP_PKEY_derive_set_peer(pctx, peer) != 1 || EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_NONE) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_derive_set_peer/EVP_PKEY_CTX_set_ecdh_kdf_type failed"); goto out; } keylen = outlen; if (EVP_PKEY_derive(pctx, secret, &keylen) != 1 || keylen != outlen) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_derive failed"); goto out; } rc = 1; out: if (pkey != NULL) EVP_PKEY_free(pkey); if (peer != NULL) EVP_PKEY_free(peer); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); return rc; } static int ibmca_keyexch_ec_derive_plain(struct ibmca_op_ctx *ctx, unsigned char *secret, size_t *secretlen, size_t outlen) { int rc = 0; unsigned char *buf; bool use_tbuf = false; ibmca_debug_op_ctx(ctx, "ctx: %p secret: %p outlen: %lu", ctx, secret, outlen); if (secret == NULL) { *secretlen = ctx->key->ec.prime_size; rc = 1; goto out; } *secretlen = outlen < ctx->key->ec.prime_size ? outlen : ctx->key->ec.prime_size; if (*secretlen == ctx->key->ec.prime_size) { buf = secret; } else { if (ibmca_op_alloc_tbuf(ctx, ctx->key->ec.prime_size) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); goto out; } buf = ctx->tbuf; use_tbuf = true; } if (ctx->key->ec.fallback.d != NULL || (ctx->ec.derive.peer_key->ec.fallback.x != NULL && ctx->ec.derive.peer_key->ec.fallback.y != NULL)) { rc = ibmca_keyexch_ec_derive_plain_fallback(ctx, buf, ctx->key->ec.prime_size); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_ec_derive_plain_fallback failed"); rc = 0; goto out; } goto copy; } rc = ica_ecdh_derive_secret(ctx->provctx->ica_adapter, ctx->key->ec.key, ctx->ec.derive.peer_key->ec.key, buf, ctx->key->ec.prime_size); if (rc != 0) { ibmca_debug_op_ctx(ctx, "ica_ecdh_derive_secret failed with: %s", strerror(rc)); rc = ibmca_keyexch_ec_derive_plain_fallback(ctx, buf, ctx->key->ec.prime_size); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_ec_derive_plain_fallback failed"); rc = 0; goto out; } } copy: if (use_tbuf) memcpy(secret, ctx->tbuf, *secretlen); rc = 1; out: if (rc != 1) *secretlen = 0; if (use_tbuf && ctx->tbuf != NULL) P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); ibmca_debug_op_ctx(ctx, "secretlen: %lu", *secretlen); return rc; } static int ibmca_keyexch_ec_kdf_x963(const struct ibmca_prov_ctx *provctx, const unsigned char *z, size_t z_len, EVP_MD *md, const unsigned char *ukm, size_t ukm_len, unsigned char *out, size_t outlen) { int rc = 0; OSSL_PARAM params[4]; OSSL_PARAM *p; EVP_KDF *kdf = NULL; EVP_KDF_CTX *kctx = NULL; kdf = EVP_KDF_fetch(provctx->libctx, OSSL_KDF_NAME_X963KDF, NULL); if (kdf == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to fetch KDF '%s'", OSSL_KDF_NAME_X963KDF); goto out; } kctx = EVP_KDF_CTX_new(kdf); if (kctx == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_KDF_CTX_new failed"); goto out; } p = params; *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, (char *)EVP_MD_get0_name(md), 0); *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)z, z_len); *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, (void *)ukm, ukm_len); *p = OSSL_PARAM_construct_end(); rc = EVP_KDF_derive(kctx, out, outlen, params); if (rc <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_KDF_derive failed"); goto out; } rc = 1; out: if (kctx != NULL) EVP_KDF_CTX_free(kctx); if (kdf != NULL) EVP_KDF_free(kdf); return rc; } static int ibmca_keyexch_ec_derive_x963_kdf(struct ibmca_op_ctx *ctx, unsigned char *secret, size_t *secretlen, size_t outlen) { int rc = 0; size_t len; ibmca_debug_op_ctx(ctx, "ctx: %p secret: %p outlen: %lu", ctx, secret, outlen); *secretlen = ctx->ec.derive.kdf_outlen; if (secret == NULL) { rc = 1; goto out; } if (outlen < *secretlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); goto out; } if (ibmca_op_alloc_tbuf(ctx, ctx->key->ec.prime_size) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); goto out; } rc = ibmca_keyexch_ec_derive_plain(ctx, ctx->tbuf, &len, ctx->key->ec.prime_size); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_ec_derive_plain failed"); goto out; } rc = ibmca_keyexch_ec_kdf_x963(ctx->provctx, ctx->tbuf, ctx->key->ec.prime_size, ctx->ec.derive.kdf_md, ctx->ec.derive.kdf_ukm, ctx->ec.derive.kdf_ukmlen, secret, ctx->ec.derive.kdf_outlen); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_keyexch_ec_alloc_tbuf failed"); goto out; } rc = 1; out: if (rc != 1) *secretlen = 0; ibmca_debug_op_ctx(ctx, "secretlen: %lu", *secretlen); if (ctx->tbuf != NULL) P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); return rc; } static int ibmca_keyexch_ec_derive(void *vctx, unsigned char *secret, size_t *secretlen, size_t outlen) { struct ibmca_op_ctx *ctx = vctx; if (ctx == NULL || secretlen == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p secret: %p outlen: %lu", ctx, secret, outlen); switch (ctx->ec.derive.kdf_type) { case EVP_PKEY_ECDH_KDF_X9_63: return ibmca_keyexch_ec_derive_x963_kdf(ctx, secret, secretlen, outlen); case EVP_PKEY_ECDH_KDF_NONE: default: return ibmca_keyexch_ec_derive_plain(ctx, secret, secretlen, outlen); } return 0; } static int ibmca_keyexch_ec_get_ctx_params(void *vctx, OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; OSSL_PARAM *p; const char *name; int rc; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE */ rc = ibmca_param_build_set_int(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, 0); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_TYPE */ switch (ctx->ec.derive.kdf_type) { case EVP_PKEY_ECDH_KDF_X9_63: name = OSSL_KDF_NAME_X963KDF; break; case EVP_PKEY_ECDH_KDF_NONE: default: name = ""; break; } rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_KDF_TYPE, name); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_DIGEST */ if (ctx->ec.derive.kdf_md != NULL) name = EVP_MD_get0_name(ctx->ec.derive.kdf_md); else name = ""; rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_KDF_DIGEST, name); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_OUTLEN */ rc = ibmca_param_build_set_size_t(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN, ctx->ec.derive.kdf_outlen); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_UKM */ rc = ibmca_param_build_set_octet_ptr(ctx->provctx, NULL, params, OSSL_EXCHANGE_PARAM_KDF_UKM, ctx->ec.derive.kdf_ukm, ctx->ec.derive.kdf_ukmlen); if (rc == 0) return 0; return 1; } static int ibmca_keyexch_ec_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; const OSSL_PARAM *p; const char *name, *props = NULL; int rc, value; void *ukm = NULL; size_t ukmlen; EVP_MD *md; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE */ rc = ibmca_param_get_int(ctx->provctx, params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, &value); if (rc == 0) return 0; if (rc > 0) { /* We do not support Cofactor DH (ECC CDH) */ if (value != 0) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "EC '%s': %d is not supported", OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, value); return 0; } } /* OSSL_EXCHANGE_PARAM_KDF_TYPE */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_TYPE, &name); if (rc == 0) return 0; if (rc > 0) { if (name[0] == '\0') { ctx->ec.derive.kdf_type = EVP_PKEY_ECDH_KDF_NONE; } else if (strcmp(name, OSSL_KDF_NAME_X963KDF) == 0) { ctx->ec.derive.kdf_type = EVP_PKEY_ECDH_KDF_X9_62; } else { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "EC '%s': '%s' is not supported", OSSL_EXCHANGE_PARAM_KDF_TYPE, name); return 0; } } /* OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, &props); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_DIGEST */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_DIGEST, &name); if (rc == 0) return 0; if (rc > 0) { md = EVP_MD_fetch(ctx->provctx->libctx, name, props != NULL ? props : ctx->propq); if (md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "EC '%s': '%s' could not be fetched", OSSL_EXCHANGE_PARAM_KDF_DIGEST, name); return 0; } if (ctx->ec.derive.kdf_md != NULL) EVP_MD_free(ctx->ec.derive.kdf_md); ctx->ec.derive.kdf_md = md; } /* OSSL_EXCHANGE_PARAM_KDF_OUTLEN */ rc = ibmca_param_get_size_t(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN, &ctx->ec.derive.kdf_outlen); if (rc == 0) return 0; /* OSSL_EXCHANGE_PARAM_KDF_UKM */ rc = ibmca_param_get_octet_string(ctx->provctx, params, OSSL_EXCHANGE_PARAM_KDF_UKM, &ukm, &ukmlen); if (rc == 0) return 0; if (rc > 0) { if (ctx->ec.derive.kdf_ukm != NULL) P_CLEAR_FREE(ctx->provctx, ctx->ec.derive.kdf_ukm, ctx->ec.derive.kdf_ukmlen); ctx->ec.derive.kdf_ukm = ukm; ctx->ec.derive.kdf_ukmlen = ukmlen; } return 1; } static const OSSL_PARAM ibmca_keyexch_ec_gettable_params[] = { OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0), OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keyexch_ec_gettable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; ibmca_debug_ctx(provctx, "ctx: %p", ctx); for (p = ibmca_keyexch_ec_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_keyexch_ec_gettable_params; } static const OSSL_PARAM ibmca_keyexch_ec_settable_params[] = { OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0), OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keyexch_ec_settable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; ibmca_debug_ctx(provctx, "ctx: %p", ctx); for (p = ibmca_keyexch_ec_settable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_keyexch_ec_settable_params; } static const OSSL_DISPATCH ibmca_ec_keyexch_functions[] = { /* Context management */ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))ibmca_keyexch_ec_newctx }, { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ibmca_op_freectx }, { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ibmca_op_dupctx }, /* Shared secret derivation */ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ibmca_keyexch_ec_init }, { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ibmca_keyexch_ec_set_peer }, { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ibmca_keyexch_ec_derive }, /* Key Exchange parameters */ { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))ibmca_keyexch_ec_set_ctx_params }, { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, (void (*)(void))ibmca_keyexch_ec_settable_ctx_params }, { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ibmca_keyexch_ec_get_ctx_params }, { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS, (void (*)(void))ibmca_keyexch_ec_gettable_ctx_params }, { 0, NULL } }; const OSSL_ALGORITHM ibmca_ec_keyexch[] = { { "ECDH", NULL, ibmca_ec_keyexch_functions, "IBMCA ECDH implementation" }, { NULL, NULL, NULL, NULL } }; openssl-ibmca-2.4.1/src/provider/ec_keymgmt.c000066400000000000000000002346261450276407300212100ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include #include #include #include "p_ibmca.h" static OSSL_FUNC_keymgmt_new_fn ibmca_keymgmt_ec_new; static OSSL_FUNC_keymgmt_gen_init_fn ibmca_keymgmt_ec_gen_init; static OSSL_FUNC_keymgmt_gen_set_template_fn ibmca_keymgmt_ec_gen_set_template; static OSSL_FUNC_keymgmt_gen_set_params_fn ibmca_keymgmt_ec_gen_set_params; static OSSL_FUNC_keymgmt_gen_settable_params_fn ibmca_keymgmt_ec_gen_settable_params; static OSSL_FUNC_keymgmt_gen_fn ibmca_keymgmt_ec_gen; static OSSL_FUNC_keymgmt_has_fn ibmca_keymgmt_ec_has; static OSSL_FUNC_keymgmt_match_fn ibmca_keymgmt_ec_match; static OSSL_FUNC_keymgmt_validate_fn ibmca_keymgmt_ec_validate; static OSSL_FUNC_keymgmt_query_operation_name_fn ibmca_keymgmt_ec_query_operation_name; static OSSL_FUNC_keymgmt_get_params_fn ibmca_keymgmt_ec_get_params; static OSSL_FUNC_keymgmt_gettable_params_fn ibmca_keymgmt_ec_gettable_params; static OSSL_FUNC_keymgmt_set_params_fn ibmca_keymgmt_ec_set_params; static OSSL_FUNC_keymgmt_settable_params_fn ibmca_keymgmt_ec_settable_params; static OSSL_FUNC_keymgmt_export_fn ibmca_keymgmt_ec_export; static OSSL_FUNC_keymgmt_export_types_fn ibmca_keymgmt_ec_imexport_types; static OSSL_FUNC_keymgmt_import_fn ibmca_keymgmt_ec_import; static void ibmca_keymgmt_ec_free_cb(struct ibmca_key *key); static int ibmca_keymgmt_ec_dup_cb(const struct ibmca_key *key, struct ibmca_key *new_key); static size_t ibmca_keymgmt_ec_get_prime_size(const struct ibmca_key *key); static size_t ibmca_keymgmt_ec_get_max_param_size(const struct ibmca_key *key); static int ibmca_keymgmt_ec_pub_key_as_buf(const struct ibmca_key *key, unsigned char **x, unsigned char **y) { unsigned char *q = NULL; unsigned int len, i; bool all_zero; int rc = 0; *x = NULL; *y = NULL; if (key->ec.key == NULL || key->ec.prime_size == 0 || key->ec.curve_nid == NID_undef) return -1; q = P_ZALLOC(key->provctx, key->ec.prime_size * 2); if (q == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate public EC key part"); goto out; } rc = ica_ec_key_get_public_key(key->ec.key, q, &len); if ((rc != 0 && rc != EINVAL) || len != key->ec.prime_size * 2) { put_error_key(key, IBMCA_ERR_LIBICA_FAILED, "Failed to get public EC key from libica key: %s", strerror(rc)); rc = 0; goto out; } if (rc == EINVAL) { /* No public key */ rc = -1; goto out; } for (i = 0, all_zero = true; i < len && all_zero; i++) { if (q[i] != 0) { all_zero = false; break; } } if (all_zero) { /* No public key */ rc = -1; goto out; } *x = P_ZALLOC(key->provctx, key->ec.prime_size); *y = P_ZALLOC(key->provctx, key->ec.prime_size); if (*x == NULL || *y == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate public EC key parts"); P_CLEAR_FREE(key->provctx, *x, key->ec.prime_size); *x = NULL; P_CLEAR_FREE(key->provctx, *y, key->ec.prime_size); *y = NULL; goto out; } memcpy(*x, q, key->ec.prime_size); memcpy(*y, q + key->ec.prime_size, key->ec.prime_size); rc = 1; out: if (q != NULL) P_CLEAR_FREE(key->provctx, q, key->ec.prime_size * 2); return rc; } static int ibmca_keymgmt_ec_priv_key_as_buf(const struct ibmca_key *key, unsigned char **d) { unsigned int len, i; int all_zero; int rc = 0; if (key->ec.key == NULL || key->ec.prime_size == 0 || key->ec.curve_nid == NID_undef) return -1; *d = P_SECURE_ZALLOC(key->provctx, key->ec.prime_size); if (*d == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate private EC key part"); goto out; } rc = ica_ec_key_get_private_key(key->ec.key, *d, &len); if ((rc != 0 && rc != EINVAL) || len != key->ec.prime_size) { put_error_key(key, IBMCA_ERR_LIBICA_FAILED, "Failed to get private EC key from libica key: %s", strerror(rc)); rc = 0; goto out; } if (rc == EINVAL) { /* No private key */ rc = -1; goto out; } for (i = 0, all_zero = 1; i < len && all_zero; i++) all_zero &= ((*d)[i] == 0); if (all_zero) { /* No private key */ rc = -1; goto out; } rc = 1; out: if (rc != 1 && *d != NULL) { P_SECURE_CLEAR_FREE(key->provctx, *d, key->ec.prime_size); *d = NULL; } return rc; } static int ibmca_keymgmt_ec_pub_key_as_bn(const struct ibmca_key *key, BIGNUM **x, BIGNUM **y) { unsigned char *buf_x = NULL, *buf_y = NULL; int rc; if (key->ec.fallback.x != NULL && key->ec.fallback.y != NULL) { *x = BN_dup(key->ec.fallback.x); *y = BN_dup(key->ec.fallback.y); if (*x == NULL || *y == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); goto error; } return 1; } rc = ibmca_keymgmt_ec_pub_key_as_buf(key, &buf_x, &buf_y); if (rc != 1) return rc; *x = BN_bin2bn(buf_x, key->ec.prime_size, NULL); *y = BN_bin2bn(buf_y, key->ec.prime_size, NULL); if (*x == NULL || *y == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); goto error; } P_CLEAR_FREE(key->provctx, buf_x, key->ec.prime_size); P_CLEAR_FREE(key->provctx, buf_y, key->ec.prime_size); return 1; error: if (*x != NULL) BN_free(*x); *x = NULL; if (*y != NULL) BN_free(*y); *y = NULL; if (buf_x != NULL) P_CLEAR_FREE(key->provctx, buf_x, key->ec.prime_size); if (buf_y != NULL) P_CLEAR_FREE(key->provctx, buf_y, key->ec.prime_size); return 0; } static int ibmca_keymgmt_ec_priv_key_as_bn(const struct ibmca_key *key, BIGNUM **d) { unsigned char *buf_d = NULL; int rc; if (key->ec.fallback.d != NULL) { *d = BN_dup(key->ec.fallback.d); if (*d == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); goto error; } return 1; } rc = ibmca_keymgmt_ec_priv_key_as_buf(key, &buf_d); if (rc != 1) return rc; *d = BN_secure_new(); if (*d == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } *d = BN_bin2bn(buf_d, key->ec.prime_size, *d); if (*d == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); goto error; } P_SECURE_CLEAR_FREE(key->provctx, buf_d, key->ec.prime_size); return 1; error: if (*d != NULL) BN_clear_free(*d); *d = NULL; if (buf_d != NULL) P_SECURE_CLEAR_FREE(key->provctx, buf_d, key->ec.prime_size); return 0; } static int ibmca_keymgmt_ec_pub_key_from_bn(struct ibmca_key *key, BIGNUM *x, BIGNUM *y) { unsigned int privlen; unsigned char *x_buf = NULL, *y_buf = NULL; int rc = 0; if (x == NULL || y == NULL) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "Need both, x and y"); return 0; } if (key->ec.curve_nid == NID_undef) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "Curve nid is not known"); return 0; } if (key->ec.key == NULL) { key->ec.prime_size = ibmca_keymgmt_ec_get_prime_size(key); if (key->ec.prime_size == 0) { put_error_key(key, IBMCA_ERR_EC_CURVE_NOT_SUPPORTED, "Unsupported curve nid: %d", key->ec.curve_nid); return 0; } ibmca_debug_key(key, "prime_size: %lu", key->ec.prime_size); key->ec.key = ica_ec_key_new(key->ec.curve_nid, &privlen); if (key->ec.key == NULL || key->ec.prime_size != privlen) { ibmca_debug_key(key, "ica_ec_key_new failed"); goto fallback; } } x_buf = P_ZALLOC(key->provctx, key->ec.prime_size); y_buf = P_ZALLOC(key->provctx, key->ec.prime_size); if (x_buf == NULL || y_buf == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate public EC key parts"); goto out; } if (BN_bn2binpad(x, x_buf, key->ec.prime_size) <= 0 || BN_bn2binpad(y, y_buf, key->ec.prime_size) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); goto out; } rc = ica_ec_key_init(x_buf, y_buf, NULL, key->ec.key); if (rc != 0) { ibmca_debug_key(key, "ica_ec_key_init failed: %s", strerror(rc)); rc = 0; goto fallback; } rc = 1; goto out; fallback: ibmca_debug_key(key, "using fallback"); if (key->ec.key != NULL) ica_ec_key_free(key->ec.key); key->ec.key = NULL; if (key->ec.fallback.x != NULL) BN_free(key->ec.fallback.x); if (key->ec.fallback.y != NULL) BN_free(key->ec.fallback.y); key->ec.fallback.x = BN_dup(x); key->ec.fallback.y = BN_dup(y); if (key->ec.fallback.x == NULL || key->ec.fallback.y == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); goto out; } rc = 1; out: if (x_buf != NULL) P_CLEAR_FREE(key->provctx, x_buf, key->ec.prime_size); if (y_buf != NULL) P_CLEAR_FREE(key->provctx, y_buf, key->ec.prime_size); return rc; } static int ibmca_keymgmt_ec_priv_key_from_bn(struct ibmca_key *key, BIGNUM *d) { unsigned int privlen; unsigned char *d_buf = NULL; int rc = 0; if (d == NULL) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "Need private part d"); return 0; } if (key->ec.curve_nid == NID_undef) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "Curve nid is not known"); return 0; } if (key->ec.key == NULL) { key->ec.prime_size = ibmca_keymgmt_ec_get_prime_size(key); if (key->ec.prime_size == 0) { put_error_key(key, IBMCA_ERR_EC_CURVE_NOT_SUPPORTED, "Unsupported curve nid: %d", key->ec.curve_nid); return 0; } ibmca_debug_key(key, "prime_size: %lu", key->ec.prime_size); key->ec.key = ica_ec_key_new(key->ec.curve_nid, &privlen); if (key->ec.key == NULL || key->ec.prime_size != privlen) { ibmca_debug_key(key, "ica_ec_key_new failed"); goto fallback; } } d_buf = P_SECURE_ZALLOC(key->provctx, key->ec.prime_size); if (d_buf == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate private EC key part"); goto out; } if (BN_bn2binpad(d, d_buf, key->ec.prime_size) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); goto out; } rc = ica_ec_key_init(NULL, NULL, d_buf, key->ec.key); if (rc != 0) { ibmca_debug_key(key, "ica_ec_key_init failed: %s", strerror(rc)); rc = 0; goto fallback; } rc = 1; goto out; fallback: ibmca_debug_key(key, "using fallback"); if (key->ec.key != NULL) ica_ec_key_free(key->ec.key); key->ec.key = NULL; if (key->ec.fallback.d != NULL) BN_free(key->ec.fallback.d); key->ec.fallback.d = BN_dup(d); if (key->ec.fallback.d == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); goto out; } rc = 1; out: if (d_buf != NULL) P_SECURE_CLEAR_FREE(key->provctx, d_buf, key->ec.prime_size); return rc; } static int ibmca_keymgmt_ec_pub_key_to_data(struct ibmca_key *key, BIGNUM *x, BIGNUM *y, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) { EC_GROUP *group = NULL; EC_POINT *point = NULL; unsigned char *enc = NULL; size_t enc_len = 0; int rc = 0; /* OSSL_PKEY_PARAM_EC_PUB_X */ rc = ibmca_param_build_set_bn(key->provctx, bld, params, OSSL_PKEY_PARAM_EC_PUB_X, x); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_EC_PUB_Y */ rc = ibmca_param_build_set_bn(key->provctx, bld, params, OSSL_PKEY_PARAM_EC_PUB_Y, y); if (rc == 0) return 0; group = EC_GROUP_new_by_curve_name(key->ec.curve_nid); if (group == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_GROUP_new_by_curve_name failed"); goto out; } point = EC_POINT_new(group); if (point == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_new failed"); goto out; } if (EC_POINT_set_affine_coordinates(group, point, x, y, NULL) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_set_affine_coordinates failed"); goto out; } /* OSSL_PKEY_PARAM_PUB_KEY */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY) != NULL) { enc_len = EC_POINT_point2buf(group, point, POINT_CONVERSION_COMPRESSED, &enc, NULL); if (enc_len == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_point2buf failed"); goto out; } rc = ibmca_param_build_set_octet_ptr(key->provctx, bld, params, OSSL_PKEY_PARAM_PUB_KEY, enc, enc_len); if (rc == 0) goto out; P_FREE(key->provctx, enc); enc = NULL; } /* OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY) != NULL) { enc_len = EC_POINT_point2buf(group, point, POINT_CONVERSION_UNCOMPRESSED, &enc, NULL); if (enc_len == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_point2buf failed"); goto out; } rc = ibmca_param_build_set_octet_ptr(key->provctx, bld, params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, enc, enc_len); if (rc == 0) goto out; P_FREE(key->provctx, enc); enc = NULL; } rc = 1; out: EC_GROUP_free(group); EC_POINT_free(point); if (enc != NULL) P_FREE(key->provctx, enc); return rc; } static int ibmca_keymgmt_ec_priv_key_to_data(struct ibmca_key *key, BIGNUM *d, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) { int rc = 0; /* OSSL_PKEY_PARAM_PRIV_KEY */ rc = ibmca_param_build_set_bn(key->provctx, bld, params, OSSL_PKEY_PARAM_PRIV_KEY, d); if (rc == 0) return 0; return 1; } static void *ibmca_keymgmt_ec_new(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; struct ibmca_key *key; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); key = ibmca_keymgmt_new(provctx, EVP_PKEY_EC, "EC", ibmca_keymgmt_ec_free_cb, ibmca_keymgmt_ec_dup_cb, ibmca_keymgmt_ec_get_max_param_size, ibmca_keymgmt_ec_export, ibmca_keymgmt_ec_import, ibmca_keymgmt_ec_has, ibmca_keymgmt_ec_match); if (key == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_new failed"); return NULL; } key->ec.curve_nid = NID_undef; key->ec.format = POINT_CONVERSION_UNCOMPRESSED; key->ec.prime_size = 0; key->ec.include_pub = true; return key; } static void ibmca_keymgmt_ec_free_cb(struct ibmca_key *key) { if (key == NULL) return; ibmca_debug_key(key, "key: %p", key); if (key->ec.key != NULL) ica_ec_key_free(key->ec.key); key->ec.key = NULL; if (key->ec.fallback.x != NULL) BN_free(key->ec.fallback.x); key->ec.fallback.x = NULL; if (key->ec.fallback.y != NULL) BN_free(key->ec.fallback.y); key->ec.fallback.y = NULL; if (key->ec.fallback.d != NULL) BN_free(key->ec.fallback.d); key->ec.fallback.d = NULL; key->ec.curve_nid = NID_undef; key->ec.format = POINT_CONVERSION_UNCOMPRESSED; key->ec.prime_size = 0; key->ec.include_pub = true; } static int ibmca_keymgmt_ec_dup_cb(const struct ibmca_key *key, struct ibmca_key *new_key) { unsigned int privlen; unsigned char *x = NULL, *y = NULL, *d = NULL; bool has_pub = false, has_priv = false; int rc = 0; if (key == NULL || new_key == NULL) return 0; ibmca_debug_key(key, "key: %p new_key: %p", key, new_key); new_key->ec.curve_nid = key->ec.curve_nid; new_key->ec.format = key->ec.format; new_key->ec.include_pub = key->ec.include_pub; new_key->ec.prime_size = key->ec.prime_size; if (key->ec.key != NULL) { new_key->ec.key = ica_ec_key_new(new_key->ec.curve_nid, &privlen); if (new_key->ec.key == NULL) { put_error_key(key, IBMCA_ERR_LIBICA_FAILED, "Failed to allocate libica EC key"); goto out; } if (privlen != new_key->ec.prime_size) { put_error_key(key, IBMCA_ERR_LIBICA_FAILED, "Newly allocated libica EC key has a different size"); goto out; } rc = ibmca_keymgmt_ec_pub_key_as_buf(key, &x, &y); if (rc == 0) goto out; has_pub = (rc == 1); rc = ibmca_keymgmt_ec_priv_key_as_buf(key, &d); if (rc == 0) goto out; has_priv = (rc == 1); rc = ica_ec_key_init(has_pub ? x : NULL, has_pub ? y : NULL, has_priv ? d : NULL, new_key->ec.key); if (rc != 0) { put_error_key(key, IBMCA_ERR_LIBICA_FAILED, "Failed to initialize libica EC key: %s", strerror(rc)); rc = 0; goto out; } } if (key->ec.fallback.x != NULL && key->ec.fallback.y != NULL) { new_key->ec.fallback.x = BN_dup(key->ec.fallback.x); new_key->ec.fallback.y = BN_dup(key->ec.fallback.y); if (new_key->ec.fallback.x == NULL || new_key->ec.fallback.y == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); goto out; } } if (key->ec.fallback.d != NULL) { new_key->ec.fallback.d = BN_dup(key->ec.fallback.d); if (new_key->ec.fallback.d == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_dup failed"); goto out; } } rc = 1; out: if (x != NULL) P_CLEAR_FREE(key->provctx, x, privlen); if (y != NULL) P_CLEAR_FREE(key->provctx, y, privlen); if (d != NULL) P_SECURE_CLEAR_FREE(key->provctx, d, privlen); return rc; } static int ibmca_keymgmt_ec_has(const void *vkey, int selection) { const struct ibmca_key *key = vkey; BIGNUM *x = NULL, *y = NULL, *d = NULL; int rc, ok = 1; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { rc = ibmca_keymgmt_ec_pub_key_as_bn(key, &x, &y); if (rc == 0) goto out; ok = ok & (rc == 1); } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { rc = ibmca_keymgmt_ec_priv_key_as_bn(key, &d); if (rc == 0) goto out; ok = ok & (rc == 1); } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) ok = ok & (key->ec.curve_nid != NID_undef); out: if (x != NULL) BN_free(x); if (y != NULL) BN_free(y); if (d != NULL) BN_free(d); ibmca_debug_key(key, "ok: %d", ok); return ok; } static int ibmca_keymgmt_ec_match(const void *vkey1, const void *vkey2, int selection) { const struct ibmca_key *key1 = vkey1; const struct ibmca_key *key2 = vkey2; BIGNUM *x1 = NULL, *y1 = NULL, *d1 = NULL; BIGNUM *x2 = NULL, *y2 = NULL, *d2 = NULL; int ok = 1, rc1, rc2, checked = 0; if (key1 == NULL || key2 == NULL) return 0; ibmca_debug_key(key1, "key1: %p key2: %p selection: 0x%x", key1, key2, selection); if (ibmca_keymgmt_match(key1, key2) == 0) return 0; if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) ok = (key1->ec.curve_nid == key2->ec.curve_nid && key1->ec.prime_size == key2->ec.prime_size); if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { rc1 = ibmca_keymgmt_ec_pub_key_as_bn(key1, &x1, &y1); if (rc1 == 0) { ok = 0; goto out; } rc2 = ibmca_keymgmt_ec_pub_key_as_bn(key2, &x2, &y2); if (rc2 == 0) { ok = 0; goto out; } ok = ok && (rc1 == rc2 && (rc1 == -1 || (BN_cmp(x1, x2) == 0 && BN_cmp(y1, y2) == 0))); checked = 1; } if (!checked && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { rc1 = ibmca_keymgmt_ec_priv_key_as_bn(key1, &d1); if (rc1 == 0) { ok = 0; goto out; } rc2 = ibmca_keymgmt_ec_priv_key_as_bn(key2, &d2); if (rc2 == 0) { ok = 0; goto out; } ok = ok && (rc1 == rc2 && (rc1 == -1 || (BN_cmp(d1, d2) == 0))); } out: if (x1 != NULL) BN_free(x1); if (x2 != NULL) BN_free(x2); if (y1 != NULL) BN_free(y1); if (y2 != NULL) BN_free(y2); if (d1 != NULL) BN_free(d1); if (d2 != NULL) BN_free(d2); ibmca_debug_key(key1, "ok: %d", ok); return ok; } static int ibmca_keymgmt_ec_validate(const void *vkey, int selection, int checktype) { struct ibmca_key *key = (struct ibmca_key *)vkey; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; int rc = 0; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x checktype: 0x%x", key, selection, checktype); if ((key->ec.fallback.x != NULL && key->ec.fallback.y != NULL) || key->ec.fallback.d != NULL) { /* Check fallback key using OpenSSL */ pkey = ibmca_new_fallback_pkey(key); if (pkey == NULL) goto out; pctx = ibmca_new_fallback_pkey_ctx(key->provctx, pkey, NULL); if (pctx == NULL) goto out; if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR) { rc = EVP_PKEY_check(pctx); } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { rc = EVP_PKEY_public_check(pctx); } goto out; } /* * If the selected key parts are present, they are valid: * Either the EC key has been generated by libica, then the EC is valid per * definition, or the EC key has been imported, then the validity has * already been checked during ica_ec_key_init(). */ if (ibmca_keymgmt_ec_has(key, selection) == 0) goto out; rc = 1; out: ibmca_debug_key(key, "valid: %d", rc); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); if (pkey != NULL) EVP_PKEY_free(pkey); return rc; } static const char *ibmca_keymgmt_ec_query_operation_name(int operation_id) { switch (operation_id) { case OSSL_OP_KEYEXCH: return "ECDH"; case OSSL_OP_SIGNATURE: return "ECDSA"; } return NULL; } static void ibmca_keymgmt_ec_gen_free_cb(struct ibmca_op_ctx *ctx) { if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); ctx->ec.gen.curve_nid = NID_undef; ctx->ec.gen.format = POINT_CONVERSION_UNCOMPRESSED; } static int ibmca_keymgmt_ec_gen_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p new_ctx: %p", ctx, new_ctx); new_ctx->ec.gen.curve_nid = ctx->ec.gen.curve_nid; new_ctx->ec.gen.format = ctx->ec.gen.format; return 1; } static void *ibmca_keymgmt_ec_gen_init(void *vprovctx, int selection, const OSSL_PARAM params[]) { const struct ibmca_prov_ctx *provctx = vprovctx; struct ibmca_op_ctx *ctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p selection: 0x%x", provctx, selection); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "selection is not KEYPAIR and/or parameters"); return NULL; } ctx = ibmca_keymgmt_gen_init(provctx, EVP_PKEY_EC, ibmca_keymgmt_ec_gen_free_cb, ibmca_keymgmt_ec_gen_dup_cb); if (ctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_gen_init failed"); return NULL; } /* set defaults */ ctx->ec.gen.selection = selection; ctx->ec.gen.curve_nid = NID_undef; ctx->ec.gen.format = POINT_CONVERSION_UNCOMPRESSED; if (params != NULL) { if (ibmca_keymgmt_ec_gen_set_params(ctx, params) == 0) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_ec_gen_set_params failed"); ibmca_op_freectx(ctx); return NULL; } } return ctx; } static int ibmca_keymgmt_ec_gen_set_template(void *vgenctx, void *vtempl) { struct ibmca_op_ctx *genctx = vgenctx; struct ibmca_key *templ = vtempl; if (genctx == NULL || templ == NULL) return 0; ibmca_debug_op_ctx(genctx, "genctx: %p templ: %p", genctx, templ); if (genctx->type != templ->type) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "invalid template key type"); return 0; } ibmca_keymgmt_ec_gen_free_cb(genctx); genctx->ec.gen.curve_nid = templ->ec.curve_nid; genctx->ec.gen.format = templ->ec.format; ibmca_debug_op_ctx(genctx, "curve_nid: %d", genctx->ec.gen.curve_nid); ibmca_debug_op_ctx(genctx, "format: %d", genctx->ec.gen.format); return 1; } static int ibmca_keymgmt_ec_gen_set_params(void *vgenctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *genctx = vgenctx; OSSL_PARAM grp_params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; const OSSL_PARAM *p; const char *name; EC_GROUP *group; int rc, value; if (genctx == NULL) return 0; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(genctx, "param: %s", p->key); /* OSSL_PKEY_PARAM_GROUP_NAME */ rc = ibmca_param_get_utf8(genctx->provctx, params, OSSL_PKEY_PARAM_GROUP_NAME, &name); if (rc == 0) return 0; if (rc > 0) { grp_params[0] = OSSL_PARAM_construct_utf8_ptr( OSSL_PKEY_PARAM_GROUP_NAME, (char **)&name, 0); group = EC_GROUP_new_from_params(grp_params, genctx->provctx->libctx, NULL); if (group == NULL) { put_error_op_ctx(genctx, IBMCA_ERR_EC_CURVE_NOT_SUPPORTED, "EC '%s': '%s' is an unsupported curve", OSSL_PKEY_PARAM_GROUP_NAME, name); return 0; } genctx->ec.gen.curve_nid = EC_GROUP_get_curve_name(group); EC_GROUP_free(group); } /* OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT */ rc = ibmca_param_get_utf8(genctx->provctx, params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, &name); if (rc == 0) return 0; if (rc > 0) { if (strcasecmp(name, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED) != 0) { genctx->ec.gen.format = POINT_CONVERSION_UNCOMPRESSED; } else if (strcasecmp(name, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED) != 0) { genctx->ec.gen.format = POINT_CONVERSION_COMPRESSED; } else if (strcasecmp(name, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID) != 0) { genctx->ec.gen.format = POINT_CONVERSION_HYBRID; } else { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "EC '%s': '%s' is an unsupported format", OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, name); return 0; } } /* OSSL_PKEY_PARAM_EC_ENCODING */ rc = ibmca_param_get_utf8(genctx->provctx, params, OSSL_PKEY_PARAM_EC_ENCODING, &name); if (rc == 0) return 0; if (rc > 0) { /* We only support named curves */ if (strcasecmp(name, OSSL_PKEY_EC_ENCODING_GROUP) != 0) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "EC '%s': '%s' is an unsupported encoding", OSSL_PKEY_PARAM_EC_ENCODING, name); return 0; } } /* OSSL_PKEY_PARAM_USE_COFACTOR_ECDH */ rc = ibmca_param_get_int(genctx->provctx, params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, &value); if (rc == 0) return 0; if (rc > 0) { /* We do not support Cofactor DH (ECC CDH) */ if (value != 0) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "EC '%s': %d is not supported", OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, value); return 0; } } #ifdef OSSL_PKEY_PARAM_DHKEM_IKM if (OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM) != NULL) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "EC parameter '%s' is not supported", OSSL_PKEY_PARAM_DHKEM_IKM); return 0; } #endif return 1; } static const OSSL_PARAM ibmca_ec_op_ctx_settable_params[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_ec_gen_settable_params(void *vgenctx, void *vprovctx) { const struct ibmca_op_ctx *genctx = vgenctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; UNUSED(genctx); if (provctx == NULL) return NULL; for (p = ibmca_ec_op_ctx_settable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_ec_op_ctx_settable_params; } static int ibmca_keymgmt_ec_gen_fallback(struct ibmca_op_ctx *genctx, struct ibmca_key *key, OSSL_CALLBACK *osslcb, void *cbarg) { struct ibmca_keygen_cb_data cbdata; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL; int rc = 0; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); pctx = ibmca_new_fallback_pkey_ctx(genctx->provctx, NULL, "EC"); if (pctx == NULL) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_keygen_init(pctx) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_keygen_init failed"); goto out; } if (ibmca_check_fallback_provider(genctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, genctx->ec.gen.curve_nid) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_CTX_set_ec_paramgen_curve_nid failed"); goto out; } if (osslcb != NULL) { cbdata.osslcb = osslcb; cbdata.cbarg = cbarg; EVP_PKEY_CTX_set_cb(pctx, ibmca_keygen_cb); EVP_PKEY_CTX_set_app_data(pctx, &cbdata); } if (EVP_PKEY_generate(pctx, &pkey) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_generate failed"); goto out; } rc = ibmca_import_from_fallback_pkey(key, pkey, OSSL_KEYMGMT_SELECT_ALL); if (rc != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_import_from_fallback_pkey failed"); goto out; } rc = 1; out: if (pctx != NULL) EVP_PKEY_CTX_free(pctx); if (pkey != NULL) EVP_PKEY_free(pkey); return rc; } static void *ibmca_keymgmt_ec_gen(void *vgenctx, OSSL_CALLBACK *osslcb, void *cbarg) { struct ibmca_op_ctx *genctx = vgenctx; OSSL_PARAM cb_params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; struct ibmca_key *key = NULL; unsigned int privlen; int rc, p, n; bool fallback = false; if (genctx == NULL) return NULL; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); cb_params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); cb_params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); key = ibmca_keymgmt_new(genctx->provctx, genctx->type, "EC", ibmca_keymgmt_ec_free_cb, ibmca_keymgmt_ec_dup_cb, ibmca_keymgmt_ec_get_max_param_size, ibmca_keymgmt_ec_export, ibmca_keymgmt_ec_import, ibmca_keymgmt_ec_has, ibmca_keymgmt_ec_match); if (key == NULL) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_keymgmt_new failed"); return NULL; } key->ec.curve_nid = genctx->ec.gen.curve_nid; key->ec.format = genctx->ec.gen.format; key->ec.include_pub = true; ibmca_debug_op_ctx(genctx, "curve_nid: %d", key->ec.curve_nid); ibmca_debug_op_ctx(genctx, "format: %d", key->ec.format); ibmca_debug_op_ctx(genctx, "include_pub: %d", key->ec.include_pub); key->ec.prime_size = ibmca_keymgmt_ec_get_prime_size(key); if (key->ec.prime_size == 0) { put_error_op_ctx(genctx, IBMCA_ERR_EC_CURVE_NOT_SUPPORTED, "Unsupported curve nid: %d", key->ec.curve_nid); ibmca_keymgmt_free(key); return NULL; } ibmca_debug_op_ctx(genctx, "prime_size: %lu", key->ec.prime_size); if ((genctx->ec.gen.selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) goto out; key->ec.key = ica_ec_key_new(key->ec.curve_nid, &privlen); if (key->ec.key == NULL || key->ec.prime_size != privlen) { ibmca_debug_op_ctx(genctx, "ica_ec_key_new failed"); fallback = true; } p = 0; n = 0; if (osslcb != NULL && osslcb(cb_params, cbarg) == 0) { put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "osslcb failed"); ibmca_keymgmt_free(key); return NULL; } if (!fallback) rc = ica_ec_key_generate(genctx->provctx->ica_adapter, key->ec.key); else rc = ENODEV; if (rc != 0 || fallback) { if (!fallback) ibmca_debug_op_ctx(genctx, "ica_ec_key_generate failed with: %s", strerror(rc)); if (key->ec.key != NULL) ica_ec_key_free(key->ec.key); key->ec.key = NULL; rc = ibmca_keymgmt_ec_gen_fallback(genctx, key, osslcb, cbarg); if (rc != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_keymgmt_ec_gen_fallback failed"); ibmca_keymgmt_free(key); return NULL; } } p = 3; n = 0; if (osslcb != NULL && osslcb(cb_params, cbarg) == 0) { put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "osslcb failed"); ibmca_keymgmt_free(key); return NULL; } out: ibmca_debug_op_ctx(genctx, "key: %p", key); return key; } static int ibmca_keymgmt_ec_pub_key_from_data(const struct ibmca_key *key, const OSSL_PARAM params[], BIGNUM **x, BIGNUM **y, point_conversion_form_t *format) { int rc = 0; unsigned char *enc = NULL; size_t enc_len = 0; EC_GROUP *group = NULL; EC_POINT *point = NULL; *format = POINT_CONVERSION_UNCOMPRESSED; /* OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY */ rc = ibmca_param_get_octet_string(key->provctx, params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, (void **)&enc, &enc_len); if (rc == 0) return 0; if (rc < 0) { /* OSSL_PKEY_PARAM_PUB_KEY */ rc = ibmca_param_get_octet_string(key->provctx, params, OSSL_PKEY_PARAM_PUB_KEY, (void **)&enc, &enc_len); if (rc == 0) return 0; } if (rc > 0) { group = EC_GROUP_new_by_curve_name(key->ec.curve_nid); if (group == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_GROUP_new_by_curve_name failed"); goto out; } point = EC_POINT_new(group); if (point == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_new failed"); goto out; } if (EC_POINT_oct2point(group, point, enc, enc_len, NULL) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_oct2point failed"); goto out; } *x = BN_new(); *y = BN_new(); if (*x == NULL || *y == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_new failed"); goto out; } if (EC_POINT_get_affine_coordinates(group, point, *x, *y, NULL) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_get_affine_coordinates failed"); goto out; } *format = (point_conversion_form_t)(enc[0] & ~0x01); rc = 1; out: if (group != NULL) EC_GROUP_free(group); if (point != NULL) EC_POINT_free(point); if (enc != NULL) P_FREE(key->provctx, enc); return rc; /* do not check for X and Y params anymore */ } /* OSSL_PKEY_PARAM_EC_PUB_X */ rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_EC_PUB_X, x); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_EC_PUB_Y */ rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_EC_PUB_Y, y); if (rc == 0) return 0; return 1; } static int ibmca_keymgmt_ec_priv_key_from_data(const struct ibmca_key *key, const OSSL_PARAM params[], BIGNUM **d) { int rc = 0; /* OSSL_PKEY_PARAM_PRIV_KEY */ *d = BN_secure_new(); if (*d == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); return 0; } rc = ibmca_param_get_bn(key->provctx, params, OSSL_PKEY_PARAM_PRIV_KEY, d); if (rc <= 0) { BN_clear_free(*d); *d = NULL; return rc; } return 1; } static const OSSL_PARAM ibmca_ec_gettable_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_ec_gettable_params(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; for (p = ibmca_ec_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_ec_gettable_params; } static size_t ibmca_keymgmt_ec_get_max_param_size(const struct ibmca_key *key) { int rc = 0; ECDSA_SIG *sig = NULL; EC_GROUP *group = NULL; const BIGNUM *bn; BIGNUM *r = NULL, *s = NULL; group = EC_GROUP_new_by_curve_name(key->ec.curve_nid); if (group == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_GROUP_new_by_curve_name failed"); goto out; } bn = EC_GROUP_get0_order(group); if (bn == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_GROUP_get0_order failed"); goto out; } sig = ECDSA_SIG_new(); if (sig == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "ECDSA_SIG_new failed"); goto out; } r = BN_dup(bn); s = BN_dup(bn); if (ECDSA_SIG_set0(sig, r, s) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "ECDSA_SIG_set0 failed"); goto out; } rc = i2d_ECDSA_SIG(sig, NULL); if (rc <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "i2d_ECDSA_SIG failed"); rc = 0; goto out; } out: if (group != NULL) EC_GROUP_free(group); if (sig != NULL) ECDSA_SIG_free(sig); return rc; } static size_t ibmca_keymgmt_ec_get_prime_bits(const struct ibmca_key *key) { int rc = 0; EC_GROUP *group = NULL; group = EC_GROUP_new_by_curve_name(key->ec.curve_nid); if (group == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_GROUP_new_by_curve_name failed"); goto out; } rc = EC_GROUP_order_bits(group); if (rc <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_GROUP_order_bits failed"); rc = 0; goto out; } out: if (group != NULL) EC_GROUP_free(group); return rc; } static size_t ibmca_keymgmt_ec_get_prime_size(const struct ibmca_key *key) { return (ibmca_keymgmt_ec_get_prime_bits(key) + 7) / 8; } static int ibmca_keymgmt_ec_get_security_bits(const struct ibmca_key *key) { int bits; bits = ibmca_keymgmt_ec_get_prime_bits(key); if (bits == 0) return 0; /* * The following estimates are based on the values published * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4" * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 . */ if (bits >= 512) bits = 256; else if (bits >= 384) bits = 192; else if (bits >= 256) bits = 128; else if (bits >= 224) bits = 112; else if (bits >= 160) bits = 80; else bits = bits / 2; return bits; } static int ibmca_keymgmt_ec_get_params(void *vkey, OSSL_PARAM params[]) { struct ibmca_key *key = vkey; OSSL_PARAM *parm; const char *name; BIGNUM *x = NULL, *y = NULL, *d = NULL; int rc, size; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p", key); for (parm = params; parm != NULL && parm->key != NULL; parm++) ibmca_debug_key(key, "param: %s", parm->key); /* OSSL_PKEY_PARAM_BITS */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS) != NULL) { size = ibmca_keymgmt_ec_get_prime_bits(key); if (size == 0) return 0; rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_BITS, size); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_SECURITY_BITS */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS) != NULL) { size = ibmca_keymgmt_ec_get_security_bits(key); if (size == 0) return 0; rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_SECURITY_BITS, size); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_MAX_SIZE */ if (OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE) != NULL) { size = ibmca_keymgmt_ec_get_max_param_size(key); if (size == 0) return 0; rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_MAX_SIZE, size); if (rc == 0) return 0; } /* OSSL_PKEY_PARAM_DEFAULT_DIGEST */ rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_DEFAULT_DIGEST, OBJ_nid2sn(IBMCA_EC_DEFAULT_DIGEST)); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS */ rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, 0); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_USE_COFACTOR_ECDH */ rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, 0); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_EC_ENCODING */ rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_EC_ENCODING, OSSL_PKEY_EC_ENCODING_GROUP); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT */ switch (key->ec.format) { case POINT_CONVERSION_COMPRESSED: name = OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED; break; case POINT_CONVERSION_UNCOMPRESSED: name = OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED; break; case POINT_CONVERSION_HYBRID: name = OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID; break; default: name = ""; break; } rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, name); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC */ rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, key->ec.include_pub ? 1 : 0); if (rc == 0) return 0; rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_GROUP_NAME, OBJ_nid2sn(key->ec.curve_nid)); if (rc == 0) return 0; /* * OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY * OSSL_PKEY_PARAM_PUB_KEY * OSSL_PKEY_PARAM_EC_PUB_X * OSSL_PKEY_PARAM_EC_PUB_Y */ rc = ibmca_keymgmt_ec_pub_key_as_bn(key, &x, &y); if (rc == 0) goto out; if (rc > 0) { rc = ibmca_keymgmt_ec_pub_key_to_data(key, x, y, NULL, params); if (rc == 0) goto out; } /* OSSL_PKEY_PARAM_PRIV_KEY */ rc = ibmca_keymgmt_ec_priv_key_as_bn(key, &d); if (rc == 0) goto out; if (rc > 0) { rc = ibmca_keymgmt_ec_priv_key_to_data(key, d, NULL, params); if (rc == 0) goto out; } rc = 1; out: if (x != NULL) BN_free(x); if (y != NULL) BN_free(y); if (d != NULL) BN_free(d); return rc; } static const OSSL_PARAM ibmca_ec_settable_params[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_ec_settable_params(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; for (p = ibmca_ec_settable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_ec_settable_params; } static int ibmca_keymgmt_ec_set_params(void *vkey, const OSSL_PARAM params[]) { struct ibmca_key *key = vkey; const OSSL_PARAM *parm; BIGNUM *x = NULL, *y = NULL; point_conversion_form_t format; const char *name; int rc, value; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p", key); for (parm = params; parm != NULL && parm->key != NULL; parm++) ibmca_debug_key(key, "param: %s", parm->key); /* OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT */ rc = ibmca_param_get_utf8(key->provctx, params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, &name); if (rc == 0) return 0; if (rc > 0) { if (strcasecmp(name, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED) != 0) { key->ec.format = POINT_CONVERSION_UNCOMPRESSED; } else if (strcasecmp(name, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED) != 0) { key->ec.format = POINT_CONVERSION_COMPRESSED; } else if (strcasecmp(name, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID) != 0) { key->ec.format = POINT_CONVERSION_HYBRID; } else { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "EC '%s': '%s' is an unsupported format", OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, name); rc = 0; goto out; } ibmca_clean_fallback_pkey_cache(key); } /* OSSL_PKEY_PARAM_EC_ENCODING */ rc = ibmca_param_get_utf8(key->provctx, params, OSSL_PKEY_PARAM_EC_ENCODING, &name); if (rc == 0) return 0; if (rc > 0) { /* We only support named curves */ if (strcasecmp(name, OSSL_PKEY_EC_ENCODING_GROUP) != 0) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "EC '%s': '%s' is an unsupported encoding", OSSL_PKEY_PARAM_EC_ENCODING, name); rc = 0; goto out; } ibmca_clean_fallback_pkey_cache(key); } /* OSSL_PKEY_PARAM_USE_COFACTOR_ECDH */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, &value); if (rc == 0) return 0; if (rc > 0) { /* We do not support Cofactor DH (ECC CDH) */ if (value != 0) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "EC '%s': %d is not supported", OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, value); rc = 0; goto out; } ibmca_clean_fallback_pkey_cache(key); } /* OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY */ rc = ibmca_keymgmt_ec_pub_key_from_data(key, params, &x, &y, &format); if (rc == 0) goto out; if (rc > 0 && x != NULL && y != NULL) { rc = ibmca_keymgmt_ec_pub_key_from_bn(key, x, y); if (rc == 0) goto out; key->ec.format = format; ibmca_clean_fallback_pkey_cache(key); } /* OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, &value); if (rc == 0) return 0; if (rc > 0) { key->ec.include_pub = (value != 0); ibmca_clean_fallback_pkey_cache(key); } rc = 1; out: BN_free(x); BN_free(y); return rc; } static const OSSL_PARAM ibmca_keymgmt_ec_imexport_priv_key[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_pub_key[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_key_pair[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_dom_params[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_priv_key_dom_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_pub_key_dom_params[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_key_pair_dom_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_other_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_priv_key_other_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_pub_key_other_params[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_key_pair_other_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_all_params[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_priv_key_all_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_pub_key_all_params[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_keymgmt_ec_imexport_key_pair_all_params[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_ec_imexport_types(int selection) { selection &= OSSL_KEYMGMT_SELECT_ALL; switch (selection) { case OSSL_KEYMGMT_SELECT_PRIVATE_KEY: return ibmca_keymgmt_ec_imexport_priv_key; case OSSL_KEYMGMT_SELECT_PUBLIC_KEY: return ibmca_keymgmt_ec_imexport_pub_key; case OSSL_KEYMGMT_SELECT_KEYPAIR: return ibmca_keymgmt_ec_imexport_key_pair; case OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: return ibmca_keymgmt_ec_imexport_dom_params; case OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: return ibmca_keymgmt_ec_imexport_priv_key_dom_params; case OSSL_KEYMGMT_SELECT_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: return ibmca_keymgmt_ec_imexport_pub_key_dom_params; case OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS: return ibmca_keymgmt_ec_imexport_key_pair_dom_params; case OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS: return ibmca_keymgmt_ec_imexport_other_params; case OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS: return ibmca_keymgmt_ec_imexport_priv_key_other_params; case OSSL_KEYMGMT_SELECT_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS: return ibmca_keymgmt_ec_imexport_pub_key_other_params; case OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS: return ibmca_keymgmt_ec_imexport_key_pair_other_params; case OSSL_KEYMGMT_SELECT_ALL_PARAMETERS: return ibmca_keymgmt_ec_imexport_all_params; case OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS: return ibmca_keymgmt_ec_imexport_priv_key_all_params; case OSSL_KEYMGMT_SELECT_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS: return ibmca_keymgmt_ec_imexport_pub_key_all_params; case OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS: return ibmca_keymgmt_ec_imexport_key_pair_all_params; } return NULL; } static int ibmca_keymgmt_ec_export(void *vkey, int selection, OSSL_CALLBACK *param_callback, void *cbarg) { struct ibmca_key *key = vkey; OSSL_PARAM_BLD *bld; OSSL_PARAM *params = NULL; EC_GROUP *group = NULL; EC_POINT *point = NULL; unsigned char *enc = NULL; size_t enc_len = 0; BIGNUM *x = NULL, *y = NULL, *d = NULL; char *name; int rc = 1, format; if (key == NULL || param_callback == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); bld = OSSL_PARAM_BLD_new(); if (bld == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "OSSL_PARAM_BLD_new failed"); return 0; } /* Public key is required when exporting private key */ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; /* Domain parameters are required when exporting public or private key */ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { /* Public key parts */ rc = ibmca_keymgmt_ec_pub_key_as_bn(key, &x, &y); if (rc == 0) goto error; group = EC_GROUP_new_by_curve_name(key->ec.curve_nid); if (group == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_GROUP_new_by_curve_name failed"); rc = 0; goto error; } point = EC_POINT_new(group); if (point == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_new failed"); rc = 0; goto error; } if (EC_POINT_set_affine_coordinates(group, point, x, y, NULL) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_set_affine_coordinates failed"); rc = 0; goto error; } /* OSSL_PKEY_PARAM_PUB_KEY */ #if OPENSSL_VERSION_PREREQ(3, 1) /* * Since OpenSSL 3.1: Export OSSL_PKEY_PARAM_PUB_KEY in the format * selected by OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT. */ format = key->ec.format; #else format = POINT_CONVERSION_COMPRESSED; #endif enc_len = EC_POINT_point2buf(group, point, format, &enc, NULL); if (enc_len == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EC_POINT_point2buf failed"); rc = 0; goto error; } rc = ibmca_param_build_set_octet_ptr(key->provctx, bld, params, OSSL_PKEY_PARAM_PUB_KEY, enc, enc_len); if (rc == 0) goto error; } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { /* Private key parts */ rc = ibmca_keymgmt_ec_priv_key_as_bn(key, &d); if (rc == 0) goto error; if (rc > 0) { rc = ibmca_keymgmt_ec_priv_key_to_data(key, d, bld, NULL); if (rc == 0) goto error; } } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { /* OSSL_PKEY_PARAM_GROUP_NAME */ rc = ibmca_param_build_set_utf8(key->provctx, bld, NULL, OSSL_PKEY_PARAM_GROUP_NAME, OBJ_nid2sn(key->ec.curve_nid)); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_EC_ENCODING */ rc = ibmca_param_build_set_utf8(key->provctx, bld, NULL, OSSL_PKEY_PARAM_EC_ENCODING, OSSL_PKEY_EC_ENCODING_GROUP); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT */ switch (key->ec.format) { case POINT_CONVERSION_COMPRESSED: name = OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED; break; case POINT_CONVERSION_UNCOMPRESSED: name = OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED; break; case POINT_CONVERSION_HYBRID: name = OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID; break; default: name = ""; break; } rc = ibmca_param_build_set_utf8(key->provctx, bld, NULL, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, name); if (rc == 0) goto error; } if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) { /* OSSL_PKEY_PARAM_USE_COFACTOR_ECDH */ rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, 0); if (rc == 0) goto error; /* OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC */ rc = ibmca_param_build_set_int(key->provctx, bld, NULL, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, key->ec.include_pub ? 1 : 0); if (rc == 0) goto error; } params = OSSL_PARAM_BLD_to_param(bld); if (params == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "OSSL_PARAM_BLD_to_param failed"); rc = 0; goto error; } rc = param_callback(params, cbarg); OSSL_PARAM_free(params); error: OSSL_PARAM_BLD_free(bld); if (x != NULL) BN_free(x); if (y != NULL) BN_free(y); if (d != NULL) BN_free(d); if (group != NULL) EC_GROUP_free(group); if (point != NULL) EC_POINT_free(point); if (enc != NULL) P_FREE(key->provctx, enc); return rc; } static int ibmca_keymgmt_ec_import(void *vkey, int selection, const OSSL_PARAM params[]) { struct ibmca_key *key = vkey; const OSSL_PARAM *parm; point_conversion_form_t format; BIGNUM *x = NULL, *y = NULL, *d = NULL; OSSL_PARAM grp_params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; EC_GROUP *group; const char *name; int value, rc = 0; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); for (parm = params; parm != NULL && parm->key != NULL; parm++) ibmca_debug_key(key, "param: %s", parm->key); /* Clear any already existing key components */ ibmca_keymgmt_ec_free_cb(key); ibmca_clean_fallback_pkey_cache(key); if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "EC domain parameters are mandatory"); return 0; } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { /* OSSL_PKEY_PARAM_GROUP_NAME */ rc = ibmca_param_get_utf8(key->provctx, params, OSSL_PKEY_PARAM_GROUP_NAME, &name); if (rc == 0) return 0; if (rc > 0) { grp_params[0] = OSSL_PARAM_construct_utf8_ptr( OSSL_PKEY_PARAM_GROUP_NAME, (char **)&name, 0); group = EC_GROUP_new_from_params(grp_params, key->provctx->libctx, NULL); if (group == NULL) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "EC '%s': '%s' is an unsupported curve", OSSL_PKEY_PARAM_GROUP_NAME, name); return 0; } key->ec.curve_nid = EC_GROUP_get_curve_name(group); EC_GROUP_free(group); ibmca_debug_key(key, "curve_nid: %d", key->ec.curve_nid); } /* OSSL_PKEY_PARAM_EC_ENCODING */ rc = ibmca_param_get_utf8(key->provctx, params, OSSL_PKEY_PARAM_EC_ENCODING, &name); if (rc == 0) return 0; if (rc > 0) { /* We only support named curves */ if (strcasecmp(name, OSSL_PKEY_EC_ENCODING_GROUP) != 0) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "EC '%s': '%s' is an unsupported encoding", OSSL_PKEY_PARAM_EC_ENCODING, name); return 0; } } } if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) { /* OSSL_PKEY_PARAM_USE_COFACTOR_ECDH */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, &value); if (rc == 0) return 0; if (rc > 0) { /* We do not support Cofactor DH (ECC CDH) */ if (value != 0) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "EC '%s': %d is not supported", OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, value); return 0; } } /* OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC */ rc = ibmca_param_get_int(key->provctx, params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, &value); if (rc == 0) return 0; if (rc > 0) { key->ec.include_pub = (value != 0); ibmca_debug_key(key, "include_pub: %d", key->ec.include_pub); } } if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { /* Public key parts */ /* OSSL_PKEY_PARAM_PUB_KEY */ rc = ibmca_keymgmt_ec_pub_key_from_data(key, params, &x, &y, &format); if (rc == 0) goto out; if (rc > 0 && x != NULL && y != NULL) { rc = ibmca_keymgmt_ec_pub_key_from_bn(key, x, y); if (rc == 0) goto out; key->ec.format = format; ibmca_debug_key(key, "format: %d", key->ec.format); } } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { /* OSSL_PKEY_PARAM_PRIV_KEY */ rc = ibmca_keymgmt_ec_priv_key_from_data(key, params, &d); if (rc == 0) goto out; if (rc > 0 && d != NULL) { rc = ibmca_keymgmt_ec_priv_key_from_bn(key, d); if (rc == 0) goto out; key->ec.format = format; ibmca_debug_key(key, "format: %d", key->ec.format); } } rc = 1; out: if (x != NULL) BN_free(x); if (y != NULL) BN_free(y); if (d != NULL) BN_free(d); return rc; } static const OSSL_DISPATCH ibmca_ec_keymgmt_functions[] = { /* Constructor, destructor */ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ibmca_keymgmt_ec_new }, { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ibmca_keymgmt_free }, { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ibmca_keymgmt_dup }, /* Key generation and loading */ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ibmca_keymgmt_ec_gen_init }, { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))ibmca_keymgmt_ec_gen_set_template }, { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ibmca_keymgmt_ec_gen_set_params }, { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))ibmca_keymgmt_ec_gen_settable_params }, { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ibmca_keymgmt_ec_gen }, { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ibmca_keymgmt_gen_cleanup }, { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ibmca_keymgmt_load }, /* Key object checking */ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ibmca_keymgmt_ec_has }, { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ibmca_keymgmt_ec_match }, { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ibmca_keymgmt_ec_validate }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ibmca_keymgmt_ec_query_operation_name }, /* Key object information */ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ibmca_keymgmt_ec_get_params }, { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ibmca_keymgmt_ec_gettable_params }, { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ibmca_keymgmt_ec_set_params }, { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ibmca_keymgmt_ec_settable_params }, /* Import and export routines */ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ibmca_keymgmt_ec_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ibmca_keymgmt_ec_imexport_types }, { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ibmca_keymgmt_ec_import }, { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ibmca_keymgmt_ec_imexport_types }, { 0, NULL } }; const OSSL_ALGORITHM ibmca_ec_keymgmt[] = { { "EC:id-ecPublicKey:1.2.840.10045.2.1", NULL, ibmca_ec_keymgmt_functions, "IBMCA EC implementation" }, { NULL, NULL, NULL, NULL } }; struct ibmca_tls_group_constants { unsigned int group_id; unsigned int secbits; int mintls; int maxtls; int mindtls; int maxdtls; }; #define IBMCA_TLS_GROUP_ID_secp192r1 19 #define IBMCA_TLS_GROUP_ID_secp224r1 21 #define IBMCA_TLS_GROUP_ID_secp256r1 23 #define IBMCA_TLS_GROUP_ID_secp384r1 24 #define IBMCA_TLS_GROUP_ID_secp521r1 25 #define IBMCA_TLS_GROUP_ID_brainpoolP256r1 28 #define IBMCA_TLS_GROUP_ID_brainpoolP384r1 27 #define IBMCA_TLS_GROUP_ID_brainpoolP512r1 28 static const struct ibmca_tls_group_constants ibmca_tls_group_consts[8] = { { IBMCA_TLS_GROUP_ID_secp192r1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION }, { IBMCA_TLS_GROUP_ID_secp224r1, 112, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION }, { IBMCA_TLS_GROUP_ID_secp256r1, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0 }, { IBMCA_TLS_GROUP_ID_secp384r1, 192, TLS1_VERSION, 0, DTLS1_VERSION, 0 }, { IBMCA_TLS_GROUP_ID_secp521r1, 256, TLS1_VERSION, 0, DTLS1_VERSION, 0 }, { IBMCA_TLS_GROUP_ID_brainpoolP256r1, 128, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION }, { IBMCA_TLS_GROUP_ID_brainpoolP384r1, 192, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION }, { IBMCA_TLS_GROUP_ID_brainpoolP512r1, 256, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION }, }; #define IBMCA_TLS_GROUP_ENTRY(tlsname, realname, algorithm, idx) \ { \ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, \ tlsname, sizeof(tlsname)), \ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, \ realname, sizeof(realname)), \ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, \ algorithm, sizeof(algorithm)), \ OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, \ (unsigned int *)&ibmca_tls_group_consts[idx].group_id), \ OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, \ (unsigned int *)&ibmca_tls_group_consts[idx].secbits), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, \ (unsigned int *)&ibmca_tls_group_consts[idx].mintls), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, \ (unsigned int *)&ibmca_tls_group_consts[idx].maxtls), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, \ (unsigned int *)&ibmca_tls_group_consts[idx].mindtls), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, \ (unsigned int *)&ibmca_tls_group_consts[idx].maxdtls), \ OSSL_PARAM_END \ } static const OSSL_PARAM ibmca_ec_secp192r1[] = IBMCA_TLS_GROUP_ENTRY("secp192r1", "prime192v1", "EC", 0); static const OSSL_PARAM ibmca_ec_p192[] = IBMCA_TLS_GROUP_ENTRY("P-192", "prime192v1", "EC", 0); static const OSSL_PARAM ibmca_ec_secp224r1[] = IBMCA_TLS_GROUP_ENTRY("secp224r1", "secp224r1", "EC", 1); static const OSSL_PARAM ibmca_ec_p224[] = IBMCA_TLS_GROUP_ENTRY("P-224", "secp224r1", "EC", 1); static const OSSL_PARAM ibmca_ec_secp256r1[] = IBMCA_TLS_GROUP_ENTRY("secp256r1", "prime256v1", "EC", 2); static const OSSL_PARAM ibmca_ec_p256[] = IBMCA_TLS_GROUP_ENTRY("P-256", "prime256v1", "EC", 2); static const OSSL_PARAM ibmca_ec_secp384r1[] = IBMCA_TLS_GROUP_ENTRY("secp384r1", "secp384r1", "EC", 3); static const OSSL_PARAM ibmca_ec_p384[] = IBMCA_TLS_GROUP_ENTRY("P-384", "secp384r1", "EC", 3); static const OSSL_PARAM ibmca_ec_secp521r1[] = IBMCA_TLS_GROUP_ENTRY("secp521r1", "secp521r1", "EC", 4); static const OSSL_PARAM ibmca_ec_p521[] = IBMCA_TLS_GROUP_ENTRY("P-521", "secp521r1", "EC", 4); static const OSSL_PARAM ibmca_ec_brainpoolP256r1[] = IBMCA_TLS_GROUP_ENTRY("brainpoolP256r1", "brainpoolP256r1", "EC", 5); static const OSSL_PARAM ibmca_ec_brainpoolP384r1[] = IBMCA_TLS_GROUP_ENTRY("brainpoolP384r1", "brainpoolP384r1", "EC", 6); static const OSSL_PARAM ibmca_ec_brainpoolP512r1[] = IBMCA_TLS_GROUP_ENTRY("brainpoolP512r1", "brainpoolP512r1", "EC", 7); static const OSSL_PARAM *ibmca_ec_tls_group[] = { ibmca_ec_secp192r1, ibmca_ec_p192, ibmca_ec_secp224r1, ibmca_ec_p224, ibmca_ec_secp256r1, ibmca_ec_p256, ibmca_ec_secp384r1, ibmca_ec_p384, ibmca_ec_secp521r1, ibmca_ec_p521, ibmca_ec_brainpoolP256r1, ibmca_ec_brainpoolP384r1, ibmca_ec_brainpoolP512r1, NULL }; const struct ibmca_mech_capability ibmca_ec_capabilities[] = { { "TLS-GROUP", ibmca_ec_tls_group }, { NULL, NULL } }; openssl-ibmca-2.4.1/src/provider/ec_signature.c000066400000000000000000000772771450276407300215430ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include #include #include #include "p_ibmca.h" static OSSL_FUNC_signature_newctx_fn ibmca_signature_ec_newctx; static OSSL_FUNC_signature_sign_init_fn ibmca_signature_ec_sign_init; static OSSL_FUNC_signature_sign_fn ibmca_signature_ec_sign; static OSSL_FUNC_signature_verify_init_fn ibmca_signature_ec_verify_init; static OSSL_FUNC_signature_verify_fn ibmca_signature_ec_verify; static OSSL_FUNC_signature_digest_sign_init_fn ibmca_signature_ec_digest_sign_init; static OSSL_FUNC_signature_digest_sign_update_fn ibmca_signature_ec_digest_signverify_update; static OSSL_FUNC_signature_digest_sign_final_fn ibmca_signature_ec_digest_sign_final; static OSSL_FUNC_signature_digest_verify_init_fn ibmca_signature_ec_digest_verify_init; static OSSL_FUNC_signature_digest_verify_final_fn ibmca_signature_ec_digest_verify_final; static OSSL_FUNC_signature_get_ctx_params_fn ibmca_signature_ec_get_ctx_params; static OSSL_FUNC_signature_gettable_ctx_params_fn ibmca_signature_ec_gettable_ctx_params; static OSSL_FUNC_signature_set_ctx_params_fn ibmca_signature_ec_set_ctx_params; static OSSL_FUNC_signature_settable_ctx_params_fn ibmca_signature_ec_settable_ctx_params; static OSSL_FUNC_signature_get_ctx_md_params_fn ibmca_signature_ec_get_ctx_md_params; static OSSL_FUNC_signature_gettable_ctx_md_params_fn ibmca_signature_ec_gettable_ctx_md_params; static OSSL_FUNC_signature_set_ctx_md_params_fn ibmca_signature_ec_set_ctx_md_params; static OSSL_FUNC_signature_settable_ctx_md_params_fn ibmca_signature_ec_settable_ctx_md_params; static void ibmca_signature_ec_free_cb(struct ibmca_op_ctx *ctx); static int ibmca_signature_ec_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx); static void*ibmca_signature_ec_newctx(void *vprovctx, const char *propq) { const struct ibmca_prov_ctx *provctx = vprovctx; struct ibmca_op_ctx *opctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); opctx = ibmca_op_newctx(provctx, propq, EVP_PKEY_EC, ibmca_signature_ec_free_cb, ibmca_signature_ec_dup_cb); if (opctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_op_newctx failed"); return NULL; } ibmca_debug_ctx(provctx, "opctx: %p", opctx); return opctx; } static void ibmca_signature_ec_free_cb(struct ibmca_op_ctx *ctx) { if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->ec.signature.md != NULL) EVP_MD_free(ctx->ec.signature.md); ctx->ec.signature.md = NULL; ctx->ec.signature.set_md_allowed = true; ctx->ec.signature.md_size = 0; if (ctx->ec.signature.md_ctx != NULL) EVP_MD_CTX_free(ctx->ec.signature.md_ctx); ctx->ec.signature.md_ctx = NULL; } static int ibmca_signature_ec_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p new_ctx: %p", ctx, new_ctx); new_ctx->ec.signature.md = ctx->ec.signature.md; if (new_ctx->ec.signature.md != NULL) { if (EVP_MD_up_ref(new_ctx->ec.signature.md) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_up_ref failed"); return 0; } } new_ctx->ec.signature.set_md_allowed = ctx->ec.signature.set_md_allowed; new_ctx->ec.signature.md_size = ctx->ec.signature.md_size; if (ctx->ec.signature.md_ctx != NULL) { new_ctx->ec.signature.md_ctx = EVP_MD_CTX_new(); if (new_ctx->ec.signature.md_ctx == NULL || EVP_MD_CTX_copy(new_ctx->ec.signature.md_ctx, ctx->ec.signature.md_ctx) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_copy failed"); return 0; } } return 1; } static int ibmca_signature_ec_set_md(struct ibmca_op_ctx *ctx, const char *mdname, int md_nid, const char *props) { EVP_MD *md; if (mdname == NULL) mdname = OBJ_nid2sn(md_nid); ibmca_debug_op_ctx(ctx, "ctx: %p mdname: '%s'", ctx, mdname); if (!ctx->ec.signature.set_md_allowed) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest not allowed to be set in the current state"); return 0; } md = EVP_MD_fetch(ctx->provctx->libctx, mdname, props != NULL ? props : ctx->propq); if (md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest '%s' could not be fetched", mdname); return 0; } if (ctx->ec.signature.md != NULL) EVP_MD_free(ctx->ec.signature.md); ctx->ec.signature.md = md; ctx->ec.signature.md_size = EVP_MD_get_size(md); return 1; } static int ibmca_signature_ec_op_init(struct ibmca_op_ctx *ctx, struct ibmca_key *key, const OSSL_PARAM params[], int operation, const char *mdname) { const OSSL_PARAM *p; if (ctx == NULL || key == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p operation: %d mdname: %s", ctx, key, operation, mdname != NULL ? mdname : "(null)"); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); if (ibmca_op_init(ctx, key, operation) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_init failed"); return 0; } /* Setup defaults for this context */ ibmca_signature_ec_free_cb(ctx); ctx->ec.signature.set_md_allowed = true; if (mdname != NULL) { if (ibmca_signature_ec_set_md(ctx, mdname, 0, NULL) == 0) return 0; } if (params != NULL) { if (ibmca_signature_ec_set_ctx_params(ctx, params) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_signature_ec_set_ctx_params failed"); return 0; } } switch (operation) { case EVP_PKEY_OP_SIGNCTX: case EVP_PKEY_OP_VERIFYCTX: ctx->ec.signature.md_ctx = EVP_MD_CTX_new(); if (ctx->ec.signature.md_ctx == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_new failed"); return 0; } if (EVP_DigestInit_ex2(ctx->ec.signature.md_ctx, ctx->ec.signature.md, params) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestInit_ex2 failed"); return 0; } ctx->ec.signature.set_md_allowed = false; break; } return 1; } static int ibmca_signature_ec_sign_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_ec_op_init(ctx, key, params, EVP_PKEY_OP_SIGN, NULL); } static int ibmca_signature_ec_verify_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_ec_op_init(ctx, key, params, EVP_PKEY_OP_VERIFY, NULL); } static int ibmca_signature_ec_sign_fallback(struct ibmca_op_ctx *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; int rc = 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu sig: %p siglen: %lu", ctx, ctx->key, tbslen, sig, *siglen); pkey = ibmca_new_fallback_pkey(ctx->key); if (pkey == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(ctx->provctx, pkey, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_sign_init(pctx) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_sign_init failed"); goto out; } if (ibmca_check_fallback_provider(ctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } if (EVP_PKEY_sign(pctx, sig, siglen, tbs, tbslen) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_sign failed"); goto out; } rc = 1; out: if (pkey != NULL) EVP_PKEY_free(pkey); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); return rc; } static int ibmca_signature_ec_sign(void *vctx, unsigned char *sig, size_t *siglen, size_t sigsize, const unsigned char *tbs, size_t tbslen) { struct ibmca_op_ctx *ctx = vctx; ECDSA_SIG *ecdsa_sig = NULL; BIGNUM *r = NULL, *s = NULL; unsigned char *p; int rc = 0; if (ctx == NULL || siglen == NULL || tbs == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu sigsize: %lu", ctx, ctx->key, tbslen, sigsize); if (ctx->key == NULL || (ctx->operation != EVP_PKEY_OP_SIGN && ctx->operation != EVP_PKEY_OP_SIGNCTX)) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "sign operation not initialized"); return 0; } *siglen = ctx->key->get_max_param_size(ctx->key); if (sig == NULL) { /* size query */ rc = 1; goto out; } if (sigsize < *siglen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); goto out; } if (ctx->ec.signature.md_size != 0) { if (tbslen != ctx->ec.signature.md_size) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid input data size: %lu expected: %d", tbslen, ctx->ec.signature.md_size); goto out; } } if (ibmca_op_alloc_tbuf(ctx, ctx->key->ec.prime_size * 2) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); goto out; } if (ctx->key->ec.fallback.d != NULL) { rc = ibmca_signature_ec_sign_fallback(ctx, sig, siglen, tbs, tbslen); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_signature_ec_sign_fallback failed"); rc = 0; } goto out; } rc = ica_ecdsa_sign(ctx->provctx->ica_adapter, ctx->key->ec.key, tbs, tbslen, ctx->tbuf, ctx->tbuf_len); if (rc != 0) { ibmca_debug_op_ctx(ctx, "ica_ecdsa_sign failed with: %s", strerror(rc)); rc = ibmca_signature_ec_sign_fallback(ctx, sig, siglen, tbs, tbslen); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_signature_ec_sign_fallback failed"); rc = 0; } goto out; } r = BN_bin2bn(ctx->tbuf, ctx->key->ec.prime_size, NULL); s = BN_bin2bn(ctx->tbuf + ctx->key->ec.prime_size, ctx->key->ec.prime_size, NULL); if (r == NULL || s == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); goto out; } ecdsa_sig = ECDSA_SIG_new(); if (ecdsa_sig == NULL || ECDSA_SIG_set0(ecdsa_sig, r, s) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "ECDSA_SIG_new/ECDSA_SIG_set0 failed"); goto out; } r = NULL; s = NULL; p = sig; *siglen = i2d_ECDSA_SIG(ecdsa_sig, &p); if (*siglen <= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "i2d_ECDSA_SIG failed"); goto out; } rc = 1; out: if (ecdsa_sig != NULL) ECDSA_SIG_free(ecdsa_sig); if (r != NULL) BN_free(r); if (s != NULL) BN_free(s); ibmca_debug_op_ctx(ctx, "siglen: %lu rc: %d", *siglen, rc); return rc; } static int ibmca_signature_ec_verify_fallback(struct ibmca_op_ctx *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; int rc = 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu sig: %p siglen: %lu", ctx, ctx->key, tbslen, sig, siglen); pkey = ibmca_new_fallback_pkey(ctx->key); if (pkey == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(ctx->provctx, pkey, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_verify_init(pctx) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_verify_init failed"); goto out; } if (ibmca_check_fallback_provider(ctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } rc = EVP_PKEY_verify(pctx, sig, siglen, tbs, tbslen); if (rc < 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_verify failed with %d", rc); goto out; } if (rc == 0) { put_error_op_ctx(ctx, IBMCA_ERR_SIGNATURE_BAD, "Signature bad"); goto out; } rc = 1; out: if (pkey != NULL) EVP_PKEY_free(pkey); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); return rc; } static int ibmca_signature_ec_verify(void *vctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { struct ibmca_op_ctx *ctx = vctx; ECDSA_SIG *ecdsa_sig = NULL; const BIGNUM *r, *s; const unsigned char *p; unsigned char *der = NULL; int derlen = -1; int rc = -1; if (ctx == NULL || sig == NULL || tbs == NULL) return -1; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu siglen: %lu", ctx, ctx->key, tbslen, siglen); if (ctx->key == NULL || (ctx->operation != EVP_PKEY_OP_VERIFY && ctx->operation != EVP_PKEY_OP_VERIFYCTX)) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "verify operation not initialized"); return -1; } if (ctx->ec.signature.md_size != 0) { if (tbslen != ctx->ec.signature.md_size) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid input data size: %lu expected: %d", tbslen, ctx->ec.signature.md_size); goto out; } } if (ibmca_op_alloc_tbuf(ctx, ctx->key->ec.prime_size * 2) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); goto out; } if (ctx->key->ec.fallback.x != NULL && ctx->key->ec.fallback.y) { rc = ibmca_signature_ec_verify_fallback(ctx, sig, siglen, tbs, tbslen); goto out; } p = sig; if (d2i_ECDSA_SIG(&ecdsa_sig, &p, siglen) == NULL || ecdsa_sig == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_SIGNATURE_BAD, "d2i_ECDSA_SIG failed"); goto out; } /* Ensure signature uses DER and doesn't have trailing garbage */ derlen = i2d_ECDSA_SIG(ecdsa_sig, &der); if ((size_t)derlen != siglen || memcmp(sig, der, derlen) != 0) { put_error_op_ctx(ctx, IBMCA_ERR_SIGNATURE_BAD, "Signature encoding wrong"); goto out; } r = ECDSA_SIG_get0_r(ecdsa_sig); s = ECDSA_SIG_get0_s(ecdsa_sig); if (r == NULL || s == NULL || BN_bn2binpad(r, ctx->tbuf, ctx->key->ec.prime_size) <= 0 || BN_bn2binpad(s, ctx->tbuf + ctx->key->ec.prime_size, ctx->key->ec.prime_size) <= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); goto out; } rc = ica_ecdsa_verify(ctx->provctx->ica_adapter, ctx->key->ec.key, tbs, tbslen, ctx->tbuf, ctx->tbuf_len); if (rc == EFAULT) { put_error_op_ctx(ctx, IBMCA_ERR_SIGNATURE_BAD, "Bad signature"); rc = 0; goto out; } if (rc != 0) { ibmca_debug_op_ctx(ctx, "ica_ecdsa_verify failed with: %s", strerror(rc)); rc = ibmca_signature_ec_verify_fallback(ctx, sig, siglen, tbs, tbslen); goto out; } rc = 1; out: if (ecdsa_sig != NULL) ECDSA_SIG_free(ecdsa_sig); if (der != NULL) P_FREE(ctx->provctx, der); ibmca_debug_op_ctx(ctx, "rc: %d", rc); return rc; } static int ibmca_signature_ec_get_algid(struct ibmca_op_ctx *ctx, OSSL_PARAM *p) { ASN1_OBJECT *oid = NULL; X509_ALGOR * algid = NULL; unsigned char *aid_buf = NULL; size_t aid_len; if (ctx->ec.signature.md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "No digest is set"); return 0; } switch (EVP_MD_get_type(ctx->ec.signature.md)) { case NID_sha1: oid = OBJ_nid2obj(NID_ecdsa_with_SHA1); break; case NID_sha224: oid = OBJ_nid2obj(NID_ecdsa_with_SHA224); break; case NID_sha256: oid = OBJ_nid2obj(NID_ecdsa_with_SHA256); break; case NID_sha384: oid = OBJ_nid2obj(NID_ecdsa_with_SHA384); break; case NID_sha512: oid = OBJ_nid2obj(NID_ecdsa_with_SHA512); break; case NID_sha3_224: oid = OBJ_nid2obj(NID_ecdsa_with_SHA3_224); break; case NID_sha3_256: oid = OBJ_nid2obj(NID_ecdsa_with_SHA3_256); break; case NID_sha3_384: oid = OBJ_nid2obj(NID_ecdsa_with_SHA3_384); break; case NID_sha3_512: oid = OBJ_nid2obj(NID_ecdsa_with_SHA3_512); break; default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "AlgorithmID not supported for digest '%s'", EVP_MD_get0_name(ctx->ec.signature.md)); return 0; } algid = X509_ALGOR_new(); if (algid == NULL || X509_ALGOR_set0(algid, oid, V_ASN1_UNDEF, NULL) == 0 || (aid_len = i2d_X509_ALGOR(algid, &aid_buf)) <= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "X509_ALGOR_new/X509_ALGOR_set0/i2d_X509_ALGOR failed"); X509_ALGOR_free(algid); return 0; } if (OSSL_PARAM_set_octet_string(p, aid_buf, aid_len) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", OSSL_SIGNATURE_PARAM_ALGORITHM_ID); P_FREE(ctx->provctx, aid_buf); X509_ALGOR_free(algid); return 0; } P_FREE(ctx->provctx, aid_buf); X509_ALGOR_free(algid); ibmca_debug_op_ctx(ctx, "param '%s': [octet string] (%lu bytes)", OSSL_SIGNATURE_PARAM_ALGORITHM_ID, aid_len); return 1; } static int ibmca_signature_ec_get_ctx_params(void *vctx, OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; OSSL_PARAM *p; const char *name = NULL; int rc; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_SIGNATURE_PARAM_ALGORITHM_ID */ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID); if (p != NULL && ibmca_signature_ec_get_algid(ctx, p) == 0) return 0; /* OSSL_SIGNATURE_PARAM_DIGEST */ if (ctx->ec.signature.md != NULL) name = EVP_MD_get0_name(ctx->ec.signature.md); else name = ""; rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_DIGEST, name); if (rc == 0) return 0; /* OSSL_SIGNATURE_PARAM_DIGEST_SIZE */ rc = ibmca_param_build_set_size_t(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_DIGEST, ctx->ec.signature.md_size); if (rc == 0) return 0; #ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE /* OSSL_SIGNATURE_PARAM_NONCE_TYPE */ rc = ibmca_param_build_set_uint(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_NONCE_TYPE, 0); if (rc == 0) return 0; #endif return 1; } static int ibmca_signature_ec_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; const OSSL_PARAM *p; const char *name, *props = NULL; size_t md_size; #ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE unsigned int nonce_type; #endif int rc; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_SIGNATURE_PARAM_PROPERTIES */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_SIGNATURE_PARAM_PROPERTIES, &props); if (rc == 0) return 0; /* OSSL_SIGNATURE_PARAM_DIGEST */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_SIGNATURE_PARAM_DIGEST, &name); if (rc == 0) return 0; if (rc > 0 && ibmca_signature_ec_set_md(ctx, name, 0, props) == 0) return 0; /* OSSL_SIGNATURE_PARAM_DIGEST_SIZE */ rc = ibmca_param_get_size_t(ctx->provctx, params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE, &md_size); if (rc == 0) return 0; if (rc > 0) { if (!ctx->ec.signature.set_md_allowed) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest size not allowed to be set in the current state"); return 0; } ctx->ec.signature.md_size = md_size; } #ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE /* OSSL_SIGNATURE_PARAM_NONCE_TYPE */ rc = ibmca_param_get_uint(ctx->provctx, params, OSSL_SIGNATURE_PARAM_NONCE_TYPE, &nonce_type); if (rc == 0) return 0; /* Only allow nonce_type = 0 = random K */ if (nonce_type != 0) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Deterministic signature is not supported"); return 0; } #endif return 1; } static const OSSL_PARAM ibmca_signature_ec_gettable_params[] = { OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), #ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL), #endif OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_signature_ec_gettable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; ibmca_debug_ctx(provctx, "ctx: %p", ctx); for (p = ibmca_signature_ec_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_signature_ec_gettable_params; } static const OSSL_PARAM ibmca_signature_ec_settable_params[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0), #ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL), #endif OSSL_PARAM_END }; static const OSSL_PARAM ibmca_signature_ec_settable_params_no_digest[] = { OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_signature_ec_settable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p, *params; ibmca_debug_ctx(provctx, "ctx: %p", ctx); if (ctx->ec.signature.set_md_allowed) params = ibmca_signature_ec_settable_params; else params = ibmca_signature_ec_settable_params_no_digest; for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return params; } static int ibmca_signature_ec_digest_sign_init(void *vctx, const char *mdname, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_ec_op_init(ctx, key, params, EVP_PKEY_OP_SIGNCTX, mdname); } static int ibmca_signature_ec_digest_verify_init(void *vctx, const char *mdname, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_ec_op_init(ctx, key, params, EVP_PKEY_OP_VERIFYCTX, mdname); } static int ibmca_signature_ec_digest_signverify_update(void *vctx, const unsigned char *data, size_t datalen) { struct ibmca_op_ctx *ctx = vctx; return ibmca_digest_signverify_update(ctx, ctx->ec.signature.md_ctx, data, datalen); } static int ibmca_signature_ec_digest_sign_final(void *vctx, unsigned char *sig, size_t *siglen, size_t sigsize) { struct ibmca_op_ctx *ctx = vctx; return ibmca_digest_sign_final(ctx, ctx->ec.signature.md_ctx, ibmca_signature_ec_sign, sig, siglen, sigsize); } static int ibmca_signature_ec_digest_verify_final(void *vctx, const unsigned char *sig, size_t siglen) { struct ibmca_op_ctx *ctx = vctx; return ibmca_digest_verify_final(ctx, ctx->ec.signature.md_ctx, ibmca_signature_ec_verify, sig, siglen); } static int ibmca_signature_ec_get_ctx_md_params(void *vctx, OSSL_PARAM *params) { struct ibmca_op_ctx *ctx = vctx; return ibmca_get_ctx_md_params(ctx, ctx->ec.signature.md_ctx, params); } static int ibmca_signature_ec_set_ctx_md_params(void *vctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; return ibmca_set_ctx_md_params(ctx, ctx->ec.signature.md_ctx, params); } static const OSSL_PARAM *ibmca_signature_ec_gettable_ctx_md_params(void *vctx) { struct ibmca_op_ctx *ctx = vctx; return ibmca_gettable_ctx_md_params(ctx, ctx->ec.signature.md); } static const OSSL_PARAM *ibmca_signature_ec_settable_ctx_md_params(void *vctx) { struct ibmca_op_ctx *ctx = vctx; return ibmca_settable_ctx_md_params(ctx, ctx->ec.signature.md); } static const OSSL_DISPATCH ibmca_ecdsa_signature_functions[] = { /* Signature context constructor, destructor */ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ibmca_signature_ec_newctx }, { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ibmca_op_freectx }, { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ibmca_op_dupctx }, /* Signing */ { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))ibmca_signature_ec_sign_init }, { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ibmca_signature_ec_sign }, /* Verifying */ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))ibmca_signature_ec_verify_init }, { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))ibmca_signature_ec_verify }, /* Digest Sign */ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, (void (*)(void))ibmca_signature_ec_digest_sign_init }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, (void (*)(void))ibmca_signature_ec_digest_signverify_update }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, (void (*)(void))ibmca_signature_ec_digest_sign_final }, /* Digest Verify */ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, (void (*)(void))ibmca_signature_ec_digest_verify_init }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, (void (*)(void))ibmca_signature_ec_digest_signverify_update }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, (void (*)(void))ibmca_signature_ec_digest_verify_final }, /* Signature parameters */ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))ibmca_signature_ec_get_ctx_params }, { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void (*)(void))ibmca_signature_ec_gettable_ctx_params }, { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))ibmca_signature_ec_set_ctx_params }, { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, (void (*)(void))ibmca_signature_ec_settable_ctx_params }, /* MD parameters */ { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, (void (*)(void))ibmca_signature_ec_get_ctx_md_params }, { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, (void (*)(void))ibmca_signature_ec_gettable_ctx_md_params }, { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, (void (*)(void))ibmca_signature_ec_set_ctx_md_params }, { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, (void (*)(void))ibmca_signature_ec_settable_ctx_md_params }, { 0, NULL } }; const OSSL_ALGORITHM ibmca_ec_signature[] = { { "ECDSA", NULL, ibmca_ecdsa_signature_functions, "IBMCA ECDSA implementation" }, { NULL, NULL, NULL, NULL } }; openssl-ibmca-2.4.1/src/provider/ibmca-provider-opensslconfig000077500000000000000000000123501450276407300244040ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright [2021-2022] 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. # # # Generate openssl.cnf from the system config file with added provider section # for ibmca provider. # # USE WITH CARE: No automation can replace human knowledge and understanding # of the desired configuration! # use strict; use warnings; sub generate() { my ($osslconfpath); my ($ih, $line, $oh, $defaultcnfsect, $indefaultsect, $providersect, $inprovidersect); my ($inalgsect, $algsection); $osslconfpath = `openssl version -d` || die "Please install openssl binary"; $osslconfpath =~ s/OPENSSLDIR: \"([^\"]*)\"$/$1/ || die "Failed to extract OpenSSL configuration directory"; chomp $osslconfpath; open($ih, "<", "$osslconfpath/openssl.cnf") or die "Cannot open $osslconfpath/openssl.cnf"; open($oh, ">", "openssl.cnf.ibmca-provider") or die "Cannot open openssl.cnf.ibmca-provider"; $defaultcnfsect = undef; $indefaultsect = 0; $providersect = undef; $inprovidersect = 0; while ($line = <$ih>) { if ($line =~ /openssl_conf\s*=\s*(.*)/) { $defaultcnfsect = $1; chomp $defaultcnfsect; } if ($indefaultsect) { if ($line =~ /\[\s*\w+\s*\]/) { if (!$providersect) { print $oh "providers = provider_section\n"; } if (!$algsection) { print $oh "alg_section = evp_properties\n"; } $indefaultsect = 0; } elsif ($line =~ /^\s*providers\s*=\s*(\w+)\s*/) { $providersect = $1; chomp $providersect; } elsif ($line =~ /^\s*alg_section\s*=\s*(\w+)\s*/) { $algsection = $1; chomp $algsection; } } elsif ($inalgsect) { if ($line =~ /\[\s*\w+\s*\]/) { print $oh "default_properties = ?provider=ibmca\n"; $inalgsect = 0; } elsif ($line =~ /^\s*default_properties\s*=\s*(\w+)\s*/) { print $oh "default_properties = ?provider=ibmca\n"; print $oh "# The following was commented out by ibmca-provider-opensslconfig script\n"; print "WARNING: The default_properties in $algsection was modified by this script.\n"; $line = "# $line"; } } elsif ($inprovidersect) { if ($line =~ /\[\s*\w+\s*\]/) { $inprovidersect = 0; print $oh "ibmca_provider = ibmca_provider_section\n"; print $oh "# Make sure that you have configured and activated at least one other provider!\n"; print "WARNING: The IBMCA provider was added to section [$providersect].\n"; print "Make sure that you have configured and activated at least one other provider, e.g. the default provider!\n"; } } print $oh "$line"; if ($defaultcnfsect && $line =~ /\[\s*$defaultcnfsect\s*\]/) { $indefaultsect = 1; } if ($algsection && $line =~ /\[\s*$algsection\s*\]/) { $inalgsect = 1; } if ($providersect && $line =~ /\[\s*$providersect\s*\]/) { $inprovidersect = 1; } } if (!$defaultcnfsect) { print $oh, qq| openssl_conf = openssl_init [openssl_init] providers = provider_section |; } if (!$providersect) { print $oh qq| [provider_section] default = default_sect ibmca_provider = ibmca_provider_section [default_sect] activate = 1 |; } print $oh qq| [ibmca_provider_section] identity = ibmca module = ibmca-provider.so activate = 1 # Note: Disable the FIPS mode of the IBMCA provider by setting fips=no in the # provider configuration. The IBMCA provider is currently not FIPS-certified. # It does not perform any FIPS self-tests itself nor an integrity check which # would be required to be FIPS-certified. It is only checked whether libica # library has successfully performed its self-tests and integrity checks when # FIPS mode is enabled. fips = no # Note: Depending on the hardware level (IBM z15), EC is already accelerated # implicitly by OpenSSL for certain curves. Therefore, do not accelerate EC # using the IBMCA provider if you are on an IBM z15 or later. This would # actually make it slower. algorithms = RSA,EC,DH #fallback-properties = provider=default |; if (!$algsection) { print $oh qq| [evp_properties] default_properties = ?provider=ibmca |; } close($ih); close($oh); print qq| Successfully generated openssl.cnf.ibmca-provider file. Please review this configuration and, if you are happy with the changes, replace $osslconfpath/openssl.cnf with this file. |; } generate(); openssl-ibmca-2.4.1/src/provider/ibmca-provider.map000066400000000000000000000001311450276407300223000ustar00rootroot00000000000000IBMCA_PROVIDER_1.1.0 { global: OSSL_provider_init; local: *; }; openssl-ibmca-2.4.1/src/provider/openssl.cnf.provider.sample000066400000000000000000000024641450276407300241750ustar00rootroot00000000000000# # OpenSSL example configuration file. This file will load the IBMCA provider # 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] providers = provider_sect alg_section = evp_properties [provider_sect] default = default_sect ibmca_provider = ibmca_sect [default_sect] activate = 1 [ibmca_sect] identity = ibmca module = ibmca-provider.so activate = 1 # Note: Disable the FIPS mode of the IBMCA provider by setting fips=no in the # provider configuration. The IBMCA provider is currently not FIPS-certified. # It does not perform any FIPS self-tests itself nor an integrity check which # would be required to be FIPS-certified. It is only checked whether libica # library has successfully performed its self-tests and integrity checks when # FIPS mode is enabled. fips = no # Note: Depending on the hardware level (IBM z15), EC is already accelerated # implicitly by OpenSSL for certain curves. Therefore, do not accelerate EC # using the IBMCA provider if you are on an IBM z15 or later. This would # actually make it slower. algorithms = RSA,EC,DH #fallback-properties = provider=default [evp_properties] default_properties = ?provider=ibmca openssl-ibmca-2.4.1/src/provider/p_context.c000066400000000000000000000306051450276407300210560ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include "p_ibmca.h" struct ibmca_op_ctx *ibmca_op_newctx(const struct ibmca_prov_ctx *provctx, const char *propq, int type, void (*free_cb)(struct ibmca_op_ctx *ctx), int (*dup_cb) (const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx)) { struct ibmca_op_ctx *ctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "propq: %s type: %d", propq != NULL ? propq : "", type); ctx = P_ZALLOC(provctx, sizeof(struct ibmca_op_ctx)); if (ctx == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate operation context"); return NULL; } ctx->provctx = provctx; ctx->type = type; ctx->free_cb = free_cb; ctx->dup_cb = dup_cb; if (propq != NULL) { ctx->propq = P_STRDUP(provctx, propq); if (ctx->propq == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "strdup failed"); P_FREE(provctx, ctx); return NULL; } } ibmca_debug_ctx(provctx, "ctx: %p", ctx); return ctx; } void ibmca_op_freectx(void *vctx) { struct ibmca_op_ctx *ctx = vctx; if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->key != NULL) ibmca_keymgmt_free(ctx->key); ctx->key = NULL; if (ctx->propq != NULL) P_FREE(ctx->provctx, (void *)ctx->propq); ctx->propq = NULL; if (ctx->free_cb != NULL) ctx->free_cb(ctx); if (ctx->tbuf != NULL) P_SECURE_CLEAR_FREE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); ctx->tbuf = NULL; ctx->tbuf_len = 0; P_FREE(ctx->provctx, ctx); } void *ibmca_op_dupctx(void *vctx) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_op_ctx *new_ctx; if (ctx == NULL) return NULL; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); new_ctx = ibmca_op_newctx(ctx->provctx, ctx->propq, ctx->type, ctx->free_cb, ctx->dup_cb); if (new_ctx == NULL) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_newctx failed"); return NULL; } new_ctx->operation = ctx->operation; if (ctx->key != NULL) { new_ctx->key = ctx->key; ibmca_keymgmt_upref(ctx->key); } if (ctx->dup_cb != NULL) { if (ctx->dup_cb(ctx, new_ctx) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: dup_cb failed"); ibmca_op_freectx(new_ctx); return NULL; } } ibmca_debug_op_ctx(ctx, "new_ctx: %p", new_ctx); return new_ctx; } int ibmca_op_init(struct ibmca_op_ctx *ctx, struct ibmca_key *key, int operation) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p operation: %d", ctx, key, operation); if (key != NULL) { switch (ctx->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA_PSS: if (key->type != EVP_PKEY_RSA && key->type != EVP_PKEY_RSA_PSS) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "key type mismatch: ctx type: %d key type: %d", ctx->type, key->type); return 0; } break; case EVP_PKEY_EC: if (key->type != EVP_PKEY_EC) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "key type mismatch: ctx type: %d key type: %d", ctx->type, key->type); return 0; } break; case EVP_PKEY_DH: case EVP_PKEY_DHX: if (key->type != EVP_PKEY_DH && key->type != EVP_PKEY_DHX) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "key type mismatch: ctx type: %d key type: %d", ctx->type, key->type); return 0; } break; default: put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "key type unknown: ctx type: %d key type: %d", ctx->type, key->type); return 0; } switch (operation) { case EVP_PKEY_OP_DECRYPT: case EVP_PKEY_OP_DERIVE: case EVP_PKEY_OP_SIGN: case EVP_PKEY_OP_SIGNCTX: if (key->has(key, OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "operation %d not possible without a private key", operation); return 0; } break; case EVP_PKEY_OP_ENCRYPT: case EVP_PKEY_OP_VERIFY: case EVP_PKEY_OP_VERIFYCTX: if (key->has(key, OSSL_KEYMGMT_SELECT_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "operation %d not possible without a public key", operation); return 0; } break; } ibmca_keymgmt_upref(key); } if (ctx->key != NULL) ibmca_keymgmt_free(ctx->key); ctx->key = key; ctx->operation = operation; return 1; } int ibmca_op_alloc_tbuf(struct ibmca_op_ctx *ctx, size_t tbuf_len) { ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->tbuf != NULL) { if (ctx->tbuf_len >= tbuf_len) return 1; P_FREE(ctx->provctx, ctx->tbuf); ctx->tbuf_len = 0; } ctx->tbuf = P_SECURE_ZALLOC(ctx->provctx, tbuf_len); if (ctx->tbuf == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate temporary buffer"); return 0; } ctx->tbuf_len = tbuf_len; return 1; } int ibmca_digest_signverify_update(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, const unsigned char *data, size_t datalen) { if (ctx == NULL || data == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p datalen: %lu", ctx, ctx->key, datalen); if (ctx->key == NULL || md_ctx == NULL || (ctx->operation != EVP_PKEY_OP_SIGNCTX && ctx->operation != EVP_PKEY_OP_VERIFYCTX)) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "sign operation not initialized"); return 0; } if (EVP_DigestUpdate(md_ctx, data, datalen) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestUpdate failed"); return 0; } return 1; } int ibmca_digest_sign_final(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, OSSL_FUNC_signature_sign_fn *sign_func, unsigned char *sig, size_t *siglen, size_t sigsize) { unsigned char tbs[EVP_MAX_MD_SIZE]; unsigned int tbslen = 0; if (ctx == NULL || siglen == NULL || sign_func == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p sigsize: %lu", ctx, ctx->key, sigsize); if (ctx->key == NULL || md_ctx == NULL || ctx->operation != EVP_PKEY_OP_SIGNCTX) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "sign operation not initialized"); return 0; } if (sig != NULL) { if (EVP_DigestFinal_ex(md_ctx, tbs, &tbslen) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestFinal_ex failed"); return 0; } } if (sign_func(ctx, sig, siglen, sigsize, tbs, (size_t)tbslen) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: sign_func failed"); return 0; } ibmca_debug_op_ctx(ctx, "siglen: %lu", *siglen); return 1; } int ibmca_digest_verify_final(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, OSSL_FUNC_signature_verify_fn *verify_func, const unsigned char *sig, size_t siglen) { unsigned char tbs[EVP_MAX_MD_SIZE]; unsigned int tbslen = 0; if (ctx == NULL || sig == NULL || verify_func == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p siglen: %lu", ctx, ctx->key, siglen); if (ctx->key == NULL || md_ctx == NULL || ctx->operation != EVP_PKEY_OP_VERIFYCTX) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "verify operation not initialized"); return 0; } if (EVP_DigestFinal_ex(md_ctx, tbs, &tbslen) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestFinal_ex failed"); return 0; } return verify_func(ctx, sig, siglen, tbs, (size_t)tbslen); } int ibmca_get_ctx_md_params(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, OSSL_PARAM *params) { const OSSL_PARAM *p; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); if (md_ctx == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest sign/verify context not initialized"); return 0; } if (EVP_MD_CTX_get_params(md_ctx, params) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_get_params failed"); return 0; } return 1; } int ibmca_set_ctx_md_params(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, const OSSL_PARAM params[]) { const OSSL_PARAM *p; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); if (md_ctx == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest sign/verify context not initialized"); return 0; } if (EVP_MD_CTX_set_params(md_ctx, params) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_set_params failed"); return 0; } return 1; } const OSSL_PARAM *ibmca_gettable_ctx_md_params(const struct ibmca_op_ctx *ctx, const EVP_MD *md) { const OSSL_PARAM *p, *params; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest sign/verify context not initialized"); return 0; } params = EVP_MD_gettable_ctx_params(md); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); return params; } const OSSL_PARAM *ibmca_settable_ctx_md_params(const struct ibmca_op_ctx *ctx, const EVP_MD *md) { const OSSL_PARAM *p, *params; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest sign/verify context not initialized"); return 0; } params = EVP_MD_settable_ctx_params(md); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); return params; } openssl-ibmca-2.4.1/src/provider/p_ibmca.c000066400000000000000000001305621450276407300204500ustar00rootroot00000000000000/* * Copyright [2021-2022] 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. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "p_ibmca.h" #ifndef IBMCA_LOGDIR #error "IBMCA_LOGDIR must be defined" #endif #ifndef IBMCA_VERSION #error "IBMCA_VERSION must be defined" #endif static OSSL_FUNC_provider_teardown_fn ibmca_teardown; static OSSL_FUNC_provider_gettable_params_fn ibmca_gettable_params; static OSSL_FUNC_provider_get_params_fn ibmca_get_params; static OSSL_FUNC_provider_query_operation_fn ibmca_query; static OSSL_FUNC_provider_get_reason_strings_fn ibmca_get_reason_strings; static OSSL_FUNC_provider_get_capabilities_fn ibmca_prov_get_capabilities; static OSSL_FUNC_provider_self_test_fn ibmca_prov_self_tests; struct ibmca_config_item { const char *key; int (*func)(struct ibmca_prov_ctx *provctx, const char *key, const char *value); }; static int ibmca_config_debug(struct ibmca_prov_ctx *provctx, const char *key, const char *value); static int ibmca_config_debug_path(struct ibmca_prov_ctx *provctx, const char *key, const char *value); static int ibmca_config_fips(struct ibmca_prov_ctx *provctx, const char *key, const char *value); static int ibmca_config_algorithms(struct ibmca_prov_ctx *provctx, const char *key, const char *value); static int ibmca_config_fallback_props(struct ibmca_prov_ctx *provctx, const char *key, const char *value); static int ibmca_config_module_filename(struct ibmca_prov_ctx *provctx, const char *key, const char *value); static int ibmca_config_openssl_version(struct ibmca_prov_ctx *provctx, const char *key, const char *value); static const struct ibmca_config_item config_items[] = { { IBMCA_CONF_DEBUG_PATH, ibmca_config_debug_path }, { IBMCA_CONF_DEBUG, ibmca_config_debug }, { IBMCA_CONF_FIPS, ibmca_config_fips }, { IBMCA_CONF_ALGORITHMS, ibmca_config_algorithms }, { IBMCA_CONF_FALLBACK_PROPS, ibmca_config_fallback_props }, { OSSL_PROV_PARAM_CORE_MODULE_FILENAME, ibmca_config_module_filename }, { OSSL_PROV_PARAM_CORE_VERSION, ibmca_config_openssl_version }, }; #define NUM_CONFIG_ITEMS \ (sizeof(config_items) / sizeof(struct ibmca_config_item)) struct ibmca_mech_algorithm { int operation; const OSSL_ALGORITHM *algorithms; }; struct ibmca_ica_mech_info { const char *algo; const unsigned int *ica_mechs; const struct ibmca_mech_algorithm *algos; const struct ibmca_mech_capability *capabilities; }; static const unsigned int ica_rsa_mech[] = { RSA_ME, RSA_CRT, /* RSA_KEY_GEN_CRT is always supported, but only in SW */ 0 }; static const struct ibmca_mech_algorithm ibmca_rsa_algorithms[] = { { OSSL_OP_KEYMGMT, ibmca_rsa_keymgmt }, { OSSL_OP_ASYM_CIPHER, ibmca_rsa_asym_cipher }, { OSSL_OP_SIGNATURE, ibmca_rsa_signature }, { 0, NULL } }; static const unsigned int ica_ec_mech[] = { EC_DH, EC_DSA_SIGN, EC_DSA_VERIFY, EC_KGEN, 0 }; static const struct ibmca_mech_algorithm ibmca_ec_algorithms[] = { { OSSL_OP_KEYMGMT, ibmca_ec_keymgmt }, { OSSL_OP_SIGNATURE, ibmca_ec_signature }, { OSSL_OP_KEYEXCH, ibmca_ec_keyexch }, { 0, NULL } }; static const struct ibmca_mech_algorithm ibmca_dh_algorithms[] = { { OSSL_OP_KEYMGMT, ibmca_dh_keymgmt }, { OSSL_OP_KEYEXCH, ibmca_dh_keyexch }, { 0, NULL } }; static const unsigned int ica_dh_mech[] = { RSA_ME, /* DH uses RSA mod-expo for derive */ 0 }; static const struct ibmca_ica_mech_info ica_mech_infos[] = { { IBMCA_CONFIG_ALGO_RSA, ica_rsa_mech, ibmca_rsa_algorithms, NULL }, { IBMCA_CONFIG_ALGO_EC, ica_ec_mech, ibmca_ec_algorithms, ibmca_ec_capabilities }, { IBMCA_CONFIG_ALGO_DH, ica_dh_mech, ibmca_dh_algorithms, ibmca_dh_capabilities }, { NULL, NULL, NULL, NULL } }; static const OSSL_ITEM ibmca_reason_strings[] = { { IBMCA_ERR_INTERNAL_ERROR, "Internal error" }, { IBMCA_ERR_MALLOC_FAILED, "Memory allocation failed" }, { IBMCA_ERR_INVALID_PARAM, "Invalid parameter encountered" }, { IBMCA_ERR_CONFIGURATION, "Provider configuration error" }, { IBMCA_ERR_LIBICA_FAILED, "A libica function returned an error" }, { IBMCA_ERR_SIGNATURE_BAD, "Signature bad" }, { IBMCA_ERR_EC_CURVE_NOT_SUPPORTED, "EC curve not supported" }, { 0, NULL } }; void ibmca_debug_print(struct ibmca_prov_ctx *provctx, const char *func, const char *fmt, ...) { char tmp_fmt[500]; char time_buf[200] = ""; va_list ap; time_t t; struct tm *tm; pid_t old_pid; t = time(NULL); tm = localtime(&t); if (strftime(time_buf, sizeof(time_buf), "%m/%d/%Y %H:%M:%S", tm) == 0) return; if (snprintf(tmp_fmt, sizeof(tmp_fmt), "DBG: %s %u %s: %s", time_buf, (unsigned int)gettid(), func, fmt) > (int)sizeof(tmp_fmt)) return; (void)pthread_mutex_lock(&provctx->debug_mutex); /* no error checking here: if lock fails print trace msg anyway */ if (provctx->debug_file != NULL && getpid() != provctx->debug_pid) { /* process was forked off from parent process: open new trace file */ old_pid = provctx->debug_pid; fclose(provctx->debug_file); provctx->debug_file = NULL; /* avoid recursive call from ibmca_config_debug/ibmca_config_bool */ provctx->debug = false; if (ibmca_config_debug(provctx, IBMCA_CONF_DEBUG, "on") == 0) goto out; fprintf(provctx->debug_file, "*** Forked off from parent process %u ***\n", old_pid); } va_start(ap, fmt); if (provctx->debug_file != NULL) { vfprintf(provctx->debug_file, tmp_fmt, ap); fputc('\n', provctx->debug_file); fflush(provctx->debug_file); } else { vwarnx(tmp_fmt, ap); } va_end(ap); out: pthread_mutex_unlock(&provctx->debug_mutex); } void ibmca_put_error(const struct ibmca_prov_ctx *provctx, int err, const char *file, int line, const char *func, char *fmt, ...) { va_list ap; if (provctx == NULL) return; va_start(ap, fmt); provctx->c_new_error(provctx->handle); provctx->c_set_error_debug(provctx->handle, file, line, func); provctx->c_vset_error(provctx->handle, err, fmt, ap); va_end(ap); } char *ibmca_strdup(const struct ibmca_prov_ctx *provctx, const char *str, const char* file, int line) { char *ret; if (str == NULL || provctx == NULL) return NULL; ret = provctx->c_malloc(strlen(str) + 1, file, line); if (ret != NULL) strcpy(ret, str); return ret; } void *ibmca_memdup(const struct ibmca_prov_ctx *provctx, const void *data, size_t size, const char* file, int line) { void *ret; if (data == NULL || size >= INT_MAX) return NULL; ret = provctx->c_malloc(size, file, line); if (ret != NULL) memcpy(ret, data, size); return ret; } void *ibmca_secure_memdup(const struct ibmca_prov_ctx *provctx, const void *data, size_t size, const char* file, int line) { void *ret; if (data == NULL || size >= INT_MAX) return NULL; ret = provctx->c_secure_malloc(size, file, line); if (ret != NULL) memcpy(ret, data, size); return ret; } int ibmca_param_build_set_bn(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, const BIGNUM *bn) { char *str; if (bn == NULL) return 0; if (bld != NULL) { if (OSSL_PARAM_BLD_push_BN(bld, key, bn) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } goto out; } p = OSSL_PARAM_locate(p, key); if (p == NULL) return 1; if (OSSL_PARAM_set_BN(p, bn) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } out: if (provctx->debug) { if (BN_get_flags(bn, BN_FLG_SECURE)) { ibmca_debug_ctx(provctx, "param '%s': [sensitive value omitted] (%d bits)", key, BN_num_bits(bn)); } else { str = BN_bn2hex(bn); ibmca_debug_ctx(provctx, "param '%s': 0x%s (%d bits)", key, str, BN_num_bits(bn)); P_FREE(provctx, str); } } return 1; } int ibmca_param_build_set_int(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, int val) { if (bld != NULL) { if (OSSL_PARAM_BLD_push_int(bld, key, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } goto out; } p = OSSL_PARAM_locate(p, key); if (p == NULL) return 1; if (OSSL_PARAM_set_int(p, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } out: ibmca_debug_ctx(provctx, "param '%s': %d", key, val); return 1; } int ibmca_param_build_set_uint(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, unsigned int val) { if (bld != NULL) { if (OSSL_PARAM_BLD_push_uint(bld, key, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } goto out; } p = OSSL_PARAM_locate(p, key); if (p == NULL) return 1; if (OSSL_PARAM_set_uint(p, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } out: ibmca_debug_ctx(provctx, "param '%s': %u", key, val); return 1; } int ibmca_param_build_set_utf8(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, const char *str) { if (str == NULL) return 0; if (bld != NULL) { if (OSSL_PARAM_BLD_push_utf8_string(bld, key, str, 0) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } goto out; } p = OSSL_PARAM_locate(p, key); if (p == NULL) return 1; if (OSSL_PARAM_set_utf8_string(p, str) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } out: ibmca_debug_ctx(provctx, "param '%s': '%s'", key, str); return 1; } int ibmca_param_build_set_octet_ptr(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, const void *val, size_t len) { if (val == NULL) return 0; if (bld != NULL) { if (OSSL_PARAM_BLD_push_octet_string(bld, key, val, len) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } goto out; } p = OSSL_PARAM_locate(p, key); if (p == NULL) return 1; if (OSSL_PARAM_set_octet_string(p, val, len) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } out: ibmca_debug_ctx(provctx, "param '%s': [octet string] (%lu bytes)", key, len); return 1; } int ibmca_param_build_set_size_t(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, size_t val) { if (bld != NULL) { if (OSSL_PARAM_BLD_push_size_t(bld, key, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } goto out; } p = OSSL_PARAM_locate(p, key); if (p == NULL) return 1; if (OSSL_PARAM_set_size_t(p, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", key); return 0; } out: ibmca_debug_ctx(provctx, "param '%s': %lu", key, val); return 1; } int ibmca_param_get_bn(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, BIGNUM **bn) { const OSSL_PARAM *p; if (bn == NULL) return 0; p = OSSL_PARAM_locate_const(params, key); if (p == NULL) return -1; if (OSSL_PARAM_get_BN(p, bn) == 0 || *bn == NULL) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Failed to get param '%s'", key); return 0; } if (provctx->debug) { if (BN_get_flags(*bn, BN_FLG_SECURE)) { ibmca_debug_ctx(provctx, "param '%s': [sensitive value omitted] (%d bits)", key, BN_num_bits(*bn)); } else { char *str = BN_bn2hex(*bn); ibmca_debug_ctx(provctx, "param '%s': 0x%s (%d bits)", key, str != NULL ? str : "", BN_num_bits(*bn)); P_FREE(provctx, str); } } return 1; } int ibmca_param_get_int(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, int *val) { const OSSL_PARAM *p; p = OSSL_PARAM_locate_const(params, key); if (p == NULL) return -1; if (OSSL_PARAM_get_int(p, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Failed to get param '%s'", key); return 0; } ibmca_debug_ctx(provctx, "param '%s': %d", key, *val); return 1; } int ibmca_param_get_uint(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, unsigned int *val) { const OSSL_PARAM *p; p = OSSL_PARAM_locate_const(params, key); if (p == NULL) return -1; if (OSSL_PARAM_get_uint(p, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Failed to get param '%s'", key); return 0; } ibmca_debug_ctx(provctx, "param '%s': %u", key, *val); return 1; } int ibmca_param_get_size_t(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, size_t *val) { const OSSL_PARAM *p; p = OSSL_PARAM_locate_const(params, key); if (p == NULL) return -1; if (OSSL_PARAM_get_size_t(p, val) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Failed to get param '%s'", key); return 0; } ibmca_debug_ctx(provctx, "param '%s': %lu", key, *val); return 1; } int ibmca_param_get_utf8(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, const char **str) { const OSSL_PARAM *p; p = OSSL_PARAM_locate_const(params, key); if (p == NULL) return -1; if (p->data_type == OSSL_PARAM_UTF8_STRING) { *str = p->data; } else if (OSSL_PARAM_get_utf8_ptr(p, str) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Failed to get param '%s'", key); return 0; } ibmca_debug_ctx(provctx, "param '%s': '%s'", key, *str); return 1; } int ibmca_param_get_octet_string(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, void **val, size_t *len) { const OSSL_PARAM *p; p = OSSL_PARAM_locate_const(params, key); if (p == NULL) return -1; if (OSSL_PARAM_get_octet_string(p, val, 0, len) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Failed to get param '%s'", key); return 0; } ibmca_debug_ctx(provctx, "param '%s': [octet string] (%lu bytes)", key, *len); return 1; } static void ibmca_teardown(void *vprovctx) { struct ibmca_prov_ctx *provctx = vprovctx; int i; if (provctx == NULL) return; ibmca_debug_ctx(provctx, "provctx: %p", provctx); if (provctx->ica_adapter > DRIVER_NOT_LOADED) ica_close_adapter(provctx->ica_adapter); for (i = 0; i < OSSL_OP__HIGHEST; i++) { if (provctx->algorithms[i] != NULL) P_FREE(provctx, provctx->algorithms[i]); } if (provctx->algo_enabled != NULL) P_FREE(provctx, provctx->algo_enabled); if (provctx->property_def != NULL) P_FREE(provctx, provctx->property_def); if (provctx->fallback_property_query != NULL && provctx->fallback_property_query != provctx->fallback_props_conf) P_FREE(provctx, provctx->fallback_property_query); if (provctx->libctx != NULL) OSSL_LIB_CTX_free(provctx->libctx); if (provctx->debug_file != NULL) fclose(provctx->debug_file); pthread_mutex_destroy(&provctx->debug_mutex); P_FREE(provctx, provctx); #if HAVE_DECL_ICA_CLEANUP == 1 ica_cleanup(); #endif } static const OSSL_PARAM ibmca_param_types[] = { OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0), OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0), OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0), OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_gettable_params(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); return ibmca_param_types; } static int ibmca_get_params(void *vprovctx, OSSL_PARAM params[]) { const struct ibmca_prov_ctx *provctx = vprovctx; OSSL_PARAM *p; if (provctx == NULL) return 0; ibmca_debug_ctx(provctx, "provctx: %p", provctx); p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME); if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, provctx->name)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "OSSL_PARAM_set_utf8_ptr failed"); return 0; } p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION); if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, IBMCA_VERSION)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "OSSL_PARAM_set_utf8_ptr failed"); return 0; } p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO); if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, IBMCA_VERSION)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "OSSL_PARAM_set_utf8_ptr failed"); return 0; } p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS); if (p != NULL && !OSSL_PARAM_set_int(p, 1)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "OSSL_PARAM_set_int failed"); return 0; } return 1; } static const OSSL_ALGORITHM *ibmca_query(void *vprovctx, int operation_id, int *no_cache) { const struct ibmca_prov_ctx *provctx = vprovctx; if (provctx == NULL) return NULL; *no_cache = 0; ibmca_debug_ctx(provctx, "provctx: %p operation_id: %d", provctx, operation_id); if (operation_id < 0 || operation_id > OSSL_OP__HIGHEST) return NULL; ibmca_debug_ctx(provctx, "algorithms: %p", provctx->algorithms[operation_id]); return provctx->algorithms[operation_id]; } static const OSSL_ITEM *ibmca_get_reason_strings(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; ibmca_debug_ctx(provctx, "provctx: %p", provctx); return ibmca_reason_strings; } static int ibmca_prov_get_capabilities(void *vprovctx, const char *capability, OSSL_CALLBACK *cb, void *arg) { const struct ibmca_prov_ctx *provctx = vprovctx; int i, k, rc = 0; const struct ibmca_mech_capability *cap; if (capability == NULL || cb == NULL) return 0; ibmca_debug_ctx(provctx, "provctx: %p capability: %s", provctx, capability); for (i = 0; ica_mech_infos[i].algo != NULL; i++) { for (cap = ica_mech_infos[i].capabilities; cap != NULL && cap->capability != NULL; cap++) { if (strcasecmp(capability, cap->capability) != 0) continue; ibmca_debug_ctx(provctx, "algorithm '%s' supports this capability", ica_mech_infos[i].algo); for (k = 0; cap->details[k] != NULL; k++) { rc = cb(cap->details[k], arg); if (rc == 0) break; } if (rc == 0) break; } } return rc; } static int ibmca_prov_self_tests(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; ibmca_debug_ctx(provctx, "provctx: %p", provctx); if (provctx->fips == 0) return 1; /* * libica performs FIPS self-tests if running in FIPS mode. If any of * the fips tests failed, additional flags are on. */ return (provctx->ica_fips_status == ICA_FIPS_MODE) ? 1 : 0; } static const OSSL_DISPATCH ibmca_dispatch_table[] = { { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))ibmca_teardown }, { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))ibmca_gettable_params }, { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))ibmca_get_params }, { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))ibmca_query }, { OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, (void (*)(void))ibmca_get_reason_strings }, { OSSL_FUNC_PROVIDER_GET_CAPABILITIES, (void (*)(void))ibmca_prov_get_capabilities }, { OSSL_FUNC_PROVIDER_SELF_TEST, (void (*)(void))ibmca_prov_self_tests }, { 0, NULL } }; static int ibmca_config_const_string(struct ibmca_prov_ctx *provctx, const char *key, const char *value, const char **string) { ibmca_debug_ctx(provctx, "provctx: %p key: '%s' value: '%s'", provctx, key, value); *string = value; return 1; } static int ibmca_config_module_filename(struct ibmca_prov_ctx *provctx, const char *key, const char *value) { return ibmca_config_const_string(provctx, key, value, &provctx->module_filename); } static int ibmca_config_openssl_version(struct ibmca_prov_ctx *provctx, const char *key, const char *value) { return ibmca_config_const_string(provctx, key, value, &provctx->openssl_version); } static int ibmca_config_fallback_props(struct ibmca_prov_ctx *provctx, const char *key, const char *value) { return ibmca_config_const_string(provctx, key, value, &provctx->fallback_props_conf); } static int ibmca_config_bool(struct ibmca_prov_ctx *provctx, const char *key, const char *value, bool *bval) { ibmca_debug_ctx(provctx, "provctx: %p key: '%s' value: '%s'", provctx, key, value); if (strcasecmp(value, "on") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "yes") == 0 || strcasecmp(value, "1") == 0) { *bval = true; } else if (strcasecmp(value, "off") == 0 || strcasecmp(value, "false") == 0 || strcasecmp(value, "no") == 0 || strcasecmp(value, "0") == 0) { *bval = false; } else { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Failed to parse config value: '%s' = '%s'", key, value); return 0; } return 1; } static int ibmca_config_debug(struct ibmca_prov_ctx *provctx, const char *key, const char *value) { char debug_file[PATH_MAX]; char prov_name[PATH_MAX]; char *p; /* * If debug is already on (e.g. due to IBMCA_DEBUG environment variable) * do not override the setting. */ if (provctx->debug == true) return 1; if (strcasecmp(value, "stderr") == 0) { provctx->debug = true; return 1; } if (ibmca_config_bool(provctx, key, value, &provctx->debug) == 0) return 0; if (provctx->debug == true) { provctx->debug_pid = getpid(); strncpy(prov_name, provctx->name, sizeof(prov_name)); prov_name[sizeof(prov_name) - 1] = '\0'; while ((p = strchr(prov_name, '/')) != NULL) *p = '_'; if (snprintf(debug_file, sizeof(debug_file), "%s/trace-%s.%d", provctx->debug_path != NULL ? provctx->debug_path : IBMCA_LOGDIR, prov_name, provctx->debug_pid) >= (int)sizeof(debug_file)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "IBMCA_LOGDIR too long: '%s'", IBMCA_LOGDIR); return 0; } provctx->debug_file = fopen(debug_file, "a"); if (provctx->debug_file == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to open trace file: '%s': %s - tracing to stderr instead", debug_file, strerror(errno)); return 1; } fprintf(provctx->debug_file, "*** Trace activated for IBMCA version %s ***\n", IBMCA_VERSION); } return 1; } static int ibmca_config_debug_path(struct ibmca_prov_ctx *provctx, const char *key, const char *value) { /* * If the debug path is already set (e.g. due to IBMCA_DEBUG_PATH * environment variable) do not override the setting. */ if (provctx->debug_path != NULL) return 1; return ibmca_config_const_string(provctx, key, value, &provctx->debug_path); } static int ibmca_config_fips(struct ibmca_prov_ctx *provctx, const char *key, const char *value) { if (ibmca_config_bool(provctx, key, value, &provctx->fips) == 0) return 0; provctx->fips_configured = true; return 1; } static int ibmca_config_algorithms(struct ibmca_prov_ctx *provctx, const char *key, const char *value) { char *val, *tok; int i, rc = 1; bool found; ibmca_debug_ctx(provctx, "provctx: %p key: '%s' value: '%s'", provctx, key, value); val = P_STRDUP(provctx, value); if (val == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to strdup config value"); return 0; } for (i = 0; ica_mech_infos[i].algo != NULL; i++) provctx->algo_enabled[i] = false; for (tok = strtok(val, ","); tok != NULL; tok = strtok(NULL, ",")) { ibmca_debug_ctx(provctx, "algorithm: '%s'", tok); if (strcasecmp(tok, IBMCA_CONFIG_ALGO_ALL) == 0) { for (i = 0; ica_mech_infos[i].algo != NULL; i++) provctx->algo_enabled[i] = true; continue; } for (i = 0, found = false; ica_mech_infos[i].algo != NULL; i++) { if (strcasecmp(tok, ica_mech_infos[i].algo) == 0) { provctx->algo_enabled[i] = true; found = true; break; } } if (found) continue; put_error_ctx(provctx, IBMCA_ERR_CONFIGURATION, "Unknown algorithm name '%s' in configuration for provider '%s'", tok, provctx->name); rc = 0; break; } P_FREE(provctx, val); return rc; } static int ibmca_get_configuration(struct ibmca_prov_ctx *provctx) { OSSL_PARAM params[NUM_CONFIG_ITEMS + 1]; char *param_ptrs[NUM_CONFIG_ITEMS]; const char *value; int i, num; ibmca_debug_ctx(provctx, "provctx: %p", provctx); for (num = 0; ica_mech_infos[num].algo != NULL; num++) ; provctx->algo_enabled = P_ZALLOC(provctx, num * sizeof(bool)); if (provctx->algo_enabled == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate memory for algorithm list"); return 0; } for (i = 0; ica_mech_infos[i].algo != NULL; i++) provctx->algo_enabled[i] = true; for (i = 0; i < (int)NUM_CONFIG_ITEMS; i++) params[i] = OSSL_PARAM_construct_utf8_ptr(config_items[i].key, ¶m_ptrs[i], sizeof(param_ptrs[i])); params[NUM_CONFIG_ITEMS] = OSSL_PARAM_construct_end(); if (provctx->c_get_params(provctx->handle, params) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to get configuration parameters for provider '%s'", provctx->name); return 0; } for (i = 0; i < (int)NUM_CONFIG_ITEMS; i++) { if (!OSSL_PARAM_modified(¶ms[i])) continue; if (OSSL_PARAM_get_utf8_ptr(¶ms[i], &value) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to get configuration parameter '%s' for provider '%s'", params[i].key, provctx->name); return 0; } if (config_items[i].func(provctx, params[i].key, value) != 1) return 0; } return 1; } static bool ibmca_libica_mechs_supported(const unsigned int *mechs, libica_func_list_element *mech_list, unsigned int mech_len) { unsigned int i, k; bool found; for (i = 0; mechs[i] != 0; i++) { for (k = 0, found = false; k < mech_len; k++) { if (mech_list[k].mech_mode_id != mechs[i]) continue; if (mech_list[k].flags & (ICA_FLAG_SW | ICA_FLAG_SHW | ICA_FLAG_DHW)) found = true; break; } if (!found) return false; } return true; } static int ibmca_libica_init(struct ibmca_prov_ctx *provctx) { unsigned int mech_len, i; libica_func_list_element *mech_list = NULL; int rc, ret = 1; ibmca_debug_ctx(provctx, "provctx: %p", provctx); ica_set_fallback_mode(0); provctx->ica_fips_status = ica_fips_status(); ibmca_debug_ctx(provctx, "ica_fips_status: %d", provctx->ica_fips_status); if (provctx->fips_configured == false) { /* FIPS not configured, auto-detect from libica */ provctx->fips = (provctx->ica_fips_status == ICA_FIPS_MODE); } else if (provctx->fips == true) { /* Ensure libica is also running in fips mode */ if (provctx->ica_fips_status != ICA_FIPS_MODE) { put_error_ctx(provctx, IBMCA_ERR_CONFIGURATION, "'fips=yes' is configured, but libica is not running in FIPS mode"); syslog(LOG_ERR, "IBMCA provider: 'fips=yes' is configured, but libica is not running in FIPS mode"); return 0; } } ibmca_debug_ctx(provctx, "fips: %d", provctx->fips); rc = ica_open_adapter(&provctx->ica_adapter); if (rc != 0) { put_error_ctx(provctx, IBMCA_ERR_LIBICA_FAILED, "ica_open_adapter failed: %s", strerror(rc)); syslog(LOG_ERR, "IBMCA provider: ica_open_adapter failed: %s", strerror(rc)); provctx->ica_adapter = DRIVER_NOT_LOADED; return 0; } ibmca_debug_ctx(provctx, "ica_adapter: %p", provctx->ica_adapter); rc = ica_get_functionlist(NULL, &mech_len); if (rc != 0) { put_error_ctx(provctx, IBMCA_ERR_LIBICA_FAILED, "ica_get_functionlist failed: %s", strerror(rc)); return 0; } ibmca_debug_ctx(provctx, "mech_len: %u", mech_len); mech_list = P_ZALLOC(provctx, sizeof(libica_func_list_element) * mech_len); if (mech_list == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate memory for mechanism list"); return 0; } rc = ica_get_functionlist(mech_list, &mech_len); if (rc != 0) { put_error_ctx(provctx, IBMCA_ERR_LIBICA_FAILED, "ica_get_functionlist failed: %s", strerror(rc)); ret = 0; goto done; } for (i = 0; ica_mech_infos[i].algo != NULL; i++) { if (!ibmca_libica_mechs_supported(ica_mech_infos[i].ica_mechs, mech_list, mech_len)) { ibmca_debug_ctx(provctx, "algo '%s' not supported by libica", ica_mech_infos[i].algo); provctx->algo_enabled[i] = false; } } done: P_FREE(provctx, mech_list); return ret; } static int ibmca_add_algorithm(struct ibmca_prov_ctx *provctx, int operation, const char *names, const OSSL_DISPATCH *implementation, const char *description) { unsigned int num; OSSL_ALGORITHM *alg, *new_algs; ibmca_debug_ctx(provctx, "provctx: %p operation: %d names: '%s'", provctx, operation, names); for (alg = provctx->algorithms[operation], num = 0; alg != NULL && alg->algorithm_names != NULL; alg++, num++) ; new_algs = P_REALLOC(provctx, provctx->algorithms[operation], (num + 2) * sizeof(OSSL_ALGORITHM)); if (new_algs == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate memory for algorithm array"); return 0; } new_algs[num].algorithm_names = names; new_algs[num].property_definition = provctx->property_def; new_algs[num].implementation = implementation; new_algs[num].algorithm_description = description; memset(&new_algs[num + 1], 0, sizeof(OSSL_ALGORITHM)); provctx->algorithms[operation] = new_algs; return 1; } static int ibmca_setup_algorithms(struct ibmca_prov_ctx *provctx) { unsigned int i; size_t len; const struct ibmca_mech_algorithm *alg; const OSSL_ALGORITHM *ossl_alg; ibmca_debug_ctx(provctx, "provctx: %p", provctx); len = strlen("provider=") + strlen(provctx->name) + 1; if (provctx->fips) len += strlen(",fips=yes"); provctx->property_def = P_ZALLOC(provctx, len); if (provctx->property_def == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate memory for property definition"); return 0; } sprintf(provctx->property_def, "provider=%s%s", provctx->name, provctx->fips ? ",fips=yes" : ""); ibmca_debug_ctx(provctx, "property_def: '%s'", provctx->property_def); if (provctx->fallback_props_conf != NULL) { provctx->fallback_property_query = (char *)provctx->fallback_props_conf; } else { /* * Build a property query string for fall-back operations that excludes * the IBMCA provider, since this would produce an endless loop. */ len = strlen("provider!=") + strlen(provctx->name) + 1; if (provctx->fips) len += strlen(",fips=yes"); provctx->fallback_property_query = P_ZALLOC(provctx, len); if (provctx->fallback_property_query == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate property fallback query string"); return 0; } sprintf(provctx->fallback_property_query, "provider!=%s%s", provctx->name, provctx->fips ? ",fips=yes" : ""); } ibmca_debug_ctx(provctx, "fallback_property_query: '%s'", provctx->fallback_property_query); for (i = 0; ica_mech_infos[i].algo != NULL; i++) { ibmca_debug_ctx(provctx, "algorithm '%s' enabled: %d", ica_mech_infos[i].algo, provctx->algo_enabled[i]); if (provctx->algo_enabled[i] == false) continue; for (alg = ica_mech_infos[i].algos; alg->operation != 0; alg++) { for (ossl_alg = alg->algorithms; ossl_alg != NULL && ossl_alg->algorithm_names != NULL; ossl_alg++) { if (ibmca_add_algorithm(provctx, alg->operation, ossl_alg->algorithm_names, ossl_alg->implementation, ossl_alg->algorithm_description) != 1) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to algorithm '%s' for operation %d", ossl_alg->algorithm_names, alg->operation); return 0; } } } } return 1; } int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in, const OSSL_DISPATCH **out, void **provctx) { const OSSL_DISPATCH *dptc; OSSL_FUNC_CRYPTO_zalloc_fn *c_zalloc = NULL; OSSL_FUNC_CRYPTO_free_fn *c_free = NULL; OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug = NULL; OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL; OSSL_FUNC_core_vset_error_fn *c_vset_error = NULL; OSSL_FUNC_core_new_error_fn *c_new_error = NULL; OSSL_FUNC_provider_name_fn *c_provider_name = NULL; struct ibmca_prov_ctx *ctx; char *val; *provctx = NULL; if (handle == NULL || in == NULL || out == NULL || provctx == NULL) return 0; for (dptc = in; dptc->function_id != 0; dptc++) { switch (dptc->function_id) { case OSSL_FUNC_CORE_GET_LIBCTX: c_get_libctx = OSSL_FUNC_core_get_libctx(dptc); break; case OSSL_FUNC_CORE_NEW_ERROR: c_new_error = OSSL_FUNC_core_new_error(dptc); break; case OSSL_FUNC_CORE_SET_ERROR_DEBUG: c_set_error_debug = OSSL_FUNC_core_set_error_debug(dptc); break; case OSSL_FUNC_CORE_VSET_ERROR: c_vset_error = OSSL_FUNC_core_vset_error(dptc); break; case OSSL_FUNC_CRYPTO_ZALLOC: c_zalloc = OSSL_FUNC_CRYPTO_zalloc(dptc); break; case OSSL_FUNC_CRYPTO_FREE: c_free = OSSL_FUNC_CRYPTO_free(dptc); break; case OSSL_FUNC_PROVIDER_NAME: c_provider_name = OSSL_FUNC_provider_name(dptc); break; default: /* Just ignore anything we don't understand for now */ break; } } if (c_get_libctx == NULL || c_zalloc == NULL || c_free == NULL || c_new_error == NULL || c_set_error_debug == NULL || c_vset_error == NULL || c_provider_name == NULL) return 0; ctx = c_zalloc(sizeof(struct ibmca_prov_ctx), __FILE__, __LINE__); if (ctx == NULL) { c_new_error(handle); c_set_error_debug(handle, __FILE__, __LINE__, __func__); c_vset_error(handle, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate provider context", NULL); return 0; } ctx->handle = handle; ctx->name = c_provider_name(handle); ctx->c_get_libctx = c_get_libctx; ctx->c_new_error = c_new_error; ctx->c_set_error_debug = c_set_error_debug; ctx->c_vset_error = c_vset_error; ctx->c_zalloc = c_zalloc; ctx->c_free = c_free; ctx->ica_adapter = DRIVER_NOT_LOADED; val = secure_getenv(IBMCA_DEBUG_PATH_ENVVAR); if (val != NULL) ibmca_config_debug_path(ctx, IBMCA_CONF_DEBUG_PATH, val); val = getenv(IBMCA_DEBUG_ENVVAR); if (val != NULL) ibmca_config_debug(ctx, IBMCA_CONF_DEBUG, val); if (pthread_mutex_init(&ctx->debug_mutex, NULL) != 0) { put_error_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "pthread_mutex_init failed for provider '%s': %s", ctx->name, strerror(errno)); c_free(ctx, __FILE__, __LINE__); return 0; } ctx->libctx = OSSL_LIB_CTX_new_child(handle, in); if (ctx->libctx == NULL) { put_error_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "OSSL_LIB_CTX_new_child failed for provider '%s'", ctx->name); ibmca_teardown(ctx); return 0; } for (dptc = in; dptc->function_id != 0; dptc++) { switch (dptc->function_id) { case OSSL_FUNC_CORE_GETTABLE_PARAMS: ctx->c_gettable_params = OSSL_FUNC_core_gettable_params(dptc); break; case OSSL_FUNC_CORE_GET_PARAMS: ctx->c_get_params = OSSL_FUNC_core_get_params(dptc); break; case OSSL_FUNC_CRYPTO_MALLOC: ctx->c_malloc = OSSL_FUNC_CRYPTO_malloc(dptc); break; case OSSL_FUNC_CRYPTO_REALLOC: ctx->c_realloc = OSSL_FUNC_CRYPTO_realloc(dptc); break; case OSSL_FUNC_CRYPTO_CLEAR_FREE: ctx->c_clear_free = OSSL_FUNC_CRYPTO_clear_free(dptc); break; case OSSL_FUNC_CRYPTO_SECURE_MALLOC: ctx->c_secure_malloc = OSSL_FUNC_CRYPTO_secure_malloc(dptc); break; case OSSL_FUNC_CRYPTO_SECURE_ZALLOC: ctx->c_secure_zalloc = OSSL_FUNC_CRYPTO_secure_zalloc(dptc); break; case OSSL_FUNC_CRYPTO_SECURE_FREE: ctx->c_secure_free = OSSL_FUNC_CRYPTO_secure_free(dptc); break; case OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE: ctx->c_secure_clear_free = OSSL_FUNC_CRYPTO_secure_clear_free(dptc); break; case OSSL_FUNC_OPENSSL_CLEANSE: ctx->c_cleanse = OSSL_FUNC_OPENSSL_cleanse(dptc); break; default: /* Just ignore anything we don't understand */ break; } } if (ctx->c_gettable_params == NULL || ctx->c_get_params == NULL || ctx->c_malloc == NULL || ctx->c_realloc == NULL || ctx->c_clear_free == NULL || ctx->c_secure_malloc == NULL || ctx->c_secure_zalloc == NULL || ctx->c_secure_free == NULL || ctx->c_secure_clear_free == NULL || ctx->c_cleanse == NULL) { put_error_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Not all required core functions are available for provider '%s'", ctx->name); ibmca_teardown(ctx); return 0; } if (ibmca_get_configuration(ctx) != 1) { ibmca_teardown(ctx); return 0; } if (ibmca_libica_init(ctx) != 1) { ibmca_teardown(ctx); return 0; } ibmca_debug_ctx(ctx, "provctx: %p name: '%s'", ctx, ctx->name); if (ibmca_setup_algorithms(ctx) != 1) { ibmca_teardown(ctx); return 0; } *provctx = ctx; *out = ibmca_dispatch_table; return 1; } openssl-ibmca-2.4.1/src/provider/p_ibmca.h000066400000000000000000000610001450276407300204430ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 /* Environment variable name to enable debug */ #define IBMCA_DEBUG_ENVVAR "IBMCA_DEBUG" #define IBMCA_DEBUG_PATH_ENVVAR "IBMCA_DEBUG_PATH" /* IBMCA provider configuration key words */ #define IBMCA_CONF_DEBUG "debug" #define IBMCA_CONF_DEBUG_PATH "debug-path" #define IBMCA_CONF_ALGORITHMS "algorithms" #define IBMCA_CONF_FIPS "fips" #define IBMCA_CONF_FALLBACK_PROPS "fallback-properties" /* IBMCA provider configuration key words for algorithms */ #define IBMCA_CONFIG_ALGO_ALL "ALL" #define IBMCA_CONFIG_ALGO_RSA "RSA" #define IBMCA_CONFIG_ALGO_EC "EC" #define IBMCA_CONFIG_ALGO_DH "DH" /* IBMCA provider context */ struct ibmca_prov_ctx { const OSSL_CORE_HANDLE *handle; OSSL_LIB_CTX *libctx; const char *name; const char *openssl_version; const char *module_filename; OSSL_FUNC_core_get_libctx_fn *c_get_libctx; OSSL_FUNC_core_new_error_fn *c_new_error; OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug; OSSL_FUNC_core_vset_error_fn *c_vset_error; OSSL_FUNC_core_gettable_params_fn *c_gettable_params; OSSL_FUNC_core_get_params_fn *c_get_params; OSSL_FUNC_CRYPTO_zalloc_fn *c_zalloc; OSSL_FUNC_CRYPTO_malloc_fn *c_malloc; OSSL_FUNC_CRYPTO_realloc_fn *c_realloc; OSSL_FUNC_CRYPTO_free_fn *c_free; OSSL_FUNC_CRYPTO_clear_free_fn *c_clear_free; OSSL_FUNC_CRYPTO_secure_malloc_fn *c_secure_malloc; OSSL_FUNC_CRYPTO_secure_zalloc_fn *c_secure_zalloc; OSSL_FUNC_CRYPTO_secure_free_fn *c_secure_free; OSSL_FUNC_CRYPTO_secure_clear_free_fn *c_secure_clear_free; OSSL_FUNC_OPENSSL_cleanse_fn *c_cleanse; bool debug; const char *debug_path; FILE *debug_file; pid_t debug_pid; pthread_mutex_t debug_mutex; bool fips; bool fips_configured; bool *algo_enabled; char *property_def; const char *fallback_props_conf; char *fallback_property_query; ica_adapter_handle_t ica_adapter; int ica_fips_status; OSSL_ALGORITHM *algorithms[OSSL_OP__HIGHEST + 1]; }; /* IBMCA provider key */ struct ibmca_pss_params { int digest_nid; int mgf_nid; int mgf_digest_nid; int saltlen; bool restricted; }; struct ibmca_ffc_params { int group_nid; BIGNUM *p; BIGNUM *q; BIGNUM *g; /* DHX only */ BIGNUM *cofactor; /* DHX only */ int length; unsigned char *seed; size_t seed_len; int gindex; int pcounter; int hindex; unsigned int validate_pq : 1; unsigned int validate_g : 1; unsigned int validate_legacy : 1; const char *mdname; const char *mdprops; }; struct ibmca_key { const struct ibmca_prov_ctx *provctx; unsigned int ref_count; int type; /* EVP_PKEY_xxx types */ void (*free_cb)(struct ibmca_key *key); int (*dup_cb)(const struct ibmca_key *key, struct ibmca_key *new_key); size_t (*get_max_param_size)(const struct ibmca_key *key); OSSL_FUNC_keymgmt_export_fn *export; OSSL_FUNC_keymgmt_import_fn *import; OSSL_FUNC_keymgmt_has_fn *has; OSSL_FUNC_keymgmt_match_fn *match; const char *algorithm; EVP_PKEY *fallback_pkey_cache; pthread_rwlock_t fallback_pkey_cache_lock; union { struct { size_t bits; size_t keylength; ica_rsa_key_crt_t private_crt; ica_rsa_key_mod_expo_t private_me; ica_rsa_key_mod_expo_t public; struct ibmca_pss_params pss; /* For type EVP_PKEY_RSA_PSS only */ BN_BLINDING *blinding; BN_BLINDING *mt_blinding; pthread_rwlock_t blinding_lock; BN_MONT_CTX *blinding_mont_ctx; BN_ULONG blinding_mont_ctx_n0; } rsa; /* For type EVP_PKEY_RSA and EVP_PKEY_RSA_PSS */ struct { int curve_nid; point_conversion_form_t format; bool include_pub; size_t prime_size; ICA_EC_KEY *key; struct { BIGNUM *x; BIGNUM *y; BIGNUM *d; } fallback; } ec; /* For type EVP_PKEY_EC */ struct { BIGNUM *pub; BIGNUM *priv; struct ibmca_ffc_params ffc_params; } dh; /* For type EVP_PKEY_DH and EVP_PKEY_DHX */ }; }; void ibmca_keymgmt_upref(struct ibmca_key *key); unsigned int ibmca_keymgmt_downref(struct ibmca_key *key); struct ibmca_key *ibmca_keymgmt_new(const struct ibmca_prov_ctx *provctx, int type, const char *algorithm, void (*free_cb)(struct ibmca_key *key), int (*dup_cb)(const struct ibmca_key *key, struct ibmca_key *new_key), size_t (*get_max_param_size)( const struct ibmca_key *key), OSSL_FUNC_keymgmt_export_fn *export, OSSL_FUNC_keymgmt_import_fn *import, OSSL_FUNC_keymgmt_has_fn *has, OSSL_FUNC_keymgmt_match_fn *match); int ibmca_keymgmt_match(const struct ibmca_key *key1, const struct ibmca_key *key2); struct ibmca_op_ctx *ibmca_keymgmt_gen_init( const struct ibmca_prov_ctx *provctx, int type, void (*free_cb) (struct ibmca_op_ctx *ctx), int (*dup_cb) (const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx)); bool ibmca_keymgmt_rsa_pub_valid(const ica_rsa_key_mod_expo_t *public); bool ibmca_keymgmt_rsa_priv_crt_valid(const ica_rsa_key_crt_t *private_crt); bool ibmca_keymgmt_rsa_priv_me_valid(const ica_rsa_key_mod_expo_t *private_me); OSSL_FUNC_keymgmt_free_fn ibmca_keymgmt_free; OSSL_FUNC_keymgmt_dup_fn ibmca_keymgmt_dup; OSSL_FUNC_keymgmt_gen_cleanup_fn ibmca_keymgmt_gen_cleanup; OSSL_FUNC_keymgmt_load_fn ibmca_keymgmt_load; /* IBMCA provider operation context */ struct ibmca_op_ctx { const struct ibmca_prov_ctx *provctx; int type; /* EVP_PKEY_xxx types */ const char *propq; struct ibmca_key *key; int operation; void (*free_cb)(struct ibmca_op_ctx *ctx); int (*dup_cb)(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx); unsigned char *tbuf; size_t tbuf_len; union { union { struct { size_t bits; BIGNUM *pub_exp; struct ibmca_pss_params pss; /* For EVP_PKEY_RSA_PSS only */ } gen; /* For operation EVP_PKEY_OP_KEYGEN */ struct { int pad_mode; EVP_MD *mgf1_md; EVP_MD *oaep_md; unsigned char *oaep_label; size_t oaep_labellen; unsigned int tls_clnt_version; unsigned int tls_alt_version; unsigned int implicit_rejection; } cipher; /* For operation EVP_PKEY_OP_ENCRYPT/DECRYPT */ struct { int pad_mode; EVP_MD *md; bool set_md_allowed; EVP_MD *mgf1_md; int saltlen; struct ibmca_pss_params pss; EVP_MD_CTX *md_ctx; } signature; /* For operation EVP_PKEY_OP_SIGN/VERIFY */ } rsa; /* For type EVP_PKEY_RSA and EVP_PKEY_RSA_PSS */ union { struct { int selection; int curve_nid; point_conversion_form_t format; } gen; /* For operation EVP_PKEY_OP_KEYGEN */ struct { EVP_MD *md; bool set_md_allowed; size_t md_size; EVP_MD_CTX *md_ctx; } signature; /* For operation EVP_PKEY_OP_SIGN/VERIFY */ struct { struct ibmca_key *peer_key; int kdf_type; /* EVP_PKEY_ECDH_KDF_xxx */ EVP_MD *kdf_md; size_t kdf_outlen; unsigned char *kdf_ukm; size_t kdf_ukmlen; } derive;/* For operation EVP_PKEY_OP_DERIVE */ } ec; /* For type EVP_PKEY_EC */ union { struct { EVP_PKEY_CTX *pctx; int selection; int priv_len; } gen; /* For operation EVP_PKEY_OP_KEYGEN */ struct { struct ibmca_key *peer_key; bool pad; int kdf_type; /* EVP_PKEY_DH_KDF_xxx */ EVP_MD *kdf_md; size_t kdf_outlen; unsigned char *kdf_ukm; size_t kdf_ukmlen; char *kdf_cekalg; } derive;/* For operation EVP_PKEY_OP_DERIVE */ } dh; /* For type EVP_PKEY_DH and EVP_PKEY_DHX */ }; }; struct ibmca_op_ctx *ibmca_op_newctx(const struct ibmca_prov_ctx *provctx, const char *propq, int type, void (*free_cb)(struct ibmca_op_ctx *ctx), int (*dup_cb) (const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx)); int ibmca_op_init(struct ibmca_op_ctx *ctx, struct ibmca_key *key, int operation); int ibmca_op_alloc_tbuf(struct ibmca_op_ctx *ctx, size_t tbuf_len); int ibmca_digest_signverify_update(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, const unsigned char *data, size_t datalen); int ibmca_digest_sign_final(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, OSSL_FUNC_signature_sign_fn *sign_func, unsigned char *sig, size_t *siglen, size_t sigsize); int ibmca_digest_verify_final(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, OSSL_FUNC_signature_verify_fn *verify_func, const unsigned char *sig, size_t siglen); int ibmca_get_ctx_md_params(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, OSSL_PARAM *params); int ibmca_set_ctx_md_params(struct ibmca_op_ctx *ctx, EVP_MD_CTX *md_ctx, const OSSL_PARAM params[]); const OSSL_PARAM *ibmca_gettable_ctx_md_params(const struct ibmca_op_ctx *ctx, const EVP_MD *md); const OSSL_PARAM *ibmca_settable_ctx_md_params(const struct ibmca_op_ctx *ctx, const EVP_MD *md); OSSL_FUNC_asym_cipher_freectx_fn ibmca_op_freectx; OSSL_FUNC_asym_cipher_dupctx_fn ibmca_op_dupctx; /* Macros for calling core functions */ #define P_ZALLOC(prov_ctx, size) \ (prov_ctx)->c_zalloc((size), __FILE__ , __LINE__) #define P_MALLOC(prov_ctx, size) \ (prov_ctx)->c_malloc((size), __FILE__ , __LINE__) #define P_REALLOC(prov_ctx, ptr, size) \ (prov_ctx)->c_realloc((ptr), (size), __FILE__ , __LINE__) #define P_FREE(prov_ctx, ptr) \ (prov_ctx)->c_free((ptr), __FILE__ , __LINE__) #define P_CLEAR_FREE(prov_ctx, ptr, size) \ (prov_ctx)->c_clear_free((ptr), (size), __FILE__ , __LINE__) #define P_SECURE_MALLOC(prov_ctx, size) \ (prov_ctx)->c_secure_malloc((size), __FILE__ , __LINE__) #define P_SECURE_ZALLOC(prov_ctx, size) \ (prov_ctx)->c_secure_zalloc((size), __FILE__ , __LINE__) #define P_SECURE_FREE(prov_ctx, ptr) \ (prov_ctx)->c_secure_free((ptr), __FILE__ , __LINE__) #define P_SECURE_CLEAR_FREE(prov_ctx, ptr, size) \ (prov_ctx)->c_secure_clear_free((ptr), (size), __FILE__ , __LINE__) #define P_CLEANSE(prov_ctx, ptr, size) \ (prov_ctx)->c_cleanse((ptr), (size)) #define P_STRDUP(prov_ctx, str) \ ibmca_strdup((prov_ctx), (str), __FILE__ , __LINE__) #define P_MEMDUP(prov_ctx, data, size) \ ibmca_memdup((prov_ctx), (data), (size), __FILE__ , __LINE__) #define P_SECURE_MEMDUP(prov_ctx, data, size) \ ibmca_secure_memdup((prov_ctx), (data), (size), __FILE__ , __LINE__) char *ibmca_strdup(const struct ibmca_prov_ctx *provctx, const char *str, const char* file, int line); void *ibmca_memdup(const struct ibmca_prov_ctx *provctx, const void *data, size_t size, const char* file, int line); void *ibmca_secure_memdup(const struct ibmca_prov_ctx *provctx, const void *data, size_t size, const char* file, int line); EVP_PKEY_CTX *ibmca_new_fallback_pkey_ctx(const struct ibmca_prov_ctx *provctx, EVP_PKEY *pkey, const char *algorithm); EVP_PKEY *ibmca_new_fallback_pkey(struct ibmca_key *key); void ibmca_clean_fallback_pkey_cache(struct ibmca_key *key); int ibmca_import_from_fallback_pkey(struct ibmca_key *key, const EVP_PKEY *pkey, int selection); int ibmca_check_fallback_provider(const struct ibmca_prov_ctx *provctx, EVP_PKEY_CTX *pctx); struct ibmca_keygen_cb_data { OSSL_CALLBACK *osslcb; void *cbarg; }; int ibmca_keygen_cb(EVP_PKEY_CTX *ctx); int ibmca_param_build_set_bn(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, const BIGNUM *bn); int ibmca_param_build_set_int(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, int val); int ibmca_param_build_set_uint(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, unsigned int val); int ibmca_param_build_set_utf8(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, const char *str); int ibmca_param_build_set_octet_ptr(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, const void *val, size_t len); int ibmca_param_build_set_size_t(const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key, size_t val); int ibmca_param_get_bn(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, BIGNUM **bn); int ibmca_param_get_int(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, int *val); int ibmca_param_get_uint(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, unsigned int *val); int ibmca_param_get_size_t(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, size_t *val); int ibmca_param_get_utf8(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, const char **str); int ibmca_param_get_octet_string(const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], const char *key, void **val, size_t *len); /* Debug and error handling functions and macros */ void ibmca_debug_print(struct ibmca_prov_ctx *provctx, const char *func, const char *fmt, ...); #define ibmca_debug(ctx, fmt...) \ do { \ if ((ctx)->debug) \ ibmca_debug_print((struct ibmca_prov_ctx*)(ctx), \ __func__, fmt); \ } while (0) #define ibmca_debug_ctx(ctx, fmt...) ibmca_debug((ctx), fmt) #define ibmca_debug_key(key, fmt...) ibmca_debug((key)->provctx, fmt) #define ibmca_debug_op_ctx(ctx, fmt...) ibmca_debug((ctx)->provctx, fmt) void ibmca_put_error(const struct ibmca_prov_ctx *provctx, int err, const char *file, int line, const char *func, char *fmt, ...); #define put_error_ctx(ctx, err, fmt...) \ do { \ ibmca_debug_ctx((ctx), "ERROR: "fmt); \ ibmca_put_error((ctx), (err), __FILE__, \ __LINE__, __func__, fmt); \ } while (0) #define put_error_key(key, err, fmt...) \ put_error_ctx((key)->provctx, (err), fmt) #define put_error_op_ctx(ctx, err, fmt...) \ put_error_ctx((ctx)->provctx, (err), fmt) #define IBMCA_ERR_INTERNAL_ERROR 1 #define IBMCA_ERR_MALLOC_FAILED 2 #define IBMCA_ERR_INVALID_PARAM 3 #define IBMCA_ERR_CONFIGURATION 4 #define IBMCA_ERR_LIBICA_FAILED 5 #define IBMCA_ERR_SIGNATURE_BAD 6 #define IBMCA_ERR_EC_CURVE_NOT_SUPPORTED 7 #define UNUSED(var) ((void)(var)) /* Algorithm support definitions */ struct ibmca_mech_capability { const char *capability; const OSSL_PARAM **details; }; extern const OSSL_ALGORITHM ibmca_rsa_keymgmt[]; extern const OSSL_ALGORITHM ibmca_rsa_asym_cipher[]; extern const OSSL_ALGORITHM ibmca_rsa_signature[]; #define IBMCA_RSA_DEFAULT_BITS 2048 #define IBMCA_RSA_DEFAULT_PUB_EXP 65537L #define IBMCA_RSA_DEFAULT_DIGEST NID_sha256 #define IBMCA_RSA_PSS_DEFAULT_DIGEST NID_sha1 #define IBMCA_RSA_PSS_DEFAULT_MGF NID_mgf1 #define IBMCA_RSA_PSS_DEFAULT_MGF_DIGEST NID_sha1 #define IBMCA_RSA_PSS_DEFAULT_SALTLEN 20 #define IBMCA_RSA_OAEP_DEFAULT_DIGEST NID_sha1 #define IBMCA_RSA_DEFAULT_PADDING RSA_PKCS1_PADDING #define IBMCA_RSA_MIN_MODULUS_BITS 512 #define IBMCA_SSL_MAX_MASTER_KEY_LENGTH 48 #define IBMCA_RSA_PSS_DEFAULTS { IBMCA_RSA_PSS_DEFAULT_DIGEST, \ IBMCA_RSA_PSS_DEFAULT_MGF, \ IBMCA_RSA_PSS_DEFAULT_MGF_DIGEST, \ IBMCA_RSA_PSS_DEFAULT_SALTLEN, \ false \ } #define MAX_DIGINFO_SIZE 128 extern const OSSL_ITEM ibmca_rsa_padding_table[]; int ibmca_rsa_build_digest_info(const struct ibmca_prov_ctx *provctx, const EVP_MD *md, const unsigned char *data, size_t data_len, unsigned char *out, size_t outsize, size_t *outlen); int ibmca_rsa_add_pkcs1_padding(const struct ibmca_prov_ctx *provctx, int type, const unsigned char *in, size_t inlen, unsigned char *out, size_t outlen); int ibmca_rsa_check_pkcs1_padding_type1(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outsize, unsigned char **outptr, size_t *outlen); int ibmca_rsa_check_pkcs1_padding_type2(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outsize, size_t *outlen, const unsigned char *kdk, size_t kdklen); int ibmca_rsa_add_oaep_mgf1_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outlen, const EVP_MD *oaep_md, const EVP_MD *mgf1_md, const unsigned char *label, size_t label_len); int ibmca_rsa_check_oaep_mgf1_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outsize, size_t *outlen, const EVP_MD *oaep_md, const EVP_MD *mgf1_md, const unsigned char *label, size_t label_len); int ibmca_rsa_check_pkcs1_tls_padding(const struct ibmca_prov_ctx *provctx, unsigned int client_version, unsigned int alt_version, const unsigned char *in, size_t inlen, unsigned char *out, size_t outsize, size_t *outlen); int ibmca_rsa_add_x931_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outlen, int digest_nid); int ibmca_rsa_check_X931_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, int inlen, unsigned char *out, size_t outsize, unsigned char **outptr, size_t *outlen, int digest_nid); int ibmca_rsa_add_pss_mgf1_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outlen, const EVP_MD *pss_md, const EVP_MD *mgf1_md, int saltlen); int ibmca_rsa_check_pss_mgf1_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, const unsigned char *data, size_t datalen, const EVP_MD *pss_md, const EVP_MD *mgf1_md, int saltlen); int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key, const unsigned char *in, size_t inlen, unsigned char *kdk, size_t kdklen); int ibmca_keymgmt_rsa_pub_as_bn(struct ibmca_key *key, BIGNUM **n, BIGNUM **e); int ibmca_rsa_priv_with_blinding(struct ibmca_key *key, const unsigned char *in, unsigned char *out, size_t rsa_size); int ossl_bn_rsa_do_unblind(const unsigned char *intermediate, const BIGNUM *unblind, const unsigned char *to_mod, unsigned char *buf, int num, BN_MONT_CTX *m_ctx, BN_ULONG n0); extern const OSSL_ALGORITHM ibmca_ec_keymgmt[]; extern const OSSL_ALGORITHM ibmca_ec_signature[]; extern const OSSL_ALGORITHM ibmca_ec_keyexch[]; extern const struct ibmca_mech_capability ibmca_ec_capabilities[]; #define IBMCA_EC_DEFAULT_DIGEST NID_sha256 extern const OSSL_ALGORITHM ibmca_dh_keymgmt[]; extern const OSSL_ALGORITHM ibmca_dh_keyexch[]; extern const struct ibmca_mech_capability ibmca_dh_capabilities[]; openssl-ibmca-2.4.1/src/provider/p_key.c000066400000000000000000000350031450276407300201570ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include "p_ibmca.h" void ibmca_keymgmt_upref(struct ibmca_key *key) { ibmca_debug_key(key, "key: %p", key); __sync_add_and_fetch(&key->ref_count, 1); ibmca_debug_key(key, "ref_count: %u", key->ref_count); } unsigned int ibmca_keymgmt_downref(struct ibmca_key *key) { const struct ibmca_prov_ctx *provctx; unsigned int cnt; assert(key->ref_count > 0); provctx = key->provctx; ibmca_debug_ctx(provctx, "key: %p ", key); cnt = __sync_sub_and_fetch(&key->ref_count, 1); ibmca_debug_ctx(provctx, "ref_count: %u", cnt); return cnt; } struct ibmca_key *ibmca_keymgmt_new(const struct ibmca_prov_ctx *provctx, int type, const char *algorithm, void (*free_cb)(struct ibmca_key *key), int (*dup_cb)(const struct ibmca_key *key, struct ibmca_key *new_key), size_t (*get_max_param_size)( const struct ibmca_key *key), OSSL_FUNC_keymgmt_export_fn *export, OSSL_FUNC_keymgmt_import_fn *import, OSSL_FUNC_keymgmt_has_fn *has, OSSL_FUNC_keymgmt_match_fn *match) { struct ibmca_key *key; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p type: %d algorithm: '%s'", provctx, type, algorithm); key = P_ZALLOC(provctx, sizeof(struct ibmca_key)); if (key == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate a key"); return NULL; } key->provctx = provctx; key->type = type; key->algorithm = algorithm; key->free_cb = free_cb; key->dup_cb = dup_cb; key->get_max_param_size = get_max_param_size; key->export = export; key->import = import; key->has = has; key->match = match; if (pthread_rwlock_init(&key->fallback_pkey_cache_lock, NULL) != 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "pthread_rwlock_init failed: %s", strerror(errno)); P_FREE(provctx, key); return NULL; } ibmca_keymgmt_upref(key); ibmca_debug_ctx(provctx, "key: %p", key); return key; } void ibmca_keymgmt_free(void *vkey) { struct ibmca_key *key = vkey; if (key == NULL) return; ibmca_debug_key(key, "key: %p", key); if (ibmca_keymgmt_downref(key) > 0) return; ibmca_debug_key(key, "free key: %p", key); if (key->free_cb != NULL) key->free_cb(key); ibmca_clean_fallback_pkey_cache(key); pthread_rwlock_destroy(&key->fallback_pkey_cache_lock); P_FREE(key->provctx, key); } void *ibmca_keymgmt_dup(const void *vfrom, int selection) { const struct ibmca_key *from = vfrom; struct ibmca_key *key; if (from == NULL) return NULL; ibmca_debug_key(from, "from: %p selection: 0x%x", from, selection); if ((selection & OSSL_KEYMGMT_SELECT_ALL) == 0) return NULL; key = ibmca_keymgmt_new(from->provctx, from->type, from->algorithm, from->free_cb, from->dup_cb, from->get_max_param_size, from->export, from->import, from->has, from->match); if (key == NULL) { ibmca_debug_key(from, "ERROR: ibmca_keymgmt_new failed"); return NULL; } if (from->dup_cb != NULL) { if (from->dup_cb(from, key) == 0) { ibmca_debug_key(from, "ERROR: dup_cb failed"); ibmca_keymgmt_free(key); return NULL; } } return key; } int ibmca_keymgmt_match(const struct ibmca_key *key1, const struct ibmca_key *key2) { if (key1 == NULL || key2 == NULL) return 0; ibmca_debug_key(key1, "key1: %p key2: %p", key1, key2); if (key1->provctx != key2->provctx) return 0; if (key1->type != key2->type) return 0; return 1; } struct ibmca_op_ctx *ibmca_keymgmt_gen_init( const struct ibmca_prov_ctx *provctx, int type, void (*free_cb) (struct ibmca_op_ctx *ctx), int (*dup_cb) (const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx)) { struct ibmca_op_ctx *genctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "type: %d", type); genctx = ibmca_op_newctx(provctx, NULL, type, free_cb, dup_cb); if (genctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_op_newctx failed"); return NULL; } if (ibmca_op_init(genctx, NULL, EVP_PKEY_OP_KEYGEN) == 0) { ibmca_debug_ctx(provctx, "ERROR: ibmca_op_init failed"); ibmca_op_freectx(genctx); return NULL; } ibmca_debug_ctx(provctx, "genctx: %p", genctx); return genctx; } void ibmca_keymgmt_gen_cleanup(void *vgenctx) { struct ibmca_op_ctx *genctx = vgenctx; if (genctx == NULL) return; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); ibmca_op_freectx(genctx); } void *ibmca_keymgmt_load(const void *reference, size_t reference_sz) { struct ibmca_key *key; if (reference == NULL) return NULL; if (reference_sz == sizeof(struct ibmca_key)) { /* The contents of the reference is the address to our object */ key = *(struct ibmca_key **)reference; /* We grabbed, so we detach it */ *(struct ibmca_key **)reference = NULL; return key; } return NULL; } EVP_PKEY_CTX *ibmca_new_fallback_pkey_ctx(const struct ibmca_prov_ctx *provctx, EVP_PKEY *pkey, const char *algorithm) { EVP_PKEY_CTX *pkey_ctx = NULL; ibmca_debug_ctx(provctx, "pkey: %p algorithm: '%s'", pkey, algorithm != NULL ? algorithm : "(null)"); if (pkey != NULL) { pkey_ctx = EVP_PKEY_CTX_new_from_pkey(provctx->libctx, pkey, provctx->fallback_property_query); if (pkey_ctx == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_CTX_new_from_name for pkey %p failed", pkey); return NULL; } } else if (algorithm != NULL) { pkey_ctx = EVP_PKEY_CTX_new_from_name(provctx->libctx, algorithm, provctx->fallback_property_query); if (pkey_ctx == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_CTX_new_from_name for '%s' failed", algorithm); return NULL; } } else { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Neither pkey nor algorithm specified"); } return pkey_ctx; } struct ibmca_fallback_pkey_cb_data { const struct ibmca_key *key; EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; }; static int ibmca_fallback_pkey_cb(const OSSL_PARAM params[], void *arg) { struct ibmca_fallback_pkey_cb_data *data = arg; const OSSL_PARAM *p; int rc; ibmca_debug_key(data->key, "key: %p", data->key); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_key(data->key, "param: %s", p->key); rc = EVP_PKEY_fromdata(data->pctx, &data->pkey, OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, (OSSL_PARAM *)params); if (rc == 0) { put_error_key(data->key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_fromdata failed"); return 0; } return 1; } EVP_PKEY *ibmca_new_fallback_pkey(struct ibmca_key *key) { struct ibmca_fallback_pkey_cb_data data; EVP_PKEY *pkey; int rc = 0; if (key == NULL) return NULL; ibmca_debug_key(key, "key: %p", key); /* Get from cache if one exists */ if (pthread_rwlock_rdlock(&key->fallback_pkey_cache_lock) != 0) { ibmca_debug_key(key, "ERROR: pthread_rwlock_rdlock failed: %s", strerror(errno)); return NULL; } retry: if (key->fallback_pkey_cache != NULL) { pkey = key->fallback_pkey_cache; if (EVP_PKEY_up_ref(pkey) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_up_ref failed"); pkey = NULL; } pthread_rwlock_unlock(&key->fallback_pkey_cache_lock); ibmca_debug_key(key, "got from cache: %p", pkey); return pkey; } pthread_rwlock_unlock(&key->fallback_pkey_cache_lock); /* * WR-lock the cache while creating a fallback PKEY to avoid other threads * from creating one on parallel. They will have to wait to get the RD-lock * above and will then get out fallback PKEY from the cache once we have * finished creating it. */ if (pthread_rwlock_wrlock(&key->fallback_pkey_cache_lock) != 0) { ibmca_debug_key(key, "ERROR: pthread_rwlock_wrlock failed: %s", strerror(errno)); return NULL; } /* * Another thread might have put its pkey to the cache in the meantime. * There is a small time window when we gave up the RD-lock until we got * the WR-lock where another thread could have put its fallback pkey to * the cache. * So we need to check now while we are holding the WR-lock if there is * one in the cache and use that one if so. */ if (key->fallback_pkey_cache != NULL) goto retry; data.key = key; data.pkey = NULL; data.pctx = ibmca_new_fallback_pkey_ctx( (struct ibmca_prov_ctx *)key->provctx, NULL, key->algorithm); if (data.pctx == NULL) goto out; if (EVP_PKEY_fromdata_init(data.pctx) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_fromdata_init failed"); goto out; } rc = key->export((struct ibmca_key *)key, OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, ibmca_fallback_pkey_cb, &data); if (rc == 0 || data.pkey == NULL) goto out; out: if (data.pctx != NULL) EVP_PKEY_CTX_free(data.pctx); if (rc != 1 && data.pkey != NULL) { EVP_PKEY_free(data.pkey); data.pkey = NULL; } /* Add pkey to cache */ if (data.pkey != NULL) { if (EVP_PKEY_up_ref(data.pkey) == 1) key->fallback_pkey_cache = data.pkey; } pthread_rwlock_unlock(&key->fallback_pkey_cache_lock); return data.pkey; } void ibmca_clean_fallback_pkey_cache(struct ibmca_key *key) { if (pthread_rwlock_wrlock(&key->fallback_pkey_cache_lock) != 0) { ibmca_debug_key(key, "ERROR: pthread_rwlock_wrlock failed: %s", strerror(errno)); return; } if (key->fallback_pkey_cache != NULL) EVP_PKEY_free(key->fallback_pkey_cache); key->fallback_pkey_cache = NULL; pthread_rwlock_unlock(&key->fallback_pkey_cache_lock); } int ibmca_import_from_fallback_pkey(struct ibmca_key *key, const EVP_PKEY *pkey, int selection) { OSSL_PARAM *params = NULL; int rc = 0; if (key == NULL || pkey == NULL) return 0; ibmca_debug_key(key, "key: %p pkey: %p selection: 0x%x", key, pkey, selection); if (EVP_PKEY_todata(pkey, selection, ¶ms) == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_todata failed"); goto out; } rc = key->import(key, selection, params); if (rc == 0) goto out; rc = 1; out: if (params != NULL) OSSL_PARAM_free(params); return rc; } int ibmca_check_fallback_provider(const struct ibmca_prov_ctx *provctx, EVP_PKEY_CTX *pctx) { const char *name; if (EVP_PKEY_CTX_get0_provider(pctx) == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "PKEY Context is not initialized with a provider"); return 0; } name = OSSL_PROVIDER_get0_name(EVP_PKEY_CTX_get0_provider(pctx)); if (name == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "PKEY Context is not initialized with a provider"); return 0; } ibmca_debug_ctx(provctx, "fallback provider: %s", name); if (strcmp(name, provctx->name) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Fallback provider can not be the %s provider itself", provctx->name); return 0; } return 1; } int ibmca_keygen_cb(EVP_PKEY_CTX *ctx) { struct ibmca_keygen_cb_data *cbdata = EVP_PKEY_CTX_get_app_data(ctx); OSSL_PARAM cb_params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; int p, n; if (cbdata == NULL || cbdata->osslcb == NULL) return 0; cb_params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); cb_params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); n = EVP_PKEY_CTX_get_keygen_info(ctx, 1); return cbdata->osslcb(cb_params, cbdata->cbarg); } openssl-ibmca-2.4.1/src/provider/rsa_asym_cipher.c000066400000000000000000001014061450276407300222210ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include "p_ibmca.h" static OSSL_FUNC_asym_cipher_newctx_fn ibmca_asym_cipher_rsa_newctx; static OSSL_FUNC_asym_cipher_get_ctx_params_fn ibmca_asym_cipher_rsa_get_ctx_params; static OSSL_FUNC_asym_cipher_gettable_ctx_params_fn ibmca_asym_cipher_rsa_gettable_ctx_params; static OSSL_FUNC_asym_cipher_set_ctx_params_fn ibmca_asym_cipher_rsa_set_ctx_params; static OSSL_FUNC_asym_cipher_settable_ctx_params_fn ibmca_asym_cipher_rsa_settable_ctx_params; static OSSL_FUNC_asym_cipher_encrypt_init_fn ibmca_asym_cipher_rsa_encrypt_init; static OSSL_FUNC_asym_cipher_encrypt_fn ibmca_asym_cipher_rsa_encrypt; static OSSL_FUNC_asym_cipher_decrypt_init_fn ibmca_asym_cipher_rsa_decrypt_init; static OSSL_FUNC_asym_cipher_decrypt_fn ibmca_asym_cipher_rsa_decrypt; static void ibmca_asym_cipher_rsa_free_cb(struct ibmca_op_ctx *ctx); static int ibmca_asym_cipher_rsa_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx); static void *ibmca_asym_cipher_rsa_newctx(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; struct ibmca_op_ctx *opctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); opctx = ibmca_op_newctx(provctx, NULL, EVP_PKEY_RSA, ibmca_asym_cipher_rsa_free_cb, ibmca_asym_cipher_rsa_dup_cb); if (opctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_op_newctx failed"); return NULL; } #ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION opctx->rsa.cipher.implicit_rejection = 1; #else opctx->rsa.cipher.implicit_rejection = 0; #endif ibmca_debug_ctx(provctx, "opctx: %p", opctx); return opctx; } static void ibmca_asym_cipher_rsa_free_cb(struct ibmca_op_ctx *ctx) { if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->rsa.cipher.oaep_md != NULL) EVP_MD_free(ctx->rsa.cipher.oaep_md); ctx->rsa.cipher.oaep_md = NULL; if (ctx->rsa.cipher.mgf1_md != NULL) EVP_MD_free(ctx->rsa.cipher.mgf1_md); ctx->rsa.cipher.mgf1_md = NULL; if (ctx->rsa.cipher.oaep_label != NULL) P_FREE(ctx->provctx, ctx->rsa.cipher.oaep_label); ctx->rsa.cipher.oaep_label = NULL; ctx->rsa.cipher.oaep_labellen = 0; } static int ibmca_asym_cipher_rsa_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p new_ctx: %p", ctx, new_ctx); new_ctx->rsa.cipher.oaep_md = ctx->rsa.cipher.oaep_md; if (new_ctx->rsa.cipher.oaep_md != NULL && EVP_MD_up_ref(new_ctx->rsa.cipher.oaep_md) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_up_ref failed"); return 0; } new_ctx->rsa.cipher.mgf1_md = ctx->rsa.cipher.mgf1_md; if (new_ctx->rsa.cipher.mgf1_md != NULL && EVP_MD_up_ref(new_ctx->rsa.cipher.mgf1_md) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_up_ref failed"); return 0; } new_ctx->rsa.cipher.oaep_label = NULL; new_ctx->rsa.cipher.oaep_labellen = 0; new_ctx->rsa.cipher.implicit_rejection = ctx->rsa.cipher.implicit_rejection; return 1; } static int ibmca_asym_cipher_rsa_get_ctx_params(void *vctx, OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; const OSSL_PARAM *p; const char *name = NULL; int i, rc; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_ASYM_CIPHER_PARAM_PAD_MODE */ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE); if (p != NULL) { switch (p->data_type) { case OSSL_PARAM_INTEGER: rc = ibmca_param_build_set_int(ctx->provctx, NULL, params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE, ctx->rsa.cipher.pad_mode); if (rc == 0) return 0; break; case OSSL_PARAM_UTF8_STRING: for (i = 0; ibmca_rsa_padding_table[i].id != 0; i++) { if ((int)ibmca_rsa_padding_table[i].id == ctx->rsa.cipher.pad_mode) { name = ibmca_rsa_padding_table[i].ptr; break; } } if (name == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid RSA padding mode: %d", ctx->rsa.cipher.pad_mode); return 0; } rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE, name); if (rc == 0) return 0; break; default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid param type for: '%s'", OSSL_ASYM_CIPHER_PARAM_PAD_MODE); return 0; } } /* OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST */ if (ctx->rsa.cipher.oaep_md != NULL) name = EVP_MD_get0_name(ctx->rsa.cipher.oaep_md); else name = ""; rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, name); if (rc == 0) return 0; /* OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST */ if (ctx->rsa.cipher.mgf1_md != NULL) name = EVP_MD_get0_name(ctx->rsa.cipher.mgf1_md); rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, name); if (rc == 0) return 0; /* OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL */ rc = ibmca_param_build_set_octet_ptr(ctx->provctx, NULL, params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, ctx->rsa.cipher.oaep_label, ctx->rsa.cipher.oaep_labellen); if (rc == 0) return 0; /* OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION */ rc = ibmca_param_build_set_uint(ctx->provctx, NULL, params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, ctx->rsa.cipher.tls_clnt_version); if (rc == 0) return 0; /* OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION */ rc = ibmca_param_build_set_uint(ctx->provctx, NULL, params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, ctx->rsa.cipher.tls_alt_version); if (rc == 0) return 0; #ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION /* OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION */ rc = ibmca_param_build_set_uint(ctx->provctx, NULL, params, OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, ctx->rsa.cipher.implicit_rejection); if (rc == 0) return 0; #endif return 1; } static int ibmca_asym_cipher_rsa_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; const OSSL_PARAM *p; const char *name, *props; void *label = NULL; size_t labellen = 0; int i, rc; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_ASYM_CIPHER_PARAM_PAD_MODE */ p = OSSL_PARAM_locate((OSSL_PARAM *)params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE); if (p != NULL) { switch (p->data_type) { case OSSL_PARAM_INTEGER: rc = ibmca_param_get_int(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE, &ctx->rsa.cipher.pad_mode); if (rc == 0) return 0; break; case OSSL_PARAM_UTF8_STRING: rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE, &name); if (rc == 1) { ctx->rsa.cipher.pad_mode = 0; for (i = 0; ibmca_rsa_padding_table[i].id != 0; i++) { if (strcmp(name, ibmca_rsa_padding_table[i].ptr) == 0) { ctx->rsa.cipher.pad_mode = ibmca_rsa_padding_table[i].id; break; } } } break; default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid param type for: '%s'", OSSL_ASYM_CIPHER_PARAM_PAD_MODE); return 0; } switch (ctx->rsa.cipher.pad_mode) { case RSA_NO_PADDING: case RSA_PKCS1_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: break; case RSA_PKCS1_OAEP_PADDING: /* Setup default md if not already set */ if (ctx->rsa.cipher.oaep_md == NULL) { ctx->rsa.cipher.oaep_md = EVP_MD_fetch(ctx->provctx->libctx, OBJ_nid2sn(IBMCA_RSA_OAEP_DEFAULT_DIGEST), NULL); if (ctx->rsa.cipher.oaep_md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to fetch default OAEP digest"); return 0; } } break; case RSA_PKCS1_PSS_PADDING: /* PSS is for signatures only */ case RSA_X931_PADDING: /* X.931 is for signatures only */ default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid RSA padding mode: %d", ctx->rsa.cipher.pad_mode); return 0; } } /* OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS */ props = NULL; rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS, &props); if (rc == 0) return 0; /* OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, &name); if (rc == 0) return 0; if (rc > 0) { if (ctx->rsa.cipher.oaep_md != NULL) EVP_MD_free(ctx->rsa.cipher.oaep_md); ctx->rsa.cipher.oaep_md = EVP_MD_fetch(ctx->provctx->libctx, name, props); if (ctx->rsa.cipher.oaep_md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid RSA OAEP digest: '%s'", name); return 0; } } /* OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS */ props = NULL; rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS, &props); if (rc == 0) return 0; /* OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, &name); if (rc == 0) return 0; if (rc > 0) { if (ctx->rsa.cipher.mgf1_md != NULL) EVP_MD_free(ctx->rsa.cipher.mgf1_md); ctx->rsa.cipher.mgf1_md = EVP_MD_fetch(ctx->provctx->libctx, name, props); if (ctx->rsa.cipher.mgf1_md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid RSA MGF1 digest: '%s'", name); return 0; } } /* OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL */ rc = ibmca_param_get_octet_string(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, &label, &labellen); if (rc == 0) return 0; if (rc > 0) { if (ctx->rsa.cipher.oaep_label != NULL) P_FREE(ctx->provctx, ctx->rsa.cipher.oaep_label); ctx->rsa.cipher.oaep_label = label; ctx->rsa.cipher.oaep_labellen = labellen; } /* OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION */ rc = ibmca_param_get_uint(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, &ctx->rsa.cipher.tls_clnt_version); if (rc == 0) return 0; /* OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION */ rc = ibmca_param_get_uint(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, &ctx->rsa.cipher.tls_alt_version); if (rc == 0) return 0; #ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION rc = ibmca_param_get_uint(ctx->provctx, params, OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, &ctx->rsa.cipher.implicit_rejection); if (rc == 0) return 0; #endif return 1; } static const OSSL_PARAM ibmca_asym_cipher_rsa_gettable_params[] = { OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0), OSSL_PARAM_octet_ptr(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, NULL, 0), OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL), OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL), #ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, NULL), #endif OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_asym_cipher_rsa_gettable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; ibmca_debug_ctx(provctx, "ctx: %p", ctx); for (p = ibmca_asym_cipher_rsa_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_asym_cipher_rsa_gettable_params; } static const OSSL_PARAM ibmca_asym_cipher_rsa_settable_params[] = { OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS, NULL, 0), OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS, NULL, 0), OSSL_PARAM_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, NULL, 0), OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL), OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL), #ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, NULL), #endif OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_asym_cipher_rsa_settable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; ibmca_debug_ctx(provctx, "ctx: %p", ctx); for (p = ibmca_asym_cipher_rsa_settable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_asym_cipher_rsa_settable_params; } static int ibmca_asym_cipher_rsa_op_init(struct ibmca_op_ctx *ctx, struct ibmca_key *key, const OSSL_PARAM params[], int operation) { const OSSL_PARAM *p; if (ctx == NULL || key == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p operation: %d", ctx, key, operation); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); if (ibmca_op_init(ctx, key, operation) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_init failed"); return 0; } if (key->type == EVP_PKEY_RSA_PSS) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Encrypt/decrypt operation not support for RSA-PSS keys"); return 0; } /* Setup defaults for this context */ ibmca_asym_cipher_rsa_free_cb(ctx); ctx->rsa.cipher.pad_mode = RSA_PKCS1_PADDING; ctx->rsa.cipher.mgf1_md = NULL; ctx->rsa.cipher.oaep_md = NULL; ctx->rsa.cipher.oaep_label = NULL; ctx->rsa.cipher.oaep_labellen = 0; #ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION ctx->rsa.cipher.implicit_rejection = 1; #else ctx->rsa.cipher.implicit_rejection = 0; #endif if (params != NULL) { if (ibmca_asym_cipher_rsa_set_ctx_params(ctx, params) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_asym_cipher_rsa_set_ctx_params failed"); return 0; } } return 1; } static int ibmca_asym_cipher_rsa_encrypt_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_asym_cipher_rsa_op_init(ctx, key, params, EVP_PKEY_OP_ENCRYPT); } static int ibmca_asym_cipher_rsa_decrypt_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_asym_cipher_rsa_op_init(ctx, key, params, EVP_PKEY_OP_DECRYPT); } static int ibmca_asym_cipher_rsa_encrypt_fallback(struct ibmca_op_ctx *ctx, unsigned char *out, size_t outsize, const unsigned char *in, size_t inlen) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; size_t outlen; int rc = 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p inlen: %lu out: %p outsize: %lu", ctx, ctx->key, inlen, out, outsize); pkey = ibmca_new_fallback_pkey(ctx->key); if (pkey == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(ctx->provctx, pkey, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_encrypt_init(pctx) != 1 || EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_NO_PADDING) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_encrypt_init/EVP_PKEY_CTX_set_rsa_padding failed"); goto out; } if (ibmca_check_fallback_provider(ctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } outlen = outsize; if (EVP_PKEY_encrypt(pctx, out, &outlen, in, inlen) != 1 || outlen != outsize) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_encrypt failed"); goto out; } rc = 1; out: if (pkey != NULL) EVP_PKEY_free(pkey); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); return rc; } static int ibmca_asym_cipher_rsa_encrypt(void *vctx, unsigned char *out, size_t *outlen, size_t outsize, const unsigned char *in, size_t inlen) { struct ibmca_op_ctx *ctx = vctx; unsigned char *enc_data; size_t enc_data_len, rsa_size; int rc = 1; if (ctx == NULL || in == NULL || outlen == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p inlen: %lu out: %p outsize: %lu", ctx, ctx->key, inlen, out, outsize); if (ctx->operation != EVP_PKEY_OP_ENCRYPT) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid operation"); return 0; } rsa_size = ctx->key->get_max_param_size(ctx->key); *outlen = rsa_size; if (out == NULL) /* size query */ goto out; if (outsize < *outlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); return 0; } ibmca_debug_op_ctx(ctx, "pad_mode: %d", ctx->rsa.cipher.pad_mode); /* Allocate padding buffer, if required by padding mode */ switch (ctx->rsa.cipher.pad_mode) { case RSA_NO_PADDING: if (inlen != rsa_size) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid input length"); return 0; } enc_data = (unsigned char *)in; enc_data_len = inlen; break; case RSA_PKCS1_PADDING: case RSA_PKCS1_OAEP_PADDING: if (ibmca_op_alloc_tbuf(ctx, rsa_size) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); return 0; } enc_data_len = ctx->tbuf_len; enc_data = ctx->tbuf; break; case RSA_X931_PADDING: case RSA_PKCS1_PSS_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: /* Only valid for decrypt */ default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid padding mode: %d", ctx->rsa.cipher.pad_mode); return 0; } /* Perform padding */ switch (ctx->rsa.cipher.pad_mode) { case RSA_NO_PADDING: rc = 1; break; case RSA_PKCS1_PADDING: rc = ibmca_rsa_add_pkcs1_padding(ctx->key->provctx, 2, in, inlen, enc_data, enc_data_len); break; case RSA_PKCS1_OAEP_PADDING: rc = ibmca_rsa_add_oaep_mgf1_padding(ctx->key->provctx, in, inlen, enc_data, enc_data_len, ctx->rsa.cipher.oaep_md, ctx->rsa.cipher.mgf1_md, ctx->rsa.cipher.oaep_label, ctx->rsa.cipher.oaep_labellen); break; case RSA_X931_PADDING: case RSA_PKCS1_PSS_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: /* Only valid for decrypt */ default: rc = 0; goto out; } if (rc == 0) goto out; /* Perform public key encrypt */ rc = ica_rsa_mod_expo(ctx->provctx->ica_adapter, enc_data, &ctx->key->rsa.public, out); if (rc != 0) { ibmca_debug_op_ctx(ctx, "ica_rsa_mod_expo failed with: %s", strerror(rc)); rc = ibmca_asym_cipher_rsa_encrypt_fallback(ctx, out, *outlen, enc_data, enc_data_len); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_asym_cipher_rsa_encrypt_fallback failed"); rc = 0; goto out; } } rc = 1; out: if (ctx->tbuf != NULL) P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); ibmca_debug_op_ctx(ctx, "outlen: %lu rc: %d", *outlen, rc); return rc; } static int ibmca_asym_cipher_rsa_decrypt_fallback(struct ibmca_op_ctx *ctx, unsigned char *out, size_t outsize, const unsigned char *in, size_t inlen) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; size_t outlen; int rc = 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p inlen: %lu out: %p outsize: %lu", ctx, ctx->key, inlen, out, outsize); pkey = ibmca_new_fallback_pkey(ctx->key); if (pkey == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(ctx->provctx, pkey, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_decrypt_init(pctx) != 1 || EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_NO_PADDING) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_decrypt_init/EVP_PKEY_CTX_set_rsa_padding failed"); goto out; } if (ibmca_check_fallback_provider(ctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } outlen = outsize; if (EVP_PKEY_decrypt(pctx, out, &outlen, in, inlen) != 1 || outlen != outsize) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_decrypt failed"); goto out; } rc = 1; out: if (pkey != NULL) EVP_PKEY_free(pkey); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); return rc; } static int ibmca_asym_cipher_rsa_decrypt(void *vctx, unsigned char *out, size_t *outlen, size_t outsize, const unsigned char *in, size_t inlen) { unsigned char kdk[SHA256_DIGEST_LENGTH] = {0}; struct ibmca_op_ctx *ctx = vctx; unsigned char *dec_data; size_t dec_data_len, rsa_size; int rc = 1; if (ctx == NULL || in == NULL || outlen == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p inlen: %lu out: %p outsize: %lu", ctx, ctx->key, inlen, out, outsize); if (ctx->operation != EVP_PKEY_OP_DECRYPT) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid operation"); return 0; } rsa_size = ctx->key->get_max_param_size(ctx->key); if (ctx->rsa.cipher.pad_mode == RSA_PKCS1_WITH_TLS_PADDING) *outlen = IBMCA_SSL_MAX_MASTER_KEY_LENGTH; else *outlen = rsa_size; if (out == NULL) /* size query */ goto out; if (outsize < *outlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); return 0; } if (inlen != rsa_size) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid input length"); return 0; } ibmca_debug_op_ctx(ctx, "pad_mode: %d", ctx->rsa.cipher.pad_mode); /* Allocate padding buffer, if required by padding mode */ switch (ctx->rsa.cipher.pad_mode) { case RSA_NO_PADDING: dec_data = out; dec_data_len = *outlen; break; case RSA_PKCS1_PADDING: case RSA_PKCS1_OAEP_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: if (ibmca_op_alloc_tbuf(ctx, rsa_size) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); return 0; } dec_data_len = ctx->tbuf_len; dec_data = ctx->tbuf; break; case RSA_X931_PADDING: case RSA_PKCS1_PSS_PADDING: default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid padding mode: %d", ctx->rsa.cipher.pad_mode); return 0; } /* Perform private key decrypt */ rc = ibmca_rsa_priv_with_blinding(ctx->key, in, dec_data, rsa_size); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ibmca_asym_cipher_rsa_with_blinding failed"); rc = ibmca_asym_cipher_rsa_decrypt_fallback(ctx, dec_data, dec_data_len, in, inlen); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_asym_cipher_rsa_decrypt_fallback failed"); rc = 0; goto out; } } /* Perform padding check */ switch (ctx->rsa.cipher.pad_mode) { case RSA_NO_PADDING: /* outlen is already set */ rc = 1; break; case RSA_PKCS1_PADDING: if (ctx->rsa.cipher.implicit_rejection) { rc = ibmca_keymgmt_rsa_derive_kdk(ctx->key, in, inlen, kdk, sizeof(kdk)); if (rc == 0) goto out; } rc = ibmca_rsa_check_pkcs1_padding_type2(ctx->key->provctx, dec_data, dec_data_len, out, outsize, outlen, ctx->rsa.cipher.implicit_rejection ? kdk : NULL, ctx->rsa.cipher.implicit_rejection ? sizeof(kdk) : 0); break; case RSA_PKCS1_OAEP_PADDING: rc = ibmca_rsa_check_oaep_mgf1_padding(ctx->key->provctx, dec_data, dec_data_len, out, outsize, outlen, ctx->rsa.cipher.oaep_md, ctx->rsa.cipher.mgf1_md, ctx->rsa.cipher.oaep_label, ctx->rsa.cipher.oaep_labellen); break; case RSA_PKCS1_WITH_TLS_PADDING: rc = ibmca_rsa_check_pkcs1_tls_padding(ctx->key->provctx, ctx->rsa.cipher.tls_clnt_version, ctx->rsa.cipher.tls_alt_version, dec_data, dec_data_len, out, outsize, outlen); break; case RSA_X931_PADDING: case RSA_PKCS1_PSS_PADDING: default: rc = 0; goto out; } if (rc == 0) goto out; rc = 1; out: if (ctx->tbuf != NULL) P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); ibmca_debug_op_ctx(ctx, "outlen: %lu rc: %d", *outlen, rc); return rc; } static const OSSL_DISPATCH ibmca_rsa_asym_cipher_functions[] = { /* RSA context constructor, destructor */ { OSSL_FUNC_ASYM_CIPHER_NEWCTX, (void (*)(void))ibmca_asym_cipher_rsa_newctx }, { OSSL_FUNC_ASYM_CIPHER_FREECTX, (void (*)(void))ibmca_op_freectx }, { OSSL_FUNC_ASYM_CIPHER_DUPCTX, (void (*)(void))ibmca_op_dupctx }, /* RSA context set/get parameters */ { OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS, (void (*)(void))ibmca_asym_cipher_rsa_get_ctx_params }, { OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))ibmca_asym_cipher_rsa_gettable_ctx_params }, { OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS, (void (*)(void))ibmca_asym_cipher_rsa_set_ctx_params }, { OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))ibmca_asym_cipher_rsa_settable_ctx_params }, /* RSA encrypt */ { OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT, (void (*)(void))ibmca_asym_cipher_rsa_encrypt_init }, { OSSL_FUNC_ASYM_CIPHER_ENCRYPT, (void (*)(void))ibmca_asym_cipher_rsa_encrypt }, /* RSA decrypt */ { OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT, (void (*)(void))ibmca_asym_cipher_rsa_decrypt_init }, { OSSL_FUNC_ASYM_CIPHER_DECRYPT, (void (*)(void))ibmca_asym_cipher_rsa_decrypt }, { 0, NULL } }; const OSSL_ALGORITHM ibmca_rsa_asym_cipher[] = { { "RSA:rsaEncryption:1.2.840.113549.1.1.1", NULL, ibmca_rsa_asym_cipher_functions, "IBMCA RSA asym cipher implementation" }, { NULL, NULL, NULL, NULL } }; openssl-ibmca-2.4.1/src/provider/rsa_blinding.c000066400000000000000000000352171450276407300215120ustar00rootroot00000000000000/* * Copyright [2023] 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 #include #include "p_ibmca.h" #ifdef SIXTY_FOUR_BIT_LONG #define BN_MASK2 (0xffffffffffffffffL) #endif #ifdef SIXTY_FOUR_BIT #define BN_MASK2 (0xffffffffffffffffLL) #endif #ifdef THIRTY_TWO_BIT #error "Not supported" #endif /* * Provider context used by mod-expo callback function for generating the * blinding factor by BN_BLINDING_create_param() or within BN_BLINDING_update() * when a new blinding factor is generated after 32 requests. * This variable must be thread local! */ static __thread const struct ibmca_prov_ctx *ibmca_mod_expo_provctx = NULL; static int ibmca_rsa_blinding_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) { const struct ibmca_prov_ctx *provctx = ibmca_mod_expo_provctx; ica_rsa_key_mod_expo_t ica_mode_expo; unsigned char *buffer, *in, *out; size_t size; int rc = 0; if (provctx == NULL) return 0; ibmca_debug_ctx(provctx, "provctx: %p", provctx); size = BN_num_bytes(m); buffer = P_ZALLOC(provctx, 4 * size); if (buffer == NULL) { ibmca_debug_ctx(provctx, "Failed to allocate a buffer for libica mod-expo"); goto out; } ica_mode_expo.key_length = size; ica_mode_expo.modulus = buffer; ica_mode_expo.exponent = buffer + size; in = buffer + 2 * size; out = buffer + 3 * size; if (BN_bn2binpad(a, in, size) == -1 || BN_bn2binpad(p, ica_mode_expo.exponent, size) == -1 || BN_bn2binpad(m, ica_mode_expo.modulus, size) == -1) { ibmca_debug_ctx(provctx, "BN_bn2binpad failed"); goto out; } rc = ica_rsa_mod_expo(provctx->ica_adapter, in, &ica_mode_expo, out); if (rc != 0) { ibmca_debug_ctx(provctx, "ica_rsa_mod_expo failed with: %s", strerror(rc)); rc = 0; goto out; } if (BN_bin2bn(out, size, r) == NULL) { ibmca_debug_ctx(provctx, "BN_bin2bn failed"); goto out; } rc = 1; out: P_CLEAR_FREE(provctx, buffer, 4 * size); ibmca_debug_ctx(provctx, "rc: %d", rc); /* Use software fallback if libica operation failed */ return rc != 1 ? BN_mod_exp_mont(r, a, p, m, ctx, m_ctx) : 1; } static BN_BLINDING *ibmca_rsa_setup_blinding(struct ibmca_key *key) { BIGNUM *n = NULL, *e = NULL, *R = NULL, *Ri = NULL, *tmod = NULL; BN_CTX *bn_ctx = NULL; BN_BLINDING *blinding = NULL; BN_ULONG word; int rc; ibmca_debug_key(key, "key: %p", key); bn_ctx = BN_CTX_new_ex(key->provctx->libctx); if (bn_ctx == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_CTX_new_ex failed"); goto out; } rc = ibmca_keymgmt_rsa_pub_as_bn(key, &n, &e); if (rc == 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "No public key available"); goto out; } BN_set_flags(n, BN_FLG_CONSTTIME); /* * Setup the BN_MONT_CTX if needed, it is required by for the mod-expo * callback passed to BN_BLINDING_create_param(). The callback won't be * called if BN_MONT_CTX is NULL. * We hold the write lock on blinding_lock when this function is called, * so no need to use BN_MONT_CTX_set_locked(). */ if (key->rsa.blinding_mont_ctx == NULL) { key->rsa.blinding_mont_ctx = BN_MONT_CTX_new(); if (key->rsa.blinding_mont_ctx == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_MONT_CTX_new failed"); goto out; } if (BN_MONT_CTX_set(key->rsa.blinding_mont_ctx, n, bn_ctx) != 1) { BN_MONT_CTX_free(key->rsa.blinding_mont_ctx); key->rsa.blinding_mont_ctx = NULL; put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_MONT_CTX_new failed"); goto out; } /* Calculate blinding_mont_ctx_n0, BN_MONT_CTX is opaque */ R = BN_CTX_get(bn_ctx); Ri = BN_CTX_get(bn_ctx); tmod = BN_CTX_get(bn_ctx); if (R == NULL || Ri == NULL || tmod == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_CTX_get failed"); goto out; } BN_zero(R); if (!BN_set_bit(R, BN_BITS2)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_set_bit failed"); goto out; } memcpy(&word, key->rsa.public.modulus + key->rsa.public.key_length - sizeof(BN_ULONG), sizeof(word)); if (!BN_set_word(tmod, word)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_set_word failed"); goto out; } if (BN_is_one(tmod)) BN_zero(Ri); else if ((BN_mod_inverse(Ri, R, tmod, bn_ctx)) == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_mod_inverse failed"); goto out; } if (!BN_lshift(Ri, Ri, BN_BITS2)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_lshift failed"); goto out; } if (!BN_is_zero(Ri)) { if (!BN_sub_word(Ri, 1)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_sub_word failed"); goto out; } } else { if (!BN_set_word(Ri, BN_MASK2)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_set_word failed"); goto out; } } if (!BN_div(Ri, NULL, Ri, tmod, bn_ctx)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_div failed"); goto out; } key->rsa.blinding_mont_ctx_n0 = BN_get_word(Ri); } /* * BN_BLINDING_create_param() calls the ibmca_rsa_blinding_bn_mod_exp() * callback which needs to know the provider context. */ ibmca_mod_expo_provctx = key->provctx; blinding = BN_BLINDING_create_param(NULL, e, n, bn_ctx, ibmca_rsa_blinding_bn_mod_exp, key->rsa.blinding_mont_ctx); if (blinding == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_BLINDING_create_param failed"); goto out; } BN_BLINDING_set_current_thread(blinding); out: BN_free(n); BN_free(e); BN_CTX_free(bn_ctx); ibmca_debug_key(key, "blinding: %p", blinding); return blinding; } static BN_BLINDING *ibmca_rsa_get_blinding(struct ibmca_key *key, bool *local) { BN_BLINDING *blinding = NULL; ibmca_debug_key(key, "key: %p", key); if (pthread_rwlock_rdlock(&key->rsa.blinding_lock) != 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "pthread_rwlock_rdlock failed: %s", strerror(errno)); goto out; } while (1) { blinding = key->rsa.blinding; if (blinding != NULL) { if (BN_BLINDING_is_current_thread(blinding)) { *local = true; } else { /* * BN_BLINDING is shared, meaning that accesses require locks, * and that the blinding factor must be stored outside the * BN_BLINDING */ *local = false; blinding = key->rsa.mt_blinding; } } pthread_rwlock_unlock(&key->rsa.blinding_lock); if (blinding != NULL) break; /* WR-lock the blinding lock while setting up the blinding */ if (pthread_rwlock_wrlock(&key->rsa.blinding_lock) != 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "pthread_rwlock_wrlock failed: %s", strerror(errno)); goto out; } if (key->rsa.blinding == NULL) { key->rsa.blinding = ibmca_rsa_setup_blinding(key); if (key->rsa.blinding == NULL) { pthread_rwlock_unlock(&key->rsa.blinding_lock); goto out; } continue; } if (key->rsa.mt_blinding == NULL) { key->rsa.mt_blinding = ibmca_rsa_setup_blinding(key); if (key->rsa.mt_blinding == NULL) { pthread_rwlock_unlock(&key->rsa.blinding_lock); goto out; } continue; } } out: ibmca_debug_key(key, "blinding: %p local: %d", blinding, *local); return blinding; } static int ibmca_rsa_blinding_convert(struct ibmca_key *key, BN_BLINDING *blinding, BIGNUM *unblind, BN_CTX *bn_ctx, const unsigned char *in, unsigned char *out, size_t rsa_size, bool local) { BIGNUM *bn_in; int rc = 0; ibmca_debug_key(key, "key: %p rsa_size: %lu local: %d", key, rsa_size, local); bn_in = BN_CTX_get(bn_ctx); if (bn_in == NULL || BN_bin2bn(in, (int)rsa_size, bn_in) == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_CTX_get/BN_bin2bn failed"); goto out; } if (!local) { /* Shared blinding requires locks */ if (!BN_BLINDING_lock(blinding)) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_BLINDING_lock failed"); goto out; } } /* BN_BLINDING_convert_ex() calls BN_BLINDING_update() which may call * BN_BLINDING_create_param() to generate a new blinding factor. This * calls the ibmca_rsa_blinding_bn_mod_exp() callback which needs to know * the provider context. */ ibmca_mod_expo_provctx = key->provctx; rc = BN_BLINDING_convert_ex(bn_in, unblind, blinding, bn_ctx); if (!local) BN_BLINDING_unlock(blinding); if (rc != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_BLINDING_convert_ex failed"); goto out; } rc = BN_bn2binpad(bn_in, out, rsa_size); if (rc != (int)rsa_size) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); goto out; } rc = 1; out: ibmca_debug_key(key, "rc: %d", rc); return rc; } static int ibmca_rsa_blinding_invert(struct ibmca_key *key, BIGNUM *unblind, const unsigned char *in, unsigned char *out, size_t rsa_size) { int rc; ibmca_debug_key(key, "key: %p rsa_size: %lu", key, rsa_size); rc = ossl_bn_rsa_do_unblind(in, unblind, key->rsa.public.modulus, out, rsa_size, key->rsa.blinding_mont_ctx, key->rsa.blinding_mont_ctx_n0); if (rc <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "ossl_bn_rsa_do_unblind failed"); goto out; } rc = 1; out: ibmca_debug_key(key, "rc: %d", rc); return rc; } int ibmca_rsa_priv_with_blinding(struct ibmca_key *key, const unsigned char *in, unsigned char *out, size_t rsa_size) { BN_BLINDING *blinding; bool local_blinding = false; BIGNUM *unblind = NULL; BN_CTX *bn_ctx = NULL; unsigned char *buf = NULL; int rc = 0; ibmca_debug_key(key, "key: %p rsa_size: %lu", key, rsa_size); if (rsa_size != key->rsa.keylength) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "rsa_size is not modulus size"); goto out; } bn_ctx = BN_CTX_new_ex(key->provctx->libctx); if (bn_ctx == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_CTX_new_ex failed"); goto out; } buf = P_SECURE_ZALLOC(key->provctx, rsa_size * 2); if (buf == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate blinding buffer"); goto out; } blinding = ibmca_rsa_get_blinding(key, &local_blinding); if (blinding == NULL) { ibmca_debug_key(key, "ERROR: ibmca_keymgmt_rsa_get_blinding failed"); goto out; } unblind = BN_CTX_get(bn_ctx); if (unblind == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_CTX_get failed"); goto out; } BN_set_flags(unblind, BN_FLG_CONSTTIME); rc = ibmca_rsa_blinding_convert(key, blinding, unblind, bn_ctx, in, buf, rsa_size, local_blinding); if (rc == 0) { ibmca_debug_key(key, "ERROR: ibmca_keymgmt_rsa_blinding_convert failed"); goto out; } if (ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt)) { rc = ica_rsa_crt(key->provctx->ica_adapter, buf, &key->rsa.private_crt, buf + rsa_size); if (rc != 0) { ibmca_debug_key(key, "ERROR: ica_rsa_crt failed with: %s", strerror(rc)); rc = 0; goto out; } } else if (ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)) { rc = ica_rsa_mod_expo(key->provctx->ica_adapter, buf, &key->rsa.private_me, buf + rsa_size); if (rc != 0) { ibmca_debug_key(key, "ERROR: ica_rsa_mod_expo failed with: %s", strerror(rc)); rc = 0; goto out; } } else { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "No private key"); rc = 0; goto out; } rc = ibmca_rsa_blinding_invert(key, unblind, buf + rsa_size, out, rsa_size); if (rc == 0) { ibmca_debug_key(key, "ERROR: ibmca_rsa_blinding_invert failed"); goto out; } rc = 1; out: if (buf != NULL) P_SECURE_CLEAR_FREE(key->provctx, buf, rsa_size * 2); if (bn_ctx != NULL) BN_CTX_free(bn_ctx); ibmca_debug_key(key, "rc: %d", rc); return rc; } openssl-ibmca-2.4.1/src/provider/rsa_keymgmt.c000066400000000000000000002317011450276407300213750ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include #include #include #include #include "p_ibmca.h" #define ICA_P_LEN(key_len) (((key_len) + 1) / 2 + 8) #define ICA_Q_LEN(key_len) (((key_len) + 1) / 2) #define ICA_DP_LEN(key_len) (((key_len) + 1) / 2 + 8) #define ICA_DQ_LEN(key_len) (((key_len) + 1) / 2) #define ICA_QINV_LEN(key_len) (((key_len) + 1) / 2 + 8) static const struct ibmca_pss_params ibmca_rsa_pss_defaults = IBMCA_RSA_PSS_DEFAULTS; static OSSL_FUNC_keymgmt_new_fn ibmca_keymgmt_rsa_new; static OSSL_FUNC_keymgmt_new_fn ibmca_keymgmt_rsa_pss_new; static OSSL_FUNC_keymgmt_gen_init_fn ibmca_keymgmt_rsa_gen_init; static OSSL_FUNC_keymgmt_gen_init_fn ibmca_keymgmt_rsa_pss_gen_init; static OSSL_FUNC_keymgmt_gen_set_template_fn ibmca_keymgmt_rsa_gen_set_template; static OSSL_FUNC_keymgmt_gen_set_params_fn ibmca_keymgmt_rsa_gen_set_params; static OSSL_FUNC_keymgmt_gen_settable_params_fn ibmca_keymgmt_rsa_gen_settable_params; static OSSL_FUNC_keymgmt_gen_fn ibmca_keymgmt_rsa_gen; static OSSL_FUNC_keymgmt_has_fn ibmca_keymgmt_rsa_has; static OSSL_FUNC_keymgmt_match_fn ibmca_keymgmt_rsa_match; static OSSL_FUNC_keymgmt_validate_fn ibmca_keymgmt_rsa_validate; static OSSL_FUNC_keymgmt_query_operation_name_fn ibmca_keymgmt_rsa_query_operation_name; static OSSL_FUNC_keymgmt_get_params_fn ibmca_keymgmt_rsa_get_params; static OSSL_FUNC_keymgmt_gettable_params_fn ibmca_keymgmt_rsa_gettable_params; static OSSL_FUNC_keymgmt_gettable_params_fn ibmca_keymgmt_rsa_pss_gettable_params; static OSSL_FUNC_keymgmt_export_fn ibmca_keymgmt_rsa_export; static OSSL_FUNC_keymgmt_export_types_fn ibmca_keymgmt_rsa_export_types; static OSSL_FUNC_keymgmt_export_types_fn ibmca_keymgmt_rsa_pss_export_types; static OSSL_FUNC_keymgmt_import_fn ibmca_keymgmt_rsa_import; static OSSL_FUNC_keymgmt_import_types_fn ibmca_keymgmt_rsa_import_types; static OSSL_FUNC_keymgmt_import_types_fn ibmca_keymgmt_rsa_pss_import_types; static void ibmca_keymgmt_rsa_free_cb(struct ibmca_key *key); static int ibmca_keymgmt_rsa_dup_cb(const struct ibmca_key *key, struct ibmca_key *new_key); static int ibmca_keymgmt_rsa_pss_parms_from_data( const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], struct ibmca_pss_params *pss) { const char *props = NULL; const char *name; EVP_MD *md; int rc; /* OSSL_PKEY_PARAM_RSA_DIGEST_PROPS */ rc = ibmca_param_get_utf8(provctx, params, OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, &props); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_DIGEST */ rc = ibmca_param_get_utf8(provctx, params, OSSL_PKEY_PARAM_RSA_DIGEST, &name); if (rc == 0) return 0; if (rc > 0) { md = EVP_MD_fetch(provctx->libctx, name, props); if (md == NULL) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "RSA PSS '%s'='%s' could not be fetched", OSSL_PKEY_PARAM_RSA_DIGEST, name); return 0; } pss->digest_nid = EVP_MD_get_type(md); EVP_MD_free(md); pss->restricted = true; } /* OSSL_PKEY_PARAM_RSA_MASKGENFUNC */ rc = ibmca_param_get_utf8(provctx, params, OSSL_PKEY_PARAM_RSA_MASKGENFUNC, &name); if (rc == 0) return 0; if (rc > 0) { if (strcasecmp(name, OBJ_nid2sn(IBMCA_RSA_PSS_DEFAULT_MGF)) != 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "RSA PSS '%s'='%s' is not supported", OSSL_PKEY_PARAM_RSA_MASKGENFUNC, name); return 0; } pss->mgf_nid = IBMCA_RSA_PSS_DEFAULT_MGF; pss->restricted = true; } /* OSSL_PKEY_PARAM_RSA_MGF1_DIGEST */ rc = ibmca_param_get_utf8(provctx, params, OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, &name); if (rc == 0) return 0; if (rc > 0) { md = EVP_MD_fetch(provctx->libctx, name, props); if (md == NULL) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "RSA PSS '%s'='%s' could not be fetched", OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, name); return 0; } pss->mgf_digest_nid = EVP_MD_get_type(md); EVP_MD_free(md); pss->restricted = true; } /* OSSL_PKEY_PARAM_RSA_PSS_SALTLEN */ rc = ibmca_param_get_int(provctx, params, OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, &pss->saltlen); if (rc == 0) return 0; if (rc > 0) pss->restricted = true; return 1; } static int ibmca_keymgmt_rsa_pss_parms_to_data( const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], struct ibmca_pss_params *pss) { const char *name; int rc; /* OSSL_PKEY_PARAM_RSA_DIGEST */ name = OBJ_nid2sn(pss->digest_nid); rc = ibmca_param_build_set_utf8(provctx, bld, params, OSSL_PKEY_PARAM_RSA_DIGEST, name); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_MASKGENFUNC */ name = OBJ_nid2sn(pss->mgf_nid); rc = ibmca_param_build_set_utf8(provctx, bld, params, OSSL_PKEY_PARAM_RSA_MASKGENFUNC, name); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_MGF1_DIGEST */ name = OBJ_nid2sn(pss->mgf_digest_nid); rc = ibmca_param_build_set_utf8(provctx, bld, params, OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, name); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_PSS_SALTLEN */ rc = ibmca_param_build_set_int(provctx, bld, params, OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, pss->saltlen); if (rc == 0) return 0; return 1; } static int ibmca_keymgmt_rsa_pub_key_from_data( const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], BIGNUM **n, BIGNUM **e) { int rc; /* OSSL_PKEY_PARAM_RSA_N */ rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_N, n); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_E */ rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_E, e); if (rc == 0) return 0; return 1; } static int ibmca_keymgmt_rsa_pub_key_to_data( const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], BIGNUM *n, BIGNUM *e) { int rc; /* OSSL_PKEY_PARAM_RSA_N */ rc = (n == NULL || ibmca_param_build_set_bn(provctx, bld, params, OSSL_PKEY_PARAM_RSA_N, n)); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_E */ rc = (e == NULL || ibmca_param_build_set_bn(provctx, bld, params, OSSL_PKEY_PARAM_RSA_E, e)); if (rc == 0) return 0; return 1; } static int ibmca_keymgmt_rsa_priv_crt_key_from_data( const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], BIGNUM **p, BIGNUM **q, BIGNUM **dp, BIGNUM **dq, BIGNUM **qinv) { int rc; /* OSSL_PKEY_PARAM_RSA_FACTOR1 */ *p = BN_secure_new(); if (*p == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_FACTOR1, p); if (rc <= 0) goto error; /* OSSL_PKEY_PARAM_RSA_FACTOR2 */ *q = BN_secure_new(); if (*q == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_FACTOR2, q); if (rc <= 0) goto error; /* OSSL_PKEY_PARAM_RSA_EXPONENT1 */ *dp = BN_secure_new(); if (*dp == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_EXPONENT1, dp); if (rc <= 0) goto error; /* OSSL_PKEY_PARAM_RSA_EXPONENT2 */ *dq = BN_secure_new(); if (*dq == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_EXPONENT2, dq); if (rc <= 0) goto error; /* OSSL_PKEY_PARAM_RSA_COEFFICIENT1 */ *qinv = BN_secure_new(); if (*qinv == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, qinv); if (rc <= 0) goto error; return 1; error: BN_clear_free(*p); *p = NULL; BN_clear_free(*dp); *dp = NULL; BN_clear_free(*dq); *dq = NULL; BN_clear_free(*qinv); *qinv = NULL; return 0; } static int ibmca_keymgmt_rsa_priv_me_key_from_data( const struct ibmca_prov_ctx *provctx, const OSSL_PARAM params[], BIGNUM **d) { int rc; /* OSSL_PKEY_PARAM_RSA_D */ *d = BN_secure_new(); if (*d == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } rc = ibmca_param_get_bn(provctx, params, OSSL_PKEY_PARAM_RSA_D, d); if (rc <= 0) goto error; return 1; error: BN_clear_free(*d); *d = NULL; return 0; } static int ibmca_keymgmt_rsa_priv_key_to_data( const struct ibmca_prov_ctx *provctx, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], BIGNUM *d, BIGNUM *p, BIGNUM *q, BIGNUM *dp, BIGNUM *dq, BIGNUM *qinv) { int rc; /* OSSL_PKEY_PARAM_RSA_D */ rc = (d == NULL || ibmca_param_build_set_bn(provctx, bld, params, OSSL_PKEY_PARAM_RSA_D, d)); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_FACTOR1 */ rc = (p == NULL || ibmca_param_build_set_bn(provctx, bld, params, OSSL_PKEY_PARAM_RSA_FACTOR1, p)); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_FACTOR2 */ rc = (q == NULL || ibmca_param_build_set_bn(provctx, bld, params, OSSL_PKEY_PARAM_RSA_FACTOR2, q)); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_EXPONENT1 */ rc = (dp == NULL || ibmca_param_build_set_bn(provctx, bld, params, OSSL_PKEY_PARAM_RSA_EXPONENT1, dp)); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_EXPONENT2 */ rc = (dq == NULL || ibmca_param_build_set_bn(provctx, bld, params, OSSL_PKEY_PARAM_RSA_EXPONENT2, dq)); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_RSA_COEFFICIENT1 */ rc = (qinv == NULL || ibmca_param_build_set_bn(provctx, bld, params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, qinv)); if (rc == 0) return 0; return 1; } static size_t ibmca_keymgmt_rsa_get_max_param_size(const struct ibmca_key *key) { return (key->rsa.bits + 7) / 8; } static struct ibmca_key *ibmca_keymgmt_rsa_new_type( const struct ibmca_prov_ctx *provctx, int type) { struct ibmca_key *key; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p type: %d", provctx, type); key = ibmca_keymgmt_new(provctx, type, "RSA", ibmca_keymgmt_rsa_free_cb, ibmca_keymgmt_rsa_dup_cb, ibmca_keymgmt_rsa_get_max_param_size, ibmca_keymgmt_rsa_export, ibmca_keymgmt_rsa_import, ibmca_keymgmt_rsa_has, ibmca_keymgmt_rsa_match); if (key == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_new failed"); return NULL; } if (pthread_rwlock_init(&key->rsa.blinding_lock, NULL) != 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "pthread_rwlock_init failed: %s", strerror(errno)); ibmca_keymgmt_free(key); return NULL; } /* Set defaults */ if (type == EVP_PKEY_RSA_PSS) key->rsa.pss = ibmca_rsa_pss_defaults; return key; } static void *ibmca_keymgmt_rsa_new(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); return ibmca_keymgmt_rsa_new_type(provctx, EVP_PKEY_RSA); } static void *ibmca_keymgmt_rsa_pss_new(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); return ibmca_keymgmt_rsa_new_type(provctx, EVP_PKEY_RSA_PSS); } static int ibmca_keymgmt_rsa_alloc_pub(struct ibmca_key *key) { key->rsa.public.key_length = key->rsa.keylength; key->rsa.public.modulus = P_ZALLOC(key->provctx, key->rsa.public.key_length); key->rsa.public.exponent = P_ZALLOC(key->provctx, key->rsa.public.key_length); if (!ibmca_keymgmt_rsa_pub_valid(&key->rsa.public)) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate libica public RSA key"); return 0; } return 1; } static int ibmca_keymgmt_rsa_alloc_priv_crt(struct ibmca_key *key) { key->rsa.private_crt.key_length = key->rsa.keylength; key->rsa.private_crt.p = P_SECURE_ZALLOC(key->provctx, ICA_P_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.q = P_SECURE_ZALLOC(key->provctx, ICA_Q_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.dp = P_SECURE_ZALLOC(key->provctx, ICA_DP_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.dq = P_SECURE_ZALLOC(key->provctx, ICA_DQ_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.qInverse = P_SECURE_ZALLOC(key->provctx, ICA_QINV_LEN(key->rsa.private_crt.key_length)); if (!ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt)) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate libica private RSA CRT key"); return 0; } return 1; } static int ibmca_keymgmt_rsa_alloc_priv_me(struct ibmca_key *key) { key->rsa.private_me.key_length = key->rsa.keylength; key->rsa.private_me.modulus = P_ZALLOC(key->provctx, key->rsa.private_me.key_length); key->rsa.private_me.exponent = P_ZALLOC(key->provctx, key->rsa.private_me.key_length); if (!ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate libica private RSA ME key"); return 0; } return 1; } static void ibmca_keymgmt_rsa_free_pub(struct ibmca_key *key) { if (key->rsa.public.modulus != NULL) P_CLEAR_FREE(key->provctx, key->rsa.public.modulus, key->rsa.public.key_length); key->rsa.public.modulus = NULL; if (key->rsa.public.exponent != NULL) P_CLEAR_FREE(key->provctx, key->rsa.public.exponent, key->rsa.public.key_length); key->rsa.public.exponent = NULL; key->rsa.public.key_length = 0; } static void ibmca_keymgmt_rsa_free_priv_crt(struct ibmca_key *key) { if (key->rsa.private_crt.p != NULL) P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.p, ICA_P_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.p = NULL; if (key->rsa.private_crt.q != NULL) P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.q, ICA_Q_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.q = NULL; if (key->rsa.private_crt.dp != NULL) P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.dp, ICA_DP_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.dp = NULL; if (key->rsa.private_crt.dq != NULL) P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.dq, ICA_DQ_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.dq = NULL; if (key->rsa.private_crt.qInverse != NULL) P_SECURE_CLEAR_FREE(key->provctx, key->rsa.private_crt.qInverse, ICA_QINV_LEN(key->rsa.private_crt.key_length)); key->rsa.private_crt.qInverse = NULL; key->rsa.private_crt.key_length = 0; } static void ibmca_keymgmt_rsa_free_priv_me(struct ibmca_key *key) { if (key->rsa.private_me.modulus != NULL) P_CLEAR_FREE(key->provctx, key->rsa.private_me.modulus, key->rsa.private_me.key_length); key->rsa.private_me.modulus = NULL; if (key->rsa.private_me.exponent != NULL) P_CLEAR_FREE(key->provctx, key->rsa.private_me.exponent, key->rsa.private_me.key_length); key->rsa.private_me.exponent = NULL; key->rsa.private_me.key_length = 0; } static void ibmca_keymgmt_rsa_clean(struct ibmca_key *key) { if (key == NULL) return; ibmca_debug_key(key, "key: %p", key); ibmca_keymgmt_rsa_free_priv_crt(key); ibmca_keymgmt_rsa_free_priv_me(key); ibmca_keymgmt_rsa_free_pub(key); if (key->type == EVP_PKEY_RSA_PSS) key->rsa.pss = ibmca_rsa_pss_defaults; if (pthread_rwlock_wrlock(&key->rsa.blinding_lock) != 0) { ibmca_debug_key(key, "ERROR: pthread_rwlock_wrlock failed: %s", strerror(errno)); return; } if (key->rsa.blinding != NULL) BN_BLINDING_free(key->rsa.blinding); key->rsa.blinding = NULL; if (key->rsa.mt_blinding) BN_BLINDING_free(key->rsa.mt_blinding); key->rsa.mt_blinding = NULL; if (key->rsa.blinding_mont_ctx != NULL) BN_MONT_CTX_free(key->rsa.blinding_mont_ctx); key->rsa.blinding_mont_ctx = NULL; pthread_rwlock_unlock(&key->rsa.blinding_lock); } static void ibmca_keymgmt_rsa_free_cb(struct ibmca_key *key) { if (key == NULL) return; ibmca_debug_key(key, "key: %p", key); ibmca_keymgmt_rsa_clean(key); pthread_rwlock_destroy(&key->rsa.blinding_lock); } bool ibmca_keymgmt_rsa_pub_valid(const ica_rsa_key_mod_expo_t *public) { return public->key_length != 0 && public->modulus != NULL && public->exponent != NULL; } bool ibmca_keymgmt_rsa_priv_crt_valid(const ica_rsa_key_crt_t *private_crt) { return private_crt->key_length != 0 && private_crt->p != NULL && private_crt->q != NULL && private_crt->dp != NULL && private_crt->dq != NULL && private_crt->qInverse != NULL; } bool ibmca_keymgmt_rsa_priv_me_valid(const ica_rsa_key_mod_expo_t *private_me) { return private_me->key_length != 0 && private_me->modulus != NULL && private_me->exponent != NULL; } static int ibmca_keymgmt_rsa_dup_pub(const struct ibmca_key *key, struct ibmca_key *new_key) { new_key->rsa.public.key_length = key->rsa.public.key_length; new_key->rsa.public.modulus = P_MEMDUP(key->provctx, key->rsa.public.modulus, key->rsa.public.key_length); new_key->rsa.public.exponent = P_MEMDUP(key->provctx, key->rsa.public.exponent, key->rsa.public.key_length); if (!ibmca_keymgmt_rsa_pub_valid(&new_key->rsa.public)) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate libica RSA key"); return 0; } return 1; } static int ibmca_keymgmt_rsa_dup_priv_crt(const struct ibmca_key *key, struct ibmca_key *new_key) { new_key->rsa.private_crt.key_length = key->rsa.private_crt.key_length; new_key->rsa.private_crt.p = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.p, ICA_P_LEN(key->rsa.private_crt.key_length)); new_key->rsa.private_crt.q = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.q, ICA_Q_LEN(key->rsa.private_crt.key_length)); new_key->rsa.private_crt.dp = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.dp, ICA_DP_LEN(key->rsa.private_crt.key_length)); new_key->rsa.private_crt.dq = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.dq, ICA_DQ_LEN(key->rsa.private_crt.key_length)); new_key->rsa.private_crt.qInverse = P_SECURE_MEMDUP(key->provctx, key->rsa.private_crt.qInverse, ICA_QINV_LEN( key->rsa.private_crt.key_length)); if (!ibmca_keymgmt_rsa_priv_crt_valid(&new_key->rsa.private_crt)) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate libica RSA key"); return 0; } return 1; } static int ibmca_keymgmt_rsa_dup_priv_me(const struct ibmca_key *key, struct ibmca_key *new_key) { new_key->rsa.private_me.key_length = key->rsa.private_me.key_length; new_key->rsa.private_me.modulus = P_MEMDUP(key->provctx, key->rsa.private_me.modulus, key->rsa.private_me.key_length); new_key->rsa.private_me.exponent = P_MEMDUP(key->provctx, key->rsa.private_me.exponent, key->rsa.private_me.key_length); if (!ibmca_keymgmt_rsa_priv_me_valid(&new_key->rsa.private_me)) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate libica RSA key"); return 0; } return 1; } static int ibmca_keymgmt_rsa_dup_cb(const struct ibmca_key *key, struct ibmca_key *new_key) { if (key == NULL || new_key == NULL) return 0; ibmca_debug_key(key, "key: %p new_key: %p", key, new_key); if (pthread_rwlock_init(&new_key->rsa.blinding_lock, NULL) != 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "pthread_rwlock_init failed: %s", strerror(errno)); return 0; } new_key->rsa.bits = key->rsa.bits; new_key->rsa.keylength = key->rsa.keylength; if (ibmca_keymgmt_rsa_pub_valid(&key->rsa.public)) { if (ibmca_keymgmt_rsa_dup_pub(key, new_key) == 0) return 0; } if (ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt)) { if (ibmca_keymgmt_rsa_dup_priv_crt(key, new_key) == 0) return 0; } if (ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)) { if (ibmca_keymgmt_rsa_dup_priv_me(key, new_key) == 0) return 0; } if (key->type == EVP_PKEY_RSA_PSS) new_key->rsa.pss = key->rsa.pss; return 1; } static int ibmca_keymgmt_rsa_has(const void *vkey, int selection) { const struct ibmca_key *key = vkey; int ok = 1; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) ok = ok && ibmca_keymgmt_rsa_pub_valid(&key->rsa.public); if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) ok = ok && (ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt) || ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)); ibmca_debug_key(key, "ok: %d", ok); return ok; } static bool ibmca_keymgmt_rsa_pub_equal(const ica_rsa_key_mod_expo_t *public1, const ica_rsa_key_mod_expo_t *public2) { return public1->key_length > 0 && public1->key_length == public2-> key_length && memcmp(public1->exponent, public2->exponent, public1->key_length) == 0 && memcmp(public1->modulus, public2->modulus, public1->key_length) == 0; } static bool ibmca_keymgmt_rsa_priv_crt_equal( const ica_rsa_key_crt_t *private_crt1, const ica_rsa_key_crt_t *private_crt2) { return private_crt1->key_length > 0 && private_crt1->key_length == private_crt2->key_length && CRYPTO_memcmp(private_crt1->p, private_crt2->p, ICA_P_LEN(private_crt1->key_length)) == 0 && CRYPTO_memcmp(private_crt1->q, private_crt2->q, ICA_Q_LEN(private_crt1->key_length)) == 0 && CRYPTO_memcmp(private_crt1->dp, private_crt2->dp, ICA_DP_LEN(private_crt1->key_length)) == 0 && CRYPTO_memcmp(private_crt1->dq, private_crt2->dq, ICA_DQ_LEN(private_crt1->key_length)) == 0 && CRYPTO_memcmp(private_crt1->qInverse, private_crt2->qInverse, ICA_QINV_LEN(private_crt1->key_length)) == 0; } static bool ibmca_keymgmt_rsa_priv_me_equal( const ica_rsa_key_mod_expo_t *private_me1, const ica_rsa_key_mod_expo_t *private_me2) { return private_me1->key_length > 0 && private_me1->key_length == private_me2-> key_length && CRYPTO_memcmp(private_me1->exponent, private_me2->exponent, private_me2->key_length) == 0 && CRYPTO_memcmp(private_me1->modulus, private_me2->modulus, private_me1->key_length) == 0; } static int ibmca_keymgmt_rsa_match(const void *vkey1, const void *vkey2, int selection) { const struct ibmca_key *key1 = vkey1; const struct ibmca_key *key2 = vkey2; int ok = 1, checked = 0; if (key1 == NULL || key2 == NULL) return 0; ibmca_debug_key(key1, "key1: %p key2: %p selection: 0x%x", key1, key2, selection); if (ibmca_keymgmt_match(key1, key2) == 0) return 0; if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { ok = ok && ibmca_keymgmt_rsa_pub_equal(&key1->rsa.public, &key2->rsa.public); checked = 1; } if (!checked && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) ok = ok && (ibmca_keymgmt_rsa_priv_crt_equal(&key1->rsa.private_crt, &key2->rsa.private_crt) || ibmca_keymgmt_rsa_priv_me_equal(&key1->rsa.private_me, &key2->rsa.private_me)); ibmca_debug_key(key1, "ok: %d", ok); return ok; } static int ibmca_keymgmt_rsa_validate(const void *vkey, int selection, int checktype) { struct ibmca_key *key = (struct ibmca_key *)vkey; EVP_PKEY *pkey; EVP_PKEY_CTX *pctx = NULL; int rc = 0; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x checktype: 0x%x", key, selection, checktype); /* * Validate RSA key with OpenSSL, not libica. Libica does not provide a * way to validate an RSA key. */ pkey = ibmca_new_fallback_pkey(key); if (pkey == NULL) return 0; pctx = ibmca_new_fallback_pkey_ctx(key->provctx, pkey, NULL); if (pctx == NULL) goto out; if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR) { rc = EVP_PKEY_check(pctx); } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { rc = EVP_PKEY_public_check(pctx); } ibmca_debug_key(key, "valid: %d", rc); out: if (pctx != NULL) EVP_PKEY_CTX_free(pctx); if (pkey != NULL) EVP_PKEY_free(pkey); return rc; } static const char *ibmca_keymgmt_rsa_query_operation_name(int operation_id) { switch (operation_id) { case OSSL_OP_SIGNATURE: case OSSL_OP_ASYM_CIPHER: return "RSA"; } return NULL; } static void ibmca_keymgmt_rsa_gen_free_cb(struct ibmca_op_ctx *ctx) { if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->rsa.gen.pub_exp != NULL) { BN_free((BIGNUM *)ctx->rsa.gen.pub_exp); ctx->rsa.gen.pub_exp = NULL; } } static int ibmca_keymgmt_rsa_gen_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p new_ctx: %p", ctx, new_ctx); new_ctx->rsa.gen.bits = ctx->rsa.gen.bits; if (ctx->rsa.gen.pub_exp != NULL) { new_ctx->rsa.gen.pub_exp = BN_dup(ctx->rsa.gen.pub_exp); if (new_ctx->rsa.gen.pub_exp == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_MALLOC_FAILED, "BN_dup failed"); return 0; } } if (ctx->type == EVP_PKEY_RSA_PSS) new_ctx->rsa.gen.pss = ctx->rsa.gen.pss; return 1; } static struct ibmca_op_ctx *ibmca_keymgmt_rsa_gen_init_type( const struct ibmca_prov_ctx *provctx, int selection, const OSSL_PARAM params[], int type) { struct ibmca_op_ctx *ctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p selection: 0x%x type: %d", provctx, selection, type); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "selection is not KEYPAIR"); return NULL; } ctx = ibmca_keymgmt_gen_init(provctx, type, ibmca_keymgmt_rsa_gen_free_cb, ibmca_keymgmt_rsa_gen_dup_cb); if (ctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_gen_init failed"); return NULL; } /* set defaults */ ctx->rsa.gen.bits = IBMCA_RSA_DEFAULT_BITS; ctx->rsa.gen.pub_exp = BN_new(); if (ctx->rsa.gen.pub_exp == NULL || BN_set_word(ctx->rsa.gen.pub_exp, IBMCA_RSA_DEFAULT_PUB_EXP) == 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "BN_new/BN_set_word failed"); ibmca_op_freectx(ctx); return NULL; } if (type == EVP_PKEY_RSA_PSS) ctx->rsa.gen.pss = ibmca_rsa_pss_defaults; if (params != NULL) { if (ibmca_keymgmt_rsa_gen_set_params(ctx, params) == 0) { ibmca_debug_ctx(provctx, "ERROR: ibmca_keymgmt_rsa_gen_set_params failed"); ibmca_op_freectx(ctx); return NULL; } } return ctx; } static void *ibmca_keymgmt_rsa_gen_init(void *vprovctx, int selection, const OSSL_PARAM params[]) { const struct ibmca_prov_ctx *provctx = vprovctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); return ibmca_keymgmt_rsa_gen_init_type(provctx, selection, params, EVP_PKEY_RSA); } static void *ibmca_keymgmt_rsa_pss_gen_init(void *vprovctx, int selection, const OSSL_PARAM params[]) { const struct ibmca_prov_ctx *provctx = vprovctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); return ibmca_keymgmt_rsa_gen_init_type(provctx, selection, params, EVP_PKEY_RSA_PSS); } static int ibmca_keymgmt_rsa_gen_set_template(void *vgenctx, void *vtempl) { struct ibmca_op_ctx *genctx = vgenctx; struct ibmca_key *templ = vtempl; if (genctx == NULL || templ == NULL) return 0; ibmca_debug_op_ctx(genctx, "genctx: %p templ: %p", genctx, templ); if (genctx->type != templ->type) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "invalid template key type"); return 0; } ibmca_keymgmt_rsa_gen_free_cb(genctx); genctx->rsa.gen.bits = templ->rsa.bits; if (ibmca_keymgmt_rsa_pub_valid(&templ->rsa.public)) { genctx->rsa.gen.pub_exp = BN_bin2bn(templ->rsa.public.exponent, templ->rsa.public.key_length, NULL); if (genctx->rsa.gen.pub_exp == NULL) { put_error_op_ctx(genctx, IBMCA_ERR_MALLOC_FAILED, "BN_bin2bn failed"); return 0; } } if (genctx->type == EVP_PKEY_RSA_PSS) genctx->rsa.gen.pss = templ->rsa.pss; return 1; } static const OSSL_PARAM ibmca_rsa_op_ctx_settable_params[] = { OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_BITS, NULL), OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, NULL), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_rsa_pss_op_ctx_settable_params[] = { OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_BITS, NULL), OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, NULL), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MASKGENFUNC, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, NULL), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_rsa_gen_settable_params(void *vgenctx, void *vprovctx) { const struct ibmca_op_ctx *genctx = vgenctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *params, *p; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "type: %d", genctx->type); if (genctx->type == EVP_PKEY_RSA_PSS) params = ibmca_rsa_pss_op_ctx_settable_params; else params = ibmca_rsa_op_ctx_settable_params; for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return params; } static int ibmca_keymgmt_rsa_gen_set_params(void *vgenctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *genctx = vgenctx; const OSSL_PARAM *p; size_t primes; int rc; if (genctx == NULL) return 0; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(genctx, "param: %s", p->key); /* OSSL_PKEY_PARAM_RSA_BITS */ rc = ibmca_param_get_size_t(genctx->provctx, params, OSSL_PKEY_PARAM_RSA_BITS, &genctx->rsa.gen.bits); if (rc == 0) return 0; if (rc > 0 && genctx->rsa.gen.bits < IBMCA_RSA_MIN_MODULUS_BITS) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "RSA '%s': %u is below minimum", OSSL_PKEY_PARAM_RSA_BITS, genctx->rsa.gen.bits); return 0; } /* OSSL_PKEY_PARAM_RSA_PRIMES */ rc = ibmca_param_get_size_t(genctx->provctx, params, OSSL_PKEY_PARAM_RSA_PRIMES, &primes); if (rc == 0) return 0; if (rc > 0 && primes != 2) { put_error_op_ctx(genctx, IBMCA_ERR_INVALID_PARAM, "RSA '%s' value is not 2", OSSL_PKEY_PARAM_RSA_PRIMES); return 0; } /* OSSL_PKEY_PARAM_RSA_E */ rc = ibmca_param_get_bn(genctx->provctx, params, OSSL_PKEY_PARAM_RSA_E, &genctx->rsa.gen.pub_exp); if (rc == 0) return 0; if (genctx->type == EVP_PKEY_RSA_PSS) { /* PSS restriction parameters */ rc = ibmca_keymgmt_rsa_pss_parms_from_data(genctx->provctx, params, &genctx->rsa.gen.pss); if (rc == 0) return 0; } return 1; } static int ibmca_keymgmt_rsa_gen_fallback(struct ibmca_op_ctx *genctx, struct ibmca_key *key, OSSL_CALLBACK *osslcb, void *cbarg) { struct ibmca_keygen_cb_data cbdata; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL; int rc = 0; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); pctx = ibmca_new_fallback_pkey_ctx(genctx->provctx, NULL, "RSA"); if (pctx == NULL) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_keygen_init(pctx) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_keygen_init failed"); goto out; } if (ibmca_check_fallback_provider(genctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, genctx->rsa.gen.bits) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_CTX_set_rsa_keygen_bits failed"); goto out; } if (genctx->rsa.gen.pub_exp != NULL) { if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(pctx, genctx->rsa.gen.pub_exp) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_CTX_set1_rsa_keygen_pubexp failed"); goto out; } } if (osslcb != NULL) { cbdata.osslcb = osslcb; cbdata.cbarg = cbarg; EVP_PKEY_CTX_set_cb(pctx, ibmca_keygen_cb); EVP_PKEY_CTX_set_app_data(pctx, &cbdata); } if (EVP_PKEY_generate(pctx, &pkey) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_generate failed"); goto out; } rc = ibmca_import_from_fallback_pkey(key, pkey, OSSL_KEYMGMT_SELECT_KEYPAIR); if (rc != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_import_from_fallback_pkey failed"); goto out; } rc = 1; out: if (pctx != NULL) EVP_PKEY_CTX_free(pctx); if (pkey != NULL) EVP_PKEY_free(pkey); return rc; } static void *ibmca_keymgmt_rsa_gen(void *vgenctx, OSSL_CALLBACK *osslcb, void *cbarg) { struct ibmca_op_ctx *genctx = vgenctx; OSSL_PARAM cb_params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; struct ibmca_key *key = NULL; int rc, p, n; char *str; if (genctx == NULL) return NULL; ibmca_debug_op_ctx(genctx, "genctx: %p", genctx); cb_params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); cb_params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); key = ibmca_keymgmt_new(genctx->provctx, genctx->type, "RSA", ibmca_keymgmt_rsa_free_cb, ibmca_keymgmt_rsa_dup_cb, ibmca_keymgmt_rsa_get_max_param_size, ibmca_keymgmt_rsa_export, ibmca_keymgmt_rsa_import, ibmca_keymgmt_rsa_has, ibmca_keymgmt_rsa_match); if (key == NULL) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_keymgmt_new failed"); return NULL; } if (pthread_rwlock_init(&key->rsa.blinding_lock, NULL) != 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "pthread_rwlock_init failed: %s", strerror(errno)); ibmca_keymgmt_free(key); return NULL; } key->rsa.bits = genctx->rsa.gen.bits; key->rsa.keylength = (key->rsa.bits + 7) / 8; ibmca_debug_op_ctx(genctx, "bits: %lu", key->rsa.bits); if (ibmca_keymgmt_rsa_alloc_pub(key) == 0) { ibmca_keymgmt_free(key); return NULL; } if (ibmca_keymgmt_rsa_alloc_priv_crt(key) == 0) { ibmca_keymgmt_free(key); return NULL; } if (genctx->rsa.gen.pub_exp != NULL) { if (BN_bn2binpad(genctx->rsa.gen.pub_exp, key->rsa.public.exponent, key->rsa.public.key_length) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for public exponent"); ibmca_keymgmt_free(key); return NULL; } str = BN_bn2hex(genctx->rsa.gen.pub_exp); ibmca_debug_op_ctx(genctx, "public exponent: 0x%s (%d bits)", str, BN_num_bits(genctx->rsa.gen.pub_exp)); P_FREE(genctx->provctx, str); } p = 0; n = 0; if (osslcb != NULL && osslcb(cb_params, cbarg) == 0) { put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "osslcb failed"); ibmca_keymgmt_free(key); return NULL; } rc = ica_rsa_key_generate_crt(genctx->provctx->ica_adapter, key->rsa.bits, &key->rsa.public, &key->rsa.private_crt); if (rc != 0) { ibmca_debug_op_ctx(genctx, "ica_rsa_key_generate_crt failed with: %s", strerror(rc)); rc = ibmca_keymgmt_rsa_gen_fallback(genctx, key, osslcb, cbarg); if (rc != 1) { ibmca_debug_op_ctx(genctx, "ERROR: ibmca_keymgmt_rsa_gen_fallback failed"); ibmca_keymgmt_free(key); return NULL; } } /* If p < q, swap and recalculate now */ rc = ica_rsa_crt_key_check(&key->rsa.private_crt); if (rc > 1) { put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "ica_rsa_crt_key_check failed"); ibmca_keymgmt_free(key); return NULL; } p = 3; n = 0; if (osslcb != NULL && osslcb(cb_params, cbarg) == 0) { put_error_op_ctx(genctx, IBMCA_ERR_INTERNAL_ERROR, "osslcb failed"); ibmca_keymgmt_free(key); return NULL; } if (genctx->type == EVP_PKEY_RSA_PSS) key->rsa.pss = genctx->rsa.gen.pss; ibmca_debug_op_ctx(genctx, "key: %p", key); return key; } static int ibmca_keymgmt_rsa_security_bits(size_t bits) { switch (bits) { case 512: return 0; /* ??? */ case 1024: return 80; case 2048: return 112; case 3072: return 128; case 4096: return 152; case 6144: return 176; case 7680: return 192; case 8192: return 200; case 15360: return 256; default: return 0; } } int ibmca_keymgmt_rsa_pub_as_bn(struct ibmca_key *key, BIGNUM **n, BIGNUM **e) { if (!ibmca_keymgmt_rsa_pub_valid(&key->rsa.public)) return 0; *n = BN_bin2bn(key->rsa.public.modulus, key->rsa.public.key_length, NULL); *e = BN_bin2bn(key->rsa.public.exponent, key->rsa.public.key_length, NULL); if (*n == NULL || *e == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); goto error; } return 1; error: BN_free(*n); *n = NULL; BN_free(*e); *e = NULL; return 0; } static int ibmca_keymgmt_rsa_priv_crt_as_bn(struct ibmca_key *key, BIGNUM **p, BIGNUM **q, BIGNUM **dp, BIGNUM **dq, BIGNUM **qinv) { if (!ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt)) return 0; *p = BN_secure_new(); *q = BN_secure_new(); *dp = BN_secure_new(); *dq = BN_secure_new(); *qinv = BN_secure_new(); if (*p == NULL || *q == NULL || *dp == NULL || *dq == NULL || *qinv == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } *p = BN_bin2bn(key->rsa.private_crt.p, ICA_P_LEN(key->rsa.private_crt.key_length), *p); *q = BN_bin2bn(key->rsa.private_crt.q, ICA_Q_LEN(key->rsa.private_crt.key_length), *q); *dp = BN_bin2bn(key->rsa.private_crt.dp, ICA_DP_LEN(key->rsa.private_crt.key_length), *dp); *dq = BN_bin2bn(key->rsa.private_crt.dq, ICA_DQ_LEN(key->rsa.private_crt.key_length), *dq); *qinv = BN_bin2bn(key->rsa.private_crt.qInverse, ICA_QINV_LEN(key->rsa.private_crt.key_length), *qinv); if (*p == NULL || *q == NULL || *dp == NULL || *dq == NULL || *qinv == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); goto error; } return 1; error: BN_clear_free(*p); *p = NULL; BN_clear_free(*q); *q = NULL; BN_clear_free(*dp); *dp = NULL; BN_clear_free(*dq); *dq = NULL; BN_clear_free(*qinv); *qinv = NULL; return 0; } int ibmca_keymgmt_rsa_priv_me_as_bn(struct ibmca_key *key, BIGNUM **d) { if (!ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)) return 0; *d = BN_secure_new(); if (*d == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "BN_secure_new failed"); goto error; } *d = BN_bin2bn(key->rsa.private_me.exponent, key->rsa.private_me.key_length, *d); if (*d == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); goto error; } return 1; error: BN_clear_free(*d); *d = NULL; return 0; } static int ibmca_keymgmt_rsa_calc_priv_d(struct ibmca_key *key, BIGNUM *n, BIGNUM *e, BIGNUM *p, BIGNUM *q, BIGNUM **d) { BN_CTX *bn_ctx; /* * phi(n) = (p - 1 )(q - 1) = n - p - q + 1 * d = e ^{-1} mod phi(n). */ bn_ctx = BN_CTX_new(); *d = BN_secure_new(); if (bn_ctx == NULL || *d == NULL || BN_copy(*d, n) == NULL || BN_sub(*d, *d, p) == 0 || BN_sub(*d, *d, q) == 0 || BN_add_word(*d, 1) == 0 || BN_mod_inverse(*d, e, *d, bn_ctx) == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "Failed to calculate private key part d"); BN_CTX_free(bn_ctx); BN_clear_free(*d); *d = NULL; return 0; } BN_CTX_free(bn_ctx); return 1; } static int ibmca_keymgmt_rsa_get_params(void *vkey, OSSL_PARAM params[]) { struct ibmca_key *key = vkey; OSSL_PARAM *parm; bool empty; const char *name; BIGNUM *n = NULL, *e = NULL, *d = NULL; BIGNUM *p = NULL, *q = NULL, *dp = NULL, *dq = NULL, *qinv = NULL; int rc; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p", key); for (parm = params; parm != NULL && parm->key != NULL; parm++) ibmca_debug_key(key, "param: %s", parm->key); empty = (!ibmca_keymgmt_rsa_pub_valid(&key->rsa.public) && !ibmca_keymgmt_rsa_priv_crt_valid(&key->rsa.private_crt) && !ibmca_keymgmt_rsa_priv_me_valid(&key->rsa.private_me)); if (!empty) { /* OSSL_PKEY_PARAM_BITS */ rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_BITS, key->rsa.bits); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_SECURITY_BITS */ rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_SECURITY_BITS, ibmca_keymgmt_rsa_security_bits( key->rsa.bits)); if (rc == 0) return 0; /* OSSL_PKEY_PARAM_MAX_SIZE */ rc = ibmca_param_build_set_int(key->provctx, NULL, params, OSSL_PKEY_PARAM_MAX_SIZE, ibmca_keymgmt_rsa_get_max_param_size( key)); if (rc == 0) return 0; } /* * For non-PSS keys or unrestricted RSA-PSS keys only: * OSSL_PKEY_PARAM_DEFAULT_DIGEST */ if ((key->type != EVP_PKEY_RSA_PSS || !key->rsa.pss.restricted)) { name = OBJ_nid2sn(IBMCA_RSA_DEFAULT_DIGEST); rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_DEFAULT_DIGEST, name); if (rc == 0) return 0; } /* * For restricted RSA-PSS keys only: * OSSL_PKEY_PARAM_MANDATORY_DIGEST */ if ((key->type == EVP_PKEY_RSA_PSS && key->rsa.pss.restricted)) { name = OBJ_nid2sn(key->rsa.pss.digest_nid); rc = ibmca_param_build_set_utf8(key->provctx, NULL, params, OSSL_PKEY_PARAM_MANDATORY_DIGEST, name); if (rc == 0) return 0; } /* Public key parts */ rc = ibmca_keymgmt_rsa_pub_as_bn(key, &n, &e); if (rc == 1) { rc = ibmca_keymgmt_rsa_pub_key_to_data(key->provctx, NULL, params, n, e); if (rc == 0) goto out; } /* Private key parts */ rc = ibmca_keymgmt_rsa_priv_crt_as_bn(key, &p, &q, &dp, &dq, &qinv); if (rc == 1) { /* CRT format */ rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); if (rc == 0) { rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); if (rc == 0) goto out; } rc = ibmca_keymgmt_rsa_priv_key_to_data(key->provctx, NULL, params, d, p, q, dp, dq, qinv); if (rc == 0) goto out; } else { rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); if (rc == 1) { /* ME format */ rc = ibmca_keymgmt_rsa_priv_key_to_data(key->provctx, NULL, params, d, NULL, NULL, NULL, NULL, NULL); if (rc == 0) goto out; } } /* Return RSA-PSS parameters only for restricted RSA-PSS keys */ if (key->type == EVP_PKEY_RSA_PSS && key->rsa.pss.restricted) { rc = ibmca_keymgmt_rsa_pss_parms_to_data(key->provctx, NULL, params, &key->rsa.pss); if (rc == 0) goto out; } rc = 1; out: BN_free(n); BN_free(e); BN_free(d); BN_free(p); BN_free(q); BN_free(dp); BN_free(dq); BN_free(qinv); return rc; } static const OSSL_PARAM ibmca_rsa_gettable_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_rsa_gettable_params(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; for (p = ibmca_rsa_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_rsa_gettable_params; } static const OSSL_PARAM ibmca_rsa_pss_gettable_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MASKGENFUNC, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, NULL), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_rsa_pss_gettable_params(void *vprovctx) { const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; if (provctx == NULL) return NULL; for (p = ibmca_rsa_pss_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_rsa_pss_gettable_params; } static const OSSL_PARAM ibmca_rsa_eximport_types[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_rsa_pss_params_eximport_types[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MASKGENFUNC, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_rsa_pss_export_types[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MASKGENFUNC, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, NULL), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_rsa_pss_import_types[] = { OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT1, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT2, NULL, 0), OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST_PROPS, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MASKGENFUNC, NULL, 0), OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_RSA_MGF1_DIGEST, NULL, 0), OSSL_PARAM_int(OSSL_PKEY_PARAM_RSA_PSS_SALTLEN, NULL), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_keymgmt_rsa_export_types(int selection) { if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) return ibmca_rsa_eximport_types; return NULL; } static const OSSL_PARAM *ibmca_keymgmt_rsa_import_types(int selection) { if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) return ibmca_rsa_eximport_types; return NULL; } static const OSSL_PARAM *ibmca_keymgmt_rsa_pss_export_types(int selection) { if (selection == OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) return ibmca_rsa_pss_params_eximport_types; if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) == 0 && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) return ibmca_rsa_eximport_types; if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0 && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) return ibmca_rsa_pss_export_types; return NULL; } static const OSSL_PARAM *ibmca_keymgmt_rsa_pss_import_types(int selection) { if (selection == OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) return ibmca_rsa_pss_params_eximport_types; if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) == 0 && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) return ibmca_rsa_eximport_types; if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0 && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) return ibmca_rsa_pss_import_types; return NULL; } int ibmca_keymgmt_rsa_export(void *vkey, int selection, OSSL_CALLBACK *param_callback, void *cbarg) { struct ibmca_key *key = vkey; OSSL_PARAM_BLD *bld; OSSL_PARAM *params = NULL; BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, *dp = NULL; BIGNUM *dq = NULL, *qinv = NULL; int rc = 1; if (key == NULL || param_callback == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); bld = OSSL_PARAM_BLD_new(); if (bld == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "OSSL_PARAM_BLD_new failed"); return 0; } /* Public key is required if private key is exported */ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { /* Public key parts */ rc = ibmca_keymgmt_rsa_pub_as_bn(key, &n, &e); if (rc == 1) { rc = ibmca_keymgmt_rsa_pub_key_to_data(key->provctx, bld, NULL, n, e); if (rc == 0) goto error; } } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { /* Private key parts */ rc = ibmca_keymgmt_rsa_priv_crt_as_bn(key, &p, &q, &dp, &dq, &qinv); if (rc == 1) { /* CRT format */ rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); if (rc == 0) { rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); if (rc == 0) goto error; } rc = ibmca_keymgmt_rsa_priv_key_to_data(key->provctx, bld, NULL, d, p, q, dp, dq, qinv); if (rc == 0) goto error; } else { rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); if (rc == 1) { /* ME format */ rc = ibmca_keymgmt_rsa_priv_key_to_data(key->provctx, bld, NULL, d, NULL, NULL, NULL, NULL, NULL); if (rc == 0) goto error; } } } if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0 && key->type == EVP_PKEY_RSA_PSS && key->rsa.pss.restricted) { /* PSS parameters */ rc = ibmca_keymgmt_rsa_pss_parms_to_data(key->provctx, bld, NULL, &key->rsa.pss); if (rc == 0) goto error; } params = OSSL_PARAM_BLD_to_param(bld); if (params == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "OSSL_PARAM_BLD_to_param failed"); rc = 0; goto error; } rc = param_callback(params, cbarg); OSSL_PARAM_free(params); error: OSSL_PARAM_BLD_free(bld); if (n != NULL) BN_free(n); if (e != NULL) BN_free(e); if (d != NULL) BN_free(d); if (p != NULL) BN_free(p); if (q != NULL) BN_free(q); if (dp != NULL) BN_free(dp); if (dq != NULL) BN_free(dq); if (qinv != NULL) BN_free(qinv); return rc; } int ibmca_keymgmt_rsa_import(void *vkey, int selection, const OSSL_PARAM params[]) { struct ibmca_key *key = vkey; const OSSL_PARAM *parm; BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; BIGNUM *dp = NULL, *dq = NULL, *qinv = NULL; int rc = 0; if (key == NULL) return 0; ibmca_debug_key(key, "key: %p selection: 0x%x", key, selection); for (parm = params; parm != NULL && parm->key != NULL; parm++) ibmca_debug_key(key, "param: %s", parm->key); /* Clear any already existing key components */ ibmca_keymgmt_rsa_clean(key); ibmca_clean_fallback_pkey_cache(key); /* Import public key parts */ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "RSA public key parts are mandatory"); return 0; } rc = ibmca_keymgmt_rsa_pub_key_from_data(key->provctx, params, &n, &e); if (rc == 0) return 0; key->rsa.bits = BN_num_bits(n); key->rsa.keylength = (key->rsa.bits + 7) / 8; ibmca_debug_key(key, "key: %p bits: %u", key, key->rsa.bits); if (ibmca_keymgmt_rsa_alloc_pub(key) == 0) goto out; if (BN_bn2binpad(n, key->rsa.public.modulus, key->rsa.public.key_length) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for modulus"); goto out; } if (BN_bn2binpad(e, key->rsa.public.exponent, key->rsa.public.key_length) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for public exponent"); goto out; } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { /* Import private key parts */ rc = ibmca_keymgmt_rsa_priv_crt_key_from_data(key->provctx, params, &p, &q, &dp, &dq, &qinv); if (rc == 1) { /* CRT components */ if (ibmca_keymgmt_rsa_alloc_priv_crt(key) == 0) goto out; if (BN_bn2binpad(p, key->rsa.private_crt.p, ICA_P_LEN(key->rsa.private_crt.key_length)) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for private p"); goto out; } if (BN_bn2binpad(q, key->rsa.private_crt.q, ICA_Q_LEN(key->rsa.private_crt.key_length)) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for private q"); goto out; } if (BN_bn2binpad(dp, key->rsa.private_crt.dp, ICA_DP_LEN(key->rsa.private_crt.key_length)) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for private dp"); goto out; } if (BN_bn2binpad(dq, key->rsa.private_crt.dq, ICA_DQ_LEN(key->rsa.private_crt.key_length)) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for private dq"); goto out; } if (BN_bn2binpad(qinv, key->rsa.private_crt.qInverse, ICA_QINV_LEN(key->rsa.private_crt.key_length)) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for private qinv"); goto out; } /* If p < q, swap and recalculate now */ rc = ica_rsa_crt_key_check(&key->rsa.private_crt); if (rc > 1) { rc = 0; put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "ica_rsa_crt_key_check failed"); goto out; } } rc = ibmca_keymgmt_rsa_priv_me_key_from_data(key->provctx, params, &d); if (rc == 1) { /* ME components */ if (ibmca_keymgmt_rsa_alloc_priv_me(key) == 0) goto out; if (BN_bn2binpad(n, key->rsa.private_me.modulus, key->rsa.private_me.key_length) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for modulus"); goto out; } if (BN_bn2binpad(d, key->rsa.private_me.exponent, key->rsa.private_me.key_length) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed for private d"); goto out; } } } if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0 && key->type == EVP_PKEY_RSA_PSS) { /* Import PSS restriction parameters */ rc = ibmca_keymgmt_rsa_pss_parms_from_data(key->provctx, params, &key->rsa.pss); if (rc == 0) goto out; } rc = 1; out: BN_free(n); BN_free(e); BN_free(d); BN_free(p); BN_free(q); BN_free(dp); BN_free(dq); BN_free(qinv); return rc; } int ibmca_keymgmt_rsa_derive_kdk(struct ibmca_key *key, const unsigned char *in, size_t inlen, unsigned char *kdk, size_t kdklen) { BIGNUM *n = NULL, *e = NULL, *d = NULL; BIGNUM *p = NULL, *q = NULL, *dp = NULL, *dq = NULL, *qinv = NULL; unsigned char *buf = NULL; EVP_MAC_CTX *ctx = NULL; EVP_MAC *hmac = NULL; EVP_MD *md = NULL; size_t md_len; unsigned char d_hash[SHA256_DIGEST_LENGTH] = { 0 }; OSSL_PARAM params[2]; int rc, ret = 0; /* * The implementation of this function is copied from OpenSSL's function * derive_kdk() in crypto/rsa/rsa_ossl.c and is slightly modified to fit to * the providers environment. * Changes include: * - Different variable and define names. * - Usage of put_error_ctx and ibmca_debug_ctx to report errors and issue * debug messages. * - Different code to get the private key component 'd'. * - Use of the EVP APIs instead of the internal APIs for Digest and HMAC * operations. */ ibmca_debug_key(key, "key: %p inlen: %lu kdklen: %lu", key, inlen, kdklen); if (kdklen != SHA256_DIGEST_LENGTH) { put_error_key(key, IBMCA_ERR_INVALID_PARAM, "KDK length is wrong"); return 0; } rc = ibmca_keymgmt_rsa_priv_me_as_bn(key, &d); if (rc == 0) { rc = ibmca_keymgmt_rsa_priv_crt_as_bn(key, &p, &q, &dp, &dq, &qinv); if (rc == 0) goto out; rc = ibmca_keymgmt_rsa_pub_as_bn(key, &n, &e); if (rc == 0) goto out; rc = ibmca_keymgmt_rsa_calc_priv_d(key, n, e, p, q, &d); if (rc == 0) goto out; } buf = P_SECURE_ZALLOC(key->provctx, key->rsa.keylength); if (buf == NULL) { put_error_key(key, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate buffer for private key"); goto out; } BN_set_flags(d, BN_FLG_CONSTTIME); if (BN_bn2binpad(d, buf, key->rsa.keylength) < 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); goto out; } /* * we use hardcoded hash so that migrating between versions that use * different hash doesn't provide a Bleichenbacher oracle: * if the attacker can see that different versions return different * messages for the same ciphertext, they'll know that the message is * syntethically generated, which means that the padding check failed */ md = EVP_MD_fetch(key->provctx->libctx, "sha256", NULL); if (md == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_fetch failed for sha256"); goto out; } if (EVP_Digest(buf, key->rsa.keylength, d_hash, NULL, md, NULL) <= 0) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_Digest failed"); goto out; } hmac = EVP_MAC_fetch(key->provctx->libctx, "HMAC", NULL); if (hmac == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_fetch failed for HMAC"); goto out; } ctx = EVP_MAC_CTX_new(hmac); if (hmac == NULL) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_CTX_new failed"); goto out; } params[0] = OSSL_PARAM_construct_utf8_string( OSSL_MAC_PARAM_DIGEST, "sha256", 0); params[1] = OSSL_PARAM_construct_end(); if (EVP_MAC_init(ctx, d_hash, sizeof(d_hash), params) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_init failed for HMAC with sha256"); goto out; } if (inlen < key->rsa.keylength) { memset(buf, 0, key->rsa.keylength - inlen); if (EVP_MAC_update(ctx, buf, key->rsa.keylength - inlen) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_update failed"); goto out; } } if (EVP_MAC_update(ctx, in, inlen) != 1) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_update failed"); goto out; } if (EVP_MAC_final(ctx, kdk, &md_len, kdklen) != 1 || md_len != kdklen) { put_error_key(key, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_final failed"); goto out; } ret = 1; out: BN_free(n); BN_free(e); BN_free(d); BN_free(p); BN_free(q); BN_free(dp); BN_free(dq); BN_free(qinv); if (buf != NULL) P_SECURE_CLEAR_FREE(key->provctx, buf, key->rsa.keylength); EVP_MAC_free(hmac); EVP_MAC_CTX_free(ctx); EVP_MD_free(md); ibmca_debug_key(key, "ret: %d", ret); return ret; } static const OSSL_DISPATCH ibmca_rsa_keymgmt_functions[] = { /* Constructor, destructor */ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ibmca_keymgmt_rsa_new }, { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ibmca_keymgmt_free }, { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ibmca_keymgmt_dup }, /* Key generation and loading */ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ibmca_keymgmt_rsa_gen_init }, { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))ibmca_keymgmt_rsa_gen_set_template }, { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ibmca_keymgmt_rsa_gen_set_params }, { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))ibmca_keymgmt_rsa_gen_settable_params }, { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ibmca_keymgmt_rsa_gen }, { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ibmca_keymgmt_gen_cleanup }, { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ibmca_keymgmt_load }, /* Key object checking */ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ibmca_keymgmt_rsa_has }, { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ibmca_keymgmt_rsa_match }, { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ibmca_keymgmt_rsa_validate }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ibmca_keymgmt_rsa_query_operation_name }, /* Key object information */ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ibmca_keymgmt_rsa_get_params }, { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ibmca_keymgmt_rsa_gettable_params }, /* Import and export routines */ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ibmca_keymgmt_rsa_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ibmca_keymgmt_rsa_export_types }, { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ibmca_keymgmt_rsa_import }, { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ibmca_keymgmt_rsa_import_types }, { 0, NULL } }; static const OSSL_DISPATCH ibmca_rsapss_keymgmt_functions[] = { /* Constructor, destructor */ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ibmca_keymgmt_rsa_pss_new }, { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ibmca_keymgmt_free }, { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ibmca_keymgmt_dup }, /* Key generation and loading */ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ibmca_keymgmt_rsa_pss_gen_init }, { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))ibmca_keymgmt_rsa_gen_set_template }, { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ibmca_keymgmt_rsa_gen_set_params }, { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))ibmca_keymgmt_rsa_gen_settable_params }, { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ibmca_keymgmt_rsa_gen }, { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ibmca_keymgmt_gen_cleanup }, { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ibmca_keymgmt_load }, /* Key object checking */ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ibmca_keymgmt_rsa_has }, { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ibmca_keymgmt_rsa_match }, { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ibmca_keymgmt_rsa_validate }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ibmca_keymgmt_rsa_query_operation_name }, /* Key object information */ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ibmca_keymgmt_rsa_get_params }, { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ibmca_keymgmt_rsa_pss_gettable_params }, /* Import and export routines */ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ibmca_keymgmt_rsa_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ibmca_keymgmt_rsa_pss_export_types }, { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ibmca_keymgmt_rsa_import }, { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ibmca_keymgmt_rsa_pss_import_types }, { 0, NULL } }; const OSSL_ALGORITHM ibmca_rsa_keymgmt[] = { { "RSA:rsaEncryption:1.2.840.113549.1.1.1", NULL, ibmca_rsa_keymgmt_functions, "IBMCA RSA implementation" }, { "RSA-PSS:RSASSA-PSS:1.2.840.113549.1.1.10", NULL, ibmca_rsapss_keymgmt_functions, "IBMCA RSA-PSS implementation" }, { NULL, NULL, NULL, NULL } }; openssl-ibmca-2.4.1/src/provider/rsa_padding.c000066400000000000000000001353611450276407300213330ustar00rootroot00000000000000/* * Copyright [2021-2023] 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 #include #include #include "p_ibmca.h" #include "constant_time.h" const OSSL_ITEM ibmca_rsa_padding_table[] = { { RSA_PKCS1_PADDING, OSSL_PKEY_RSA_PAD_MODE_PKCSV15 }, { RSA_NO_PADDING, OSSL_PKEY_RSA_PAD_MODE_NONE }, { RSA_PKCS1_OAEP_PADDING, OSSL_PKEY_RSA_PAD_MODE_OAEP }, { RSA_PKCS1_OAEP_PADDING, "oeap" }, { RSA_X931_PADDING, OSSL_PKEY_RSA_PAD_MODE_X931 }, { RSA_PKCS1_PSS_PADDING, OSSL_PKEY_RSA_PAD_MODE_PSS }, { RSA_PKCS1_WITH_TLS_PADDING, "" }, /* Will only be set as integer param */ { 0, NULL } }; #define ASN1_SEQUENCE 0x30 #define ASN1_OCTET_STRING 0x04 int ibmca_rsa_build_digest_info(const struct ibmca_prov_ctx *provctx, const EVP_MD *md, const unsigned char *data, size_t data_len, unsigned char *out, size_t outsize, size_t *outlen) { X509_ALGOR *algid; int aid_len, md_len, seq_len, rc = 0; unsigned char *p; ibmca_debug_ctx(provctx, "md: '%s' data_len: %lu outsize: %lu", EVP_MD_get0_name(md), data_len, outsize); /* DigestInfo ::= SEQUENCE { digestAlgorithm AlgorithmIdentifier, digest OCTET STRING } */ md_len = EVP_MD_get_size(md); if (md_len <= 0 || md_len > 0x7F) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_get_size failed or invalid digest size"); return 0; } if (data_len != (size_t)md_len) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Input data size is incorrect, it must match the digest size: data size: %lu expected: %d", data_len, md_len); return 0; } algid = X509_ALGOR_new(); if (algid == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "X509_ALGOR_new failed"); goto out; } X509_ALGOR_set0(algid, OBJ_nid2obj(EVP_MD_get_type(md)), V_ASN1_NULL, NULL); aid_len = i2d_X509_ALGOR(algid, NULL); if (aid_len <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "i2d_X509_ALGOR failed"); goto out; } seq_len = aid_len + 2 + md_len; if (seq_len > 0x7F) *outlen = 4 + seq_len; else *outlen = 2 + seq_len; if (outsize < *outlen) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Output buffer size too small"); goto out; } p = out; *(p++) = ASN1_SEQUENCE; if (seq_len > 0x7F) { *(p++) = 0x82; *(p++) = (seq_len >> 8); *(p++) = (seq_len & 0xff); } else { *(p++) = seq_len; } if (i2d_X509_ALGOR(algid, &p) != aid_len) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "i2d_X509_ALGOR failed"); goto out; } *(p++) = ASN1_OCTET_STRING; *(p++) = md_len; memcpy(p, data, md_len); ibmca_debug_ctx(provctx, "outlen: %lu", *outlen); rc = 1; out: if (algid != NULL) X509_ALGOR_free(algid); return rc; } static int ibmca_rsa_prf(const struct ibmca_prov_ctx *provctx, unsigned char *out, size_t outlen, const char *label, size_t labellen, const unsigned char *kdk, size_t kdklen, uint16_t bitlen) { size_t pos; int ret = 0; uint16_t iter = 0; unsigned char be_iter[sizeof(iter)]; unsigned char be_bitlen[sizeof(bitlen)]; EVP_MAC_CTX *ctx = NULL; EVP_MAC *hmac = NULL; unsigned char hmac_out[SHA256_DIGEST_LENGTH]; OSSL_PARAM params[2]; size_t md_len; /* * The implementation of this function is copied from OpenSSL's function * ossl_rsa_prf() in crypto/rsa/rsapk1.c and is slightly modified to fit to * the providers environment. * Changes include: * - Different variable and define names. * - Usage of put_error_ctx and ibmca_debug_ctx to report errors and issue * debug messages. * - Use of the EVP API instead of the internal APIs for HMAC operations. */ ibmca_debug_ctx(provctx, "outlen: %lu labellen: %lu kdk: %p kdklen: %lu", outlen, labellen, kdk, kdklen); if (outlen * 8 != bitlen) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "invalid outlen"); return 0; } be_bitlen[0] = (bitlen >> 8) & 0xff; be_bitlen[1] = bitlen & 0xff; hmac = EVP_MAC_fetch(provctx->libctx, "HMAC", NULL); if (hmac == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_fetch failed for HMAC"); goto out; } ctx = EVP_MAC_CTX_new(hmac); if (hmac == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_CTX_new failed"); goto out; } /* * we use hardcoded hash so that migrating between versions that use * different hash doesn't provide a Bleichenbacher oracle: * if the attacker can see that different versions return different * messages for the same ciphertext, they'll know that the message is * syntethically generated, which means that the padding check failed */ params[0] = OSSL_PARAM_construct_utf8_string( OSSL_MAC_PARAM_DIGEST, "sha256", 0); params[1] = OSSL_PARAM_construct_end(); if (EVP_MAC_init(ctx, kdk, kdklen, params) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_init failed for HMAC with sha256"); goto out; } for (pos = 0; pos < outlen; pos += SHA256_DIGEST_LENGTH, iter++) { if (EVP_MAC_init(ctx, NULL, 0, NULL) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_init failed"); goto out; } be_iter[0] = (iter >> 8) & 0xff; be_iter[1] = iter & 0xff; if (EVP_MAC_update(ctx, be_iter, sizeof(be_iter)) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_update failed"); goto out; } if (EVP_MAC_update(ctx, (unsigned char *)label, labellen) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_update failed"); goto out; } if (EVP_MAC_update(ctx, be_bitlen, sizeof(be_bitlen)) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_update failed"); goto out; } /* * HMAC_Final requires the output buffer to fit the whole MAC * value, so we need to use the intermediate buffer for the last * unaligned block */ md_len = SHA256_DIGEST_LENGTH; if (pos + SHA256_DIGEST_LENGTH > outlen) { if (EVP_MAC_final(ctx, hmac_out, &md_len, sizeof(hmac_out)) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_final failed"); goto out; } memcpy(out + pos, hmac_out, outlen - pos); } else { if (EVP_MAC_final(ctx, out + pos, &md_len, outlen - pos) != 1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MAC_final failed"); goto out; } } } ret = 1; out: EVP_MAC_free(hmac); EVP_MAC_CTX_free(ctx); ibmca_debug_ctx(provctx, "ret: %d", ret); return ret; } int ibmca_rsa_add_pkcs1_padding(const struct ibmca_prov_ctx *provctx, int type, const unsigned char *in, size_t inlen, unsigned char *out, size_t outlen) { int i, pad_len; unsigned char *p; ibmca_debug_ctx(provctx, "type: %d inlen: %lu outlen: %lu", type, inlen, outlen); /* * The format is * 00 || BT || PS || 00 || D * BT - block type * PS - padding string, at least 8 bytes of FF for BT = 1 or at least 8 * bytes of random non-zero data for BT = 2 * D - data. */ if (outlen < (inlen + RSA_PKCS1_PADDING_SIZE)) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data too large for the key type"); return 0; } pad_len = outlen - 3 - inlen; if (pad_len < 8) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data too large for the key type"); return 0; } p = out; *(p++) = 0; *(p++) = type; switch (type) { case 1: memset(p, 0xff, pad_len); p += pad_len; break; case 2: if (RAND_bytes_ex(provctx->libctx, p, pad_len, 0) <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "RAND_bytes_ex failed"); return 0; } for (i = 0; i < pad_len; i++, p++) { while (*p == '\0') { if (RAND_bytes_ex(provctx->libctx, p, 1, 0) <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "RAND_bytes_ex failed"); return 0; } } } break; default: put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Invalid PKCS1 block type: %d", type); return 0; } *(p++) = 0; memcpy(p, in, inlen); return 1; } int ibmca_rsa_check_pkcs1_padding_type1(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outsize, unsigned char **outptr, size_t *outlen) { const unsigned char *p; int found = 0; ibmca_debug_ctx(provctx, "inlen: %lu outsize: %lu", inlen, outsize); /* * The format is * 00 || BT || PS || 00 || D * BT - block type * PS - padding string, at least 8 bytes of FF * D - data. */ if (inlen < RSA_PKCS1_PADDING_SIZE) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "PKCS1 encoding error"); return 0; } p = in; if (*(p++) != 0 || *(p++) != 1) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "PKCS1 encoding error"); return 0; } while (p < in + inlen) { if (*p != 0xff) { if (*p == 0x00) { found = 1; break; } put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "PKCS1 encoding error"); return 0; } p++; } if (!found) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "PKCS1 encoding error"); return 0; } p++; *outlen = inlen - (p - in); if (outsize < *outlen) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); return 0; } if (out != NULL) memcpy(out, p, *outlen); if (outptr != NULL) *outptr = (unsigned char *)p; ibmca_debug_ctx(provctx, "outlen: %lu", *outlen); return 1; } #define MAX_LEN_GEN_TRIES 128 int ibmca_rsa_check_pkcs1_padding_type2(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outsize, size_t *outlen, const unsigned char *kdk, size_t kdklen) { unsigned int ok = 0, found, zero; size_t zero_index = 0, msg_index, mlen; unsigned char *synthetic = NULL; int synthethic_length; uint16_t len_candidate; unsigned char candidate_lengths[MAX_LEN_GEN_TRIES * sizeof(len_candidate)]; uint16_t len_mask; uint16_t max_sep_offset; int synth_msg_index = 0; size_t i, j; /* * The implementation of this function is copied from OpenSSL's function * ossl_rsa_padding_check_PKCS1_type_2() in crypto/rsa/rsa_pk1.c * and is slightly modified to fit to the providers environment. * Changes include: * - Different variable, function and define names. * - Usage of put_error_ctx and ibmca_debug_ctx to report errors and issue * debug messages. */ ibmca_debug_ctx(provctx, "inlen: %lu outsize: %lu kdk: %p kdklen: %lu", inlen, outsize, kdk, kdklen); /* * The format is * 00 || BT || PS || 00 || D * BT - block type * PS - padding string, at least 8 bytes of random non-zero data for BT = 2 * D - data. */ /* * PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography Standard", * section 7.2.2. */ if (inlen < RSA_PKCS1_PADDING_SIZE) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "PKCS1 encoding error"); return 0; } if (kdk != NULL && kdklen > 0) { /* * Implicit rejection is enabled. * Generate a random message to return in case the padding checks fail. */ synthetic = P_ZALLOC(provctx, inlen); if (synthetic == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate synthetic buffer"); return 0; } if (ibmca_rsa_prf(provctx, synthetic, inlen, "message", 7, kdk, kdklen, inlen * 8) != 1) goto out; /* decide how long the random message should be */ if (ibmca_rsa_prf(provctx, candidate_lengths, sizeof(candidate_lengths), "length", 6, kdk, kdklen, MAX_LEN_GEN_TRIES * sizeof(len_candidate) * 8) != 1) goto out; /* * max message size is the size of the modulus size minus 2 bytes for * version and padding type and a minimum of 8 bytes padding */ len_mask = max_sep_offset = inlen - 2 - 8; /* * we want a mask so lets propagate the high bit to all positions less * significant than it */ len_mask |= len_mask >> 1; len_mask |= len_mask >> 2; len_mask |= len_mask >> 4; len_mask |= len_mask >> 8; synthethic_length = 0; for (i = 0; i < MAX_LEN_GEN_TRIES * (int)sizeof(len_candidate); i += sizeof(len_candidate)) { len_candidate = (candidate_lengths[i] << 8) | candidate_lengths[i + 1]; len_candidate &= len_mask; synthethic_length = constant_time_select_int( constant_time_lt(len_candidate, max_sep_offset), len_candidate, synthethic_length); } synth_msg_index = inlen - synthethic_length; } ok = constant_time_is_zero(in[0]); ok &= constant_time_eq(in[1], 2); /* scan over padding data */ found = 0; for (i = 2; i < inlen; i++) { zero = constant_time_is_zero(in[i]); zero_index = constant_time_select_int(~found & zero, i, zero_index); found |= zero; } /* * PS must be at least 8 bytes long, and it starts two bytes into |enc_msg|. * If we never found a 0-byte, then |zero_index| is 0 and the check * also fails. */ ok &= constant_time_ge(zero_index, 2 + 8); /* * Skip the zero byte. This is incorrect if we never found a zero-byte * but in this case we also do not copy the message out. */ msg_index = zero_index + 1; mlen = inlen - msg_index; /* * For good measure, do this check in constant time as well. */ ok &= constant_time_ge(outsize, mlen); /* * since at this point the |msg_index| does not provide the signal * indicating if the padding check failed or not, we don't have to worry * about leaking the length of returned message, we still need to ensure * that we read contents of both buffers so that cache accesses don't leak * the value of |good| */ if (kdk != NULL) { msg_index = constant_time_select_int(ok, msg_index, synth_msg_index); for (i = msg_index, j = 0; i < inlen && j < outsize; i++, j++) out[j] = constant_time_select_8(ok, in[i], synthetic[i]); } else { for (i = msg_index, j = 0; i < inlen && j < outsize; i++, j++) out[j] = constant_time_select_8(ok, in[i], out[j]); } *outlen = j; out: if (synthetic != NULL) P_FREE(provctx, synthetic); ibmca_debug_ctx(provctx, "ok: %d outlen: %lu", constant_time_select_int(ok, 1, 0), *outlen); if (kdk != NULL) return 1; else return constant_time_select_int(ok, 1, 0); } static int ibmca_rsa_pkcs1_mgf1(const struct ibmca_prov_ctx *provctx, unsigned char *mask, long mask_len, const unsigned char *seed, long seed_len, const EVP_MD *mgf1_md) { long i, outlen = 0; unsigned char cnt[4]; EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); unsigned char md[EVP_MAX_MD_SIZE]; int mdlen; int rc = 0; if (md_ctx == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_new failed"); return 0; } mdlen = EVP_MD_get_size(mgf1_md); if (mdlen < 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_get_size failed"); goto err; } /* step 4 */ for (i = 0; outlen < mask_len; i++) { /* step 4a: D = I2BS(counter, 4) */ cnt[0] = (unsigned char)((i >> 24) & 255); cnt[1] = (unsigned char)((i >> 16) & 255); cnt[2] = (unsigned char)((i >> 8)) & 255; cnt[3] = (unsigned char)(i & 255); /* step 4b: T =T || hash(mgfSeed || D) */ if (!EVP_DigestInit_ex(md_ctx, mgf1_md, NULL) || !EVP_DigestUpdate(md_ctx, seed, seed_len) || !EVP_DigestUpdate(md_ctx, cnt, 4)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestInit_ex/EVP_DigestUpdate failed"); goto err; } if (outlen + mdlen <= mask_len) { if (!EVP_DigestFinal_ex(md_ctx, mask + outlen, NULL)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestFinal_ex failed"); goto err; } outlen += mdlen; } else { if (!EVP_DigestFinal_ex(md_ctx, md, NULL)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestFinal_ex failed"); goto err; } memcpy(mask + outlen, md, mask_len - outlen); outlen = mask_len; } } rc = 1; err: OPENSSL_cleanse(md, sizeof(md)); EVP_MD_CTX_free(md_ctx); return rc; } int ibmca_rsa_add_oaep_mgf1_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outlen, const EVP_MD *oaep_md, const EVP_MD *mgf1_md, const unsigned char *label, size_t label_len) { int ps_len; size_t oaep_md_len, dbmask_len = 0, i; unsigned char *masked_seed, *masked_db, *dbmask = NULL; unsigned char seed[EVP_MAX_MD_SIZE]; int rc = 0; if (oaep_md == NULL) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "No OAEP digest available"); return 0; } if (mgf1_md == NULL) mgf1_md = oaep_md; ibmca_debug_ctx(provctx, "inlen: %lu outlen: %lu oaep_md: '%s' mgf1_md: '%s' label_len: %lu", inlen, outlen, EVP_MD_get0_name(oaep_md), EVP_MD_get0_name(mgf1_md), label_len); oaep_md_len = EVP_MD_get_size(oaep_md); if (oaep_md_len <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_get_size failed"); goto done; } if (inlen > outlen - (2 * oaep_md_len) - 2) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data too large for the key type"); return 0; } /* * pkcs1v2.2 Step i: * The encoded messages is a concatenated single octet, 0x00 with * maskedSeed and maskedDB to create encoded message EM. * So lets mark of the places in our output buffer. */ memset(out, 0, outlen); masked_seed = out + 1; masked_db = out + oaep_md_len + 1; /* * pkcs1v2.2, Step b: * Generate an octet string PS and concatenate to DB. */ ps_len = outlen - inlen - (2 * oaep_md_len) - 2; if (EVP_Digest((void *)label, label_len, masked_db, NULL, oaep_md, NULL) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_Digest failed"); goto done; } memset(masked_db + oaep_md_len, 0, ps_len); /* * pkcs1v2.2, Step c: * We have already concatenated hash and PS to maskedDB. * Now just concatenate 0x01 and message. */ masked_db[oaep_md_len + ps_len] = 0x01; memcpy(masked_db + (oaep_md_len + ps_len + 1), in, inlen); /* * pkcs1v2.2, Step d: * Generate a random seed. */ if (RAND_bytes_ex(provctx->libctx, seed, oaep_md_len, 0) <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "RAND_bytes_ex failed"); goto done; } /* pkcs1v2.2, Step e: * Compute dbmask using MGF1. */ dbmask_len = outlen - oaep_md_len - 1; dbmask = P_ZALLOC(provctx, dbmask_len); if (dbmask == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate mask buffer"); goto done; } if (ibmca_rsa_pkcs1_mgf1(provctx, dbmask, dbmask_len, seed, oaep_md_len, mgf1_md) == 0) goto done; /* pkcs1v2.2, Step f: * Compute maskedDB. */ for (i = 0; i < dbmask_len; i++) masked_db[i] ^= dbmask[i]; /* pkcs1v2.2, Step g: * Compute seedMask using MGF1. */ memset(masked_seed, 0, oaep_md_len); if (ibmca_rsa_pkcs1_mgf1(provctx, masked_seed, oaep_md_len, masked_db, dbmask_len, mgf1_md) == 0) goto done; /* pkcs1v2.2, Step h: * Compute maskedSeed. */ for (i = 0; i < oaep_md_len; i++) masked_seed[i] ^= seed[i]; rc = 1; done: if (dbmask) P_CLEAR_FREE(provctx, dbmask, dbmask_len); P_CLEANSE(provctx, seed, sizeof(seed)); return rc; } int ibmca_rsa_check_oaep_mgf1_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outsize, size_t *outlen, const EVP_MD *oaep_md, const EVP_MD *mgf1_md, const unsigned char *label, size_t label_len) { size_t i, dblen = 0, mlen = -1, one_index = 0, msg_index, mdlen; unsigned int ok = 0, found_one_byte, mask; const unsigned char *maskedseed, *maskeddb; unsigned char *db = NULL; unsigned char seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE]; /* * The implementation of this function is copied from OpenSSL's function * RSA_padding_check_PKCS1_OAEP_mgf1() in crypto/rsa/rsa_oaep.c * and is slightly modified to fit to the providers environment. * Changes include: * - Different variable and define names. * - Usage of put_error_ctx and ibmca_debug_ctx to report errors and issue * debug messages. * - No need for copying the input to an allocated 'em' buffer. The caller * guarantees that the size of the input is already the size of the * modulus. */ if (oaep_md == NULL) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "No OAEP digest available"); return 0; } if (mgf1_md == NULL) mgf1_md = oaep_md; ibmca_debug_ctx(provctx, "inlen: %lu outsize: %lu oaep_md: '%s' mgf1_md: '%s' label_len: %lu", inlen, outsize, EVP_MD_get0_name(oaep_md), EVP_MD_get0_name(mgf1_md), label_len); mdlen = EVP_MD_get_size(oaep_md); /* * |inlen| is guaranteed by the caller to be the modulus size. * |inlen| >= 2 * |mdlen| + 2 must hold for the modulus * irrespective of the ciphertext, see PKCS #1 v2.2, section 7.1.2. * This does not leak any side-channel information. */ if (inlen < 2 * mdlen + 2) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Input parameters wrong"); goto done; } dblen = inlen - mdlen - 1; db = P_ZALLOC(provctx, dblen); if (db == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate mask or message buffer"); goto done; } /* * The first byte must be zero, however we must not leak if this is * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001). */ ok = constant_time_is_zero(in[0]); maskedseed = in + 1; maskeddb = in + 1 + mdlen; if (ibmca_rsa_pkcs1_mgf1(provctx, seed, mdlen, maskeddb, dblen, mgf1_md) == 0) goto done; for (i = 0; i < mdlen; i++) seed[i] ^= maskedseed[i]; if (ibmca_rsa_pkcs1_mgf1(provctx, db, dblen, seed, mdlen, mgf1_md) == 0) goto done; for (i = 0; i < dblen; i++) db[i] ^= maskeddb[i]; if (EVP_Digest((void *)label, label_len, phash, NULL, oaep_md, NULL) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_Digest failed"); goto done; } ok &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen)); found_one_byte = 0; for (i = mdlen; i < dblen; i++) { /* * Padding consists of a number of 0-bytes, followed by a 1. */ unsigned int equals1 = constant_time_eq(db[i], 1); unsigned int equals0 = constant_time_is_zero(db[i]); one_index = constant_time_select_int(~found_one_byte & equals1, i, one_index); found_one_byte |= equals1; ok &= (found_one_byte | equals0); } ok &= found_one_byte; /* * At this point |good| is zero unless the plaintext was valid, * so plaintext-awareness ensures timing side-channels are no longer a * concern. */ msg_index = one_index + 1; mlen = dblen - msg_index; /* * For good measure, do this check in constant time as well. */ ok &= constant_time_ge(outsize, mlen); /* * Move the result in-place by |dblen| - |mdlen| - 1 - |mlen| bytes * to the left. * Then if |good| move |mlen| bytes from |db| + |mdlen| + 1 to |out|. * Otherwise leave |out| unchanged. * Copy the memory back in a way that does not reveal the size of * the data being copied via a timing side channel. This requires copying * parts of the buffer multiple times based on the bits set in the real * length. Clear bits do a non-copy with identical access pattern. * The loop below has overall complexity of O(N*log(N)). */ outsize = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, outsize), dblen - mdlen - 1, outsize); for (msg_index = 1; msg_index < dblen - mdlen - 1; msg_index <<= 1) { mask = ~constant_time_eq(msg_index & (dblen - mdlen - 1 - mlen), 0); for (i = mdlen + 1; i < dblen - msg_index; i++) db[i] = constant_time_select_8(mask, db[i + msg_index], db[i]); } for (i = 0; i < outsize; i++) { mask = ok & constant_time_lt(i, mlen); out[i] = constant_time_select_8(mask, db[i + mdlen + 1], out[i]); } done: P_CLEANSE(provctx, seed, sizeof(seed)); if (db) P_CLEAR_FREE(provctx, db, dblen); *outlen = constant_time_select_int(ok, mlen, 0); ibmca_debug_ctx(provctx, "ok: %d outlen: %lu", constant_time_select_int(ok, 1, 0), *outlen); return constant_time_select_int(ok, 1, 0); } int ibmca_rsa_check_pkcs1_tls_padding(const struct ibmca_prov_ctx *provctx, unsigned int client_version, unsigned int alt_version, const unsigned char *in, size_t inlen, unsigned char *out, size_t outsize, size_t *outlen) { size_t i; unsigned int ok, version_ok, alt_ok; unsigned char rand_buf[IBMCA_SSL_MAX_MASTER_KEY_LENGTH]; ibmca_debug_ctx(provctx, "inlen: %lu outsize: %lu client_version: 0x%04x alt_version: 0x%04x" , inlen, outsize, client_version, alt_version); /* * The implementation of this function is copied from OpenSSL's function * ossl_rsa_padding_check_PKCS1_type_2_TLS() in crypto/rsa/rsa_pk1.c * and is slightly modified to fit to the providers environment. * Changes include: * - Different variable and define names. * - Usage of put_error_ctx and ibmca_debug_ctx to report errors and issue * debug messages. */ /* * The format is * 00 || 02 || PS || 00 || PreMasterSecret * BT - block type * PS - at least 8 bytes of random non-zero data for BT = 2 * D - data = PreMasterSecret (48 bytes) * PreMasterSecret: Version-major | Version-minor | 64 bytes secret */ /* * If these checks fail then either the message in publicly invalid, or * we've been called incorrectly. We can fail immediately. */ if (inlen < RSA_PKCS1_PADDING_SIZE + IBMCA_SSL_MAX_MASTER_KEY_LENGTH) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "PKCS1 encoding error"); return 0; } if (outsize < IBMCA_SSL_MAX_MASTER_KEY_LENGTH) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); return 0; } /* * Generate a random premaster secret to use in the event that we fail * to decrypt. */ if (RAND_priv_bytes_ex(provctx->libctx, rand_buf, IBMCA_SSL_MAX_MASTER_KEY_LENGTH, 0) <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "RAND_priv_bytes_ex failed"); return 0; } ok = constant_time_is_zero(in[0]); ok &= constant_time_eq(in[1], 2); /* Check we have the expected padding data */ for (i = 2; i < inlen - IBMCA_SSL_MAX_MASTER_KEY_LENGTH - 1; i++) ok &= ~constant_time_is_zero_8(in[i]); ok &= constant_time_is_zero_8( in[inlen - IBMCA_SSL_MAX_MASTER_KEY_LENGTH - 1]); /* * If the version in the decrypted pre-master secret is correct then * version_good will be 0xff, otherwise it'll be zero. The * Klima-Pokorny-Rosa extension of Bleichenbacher's attack * (http://eprint.iacr.org/2003/052/) exploits the version number * check as a "bad version oracle". Thus version checks are done in * constant time and are treated like any other decryption error. */ version_ok = constant_time_eq(in[inlen - IBMCA_SSL_MAX_MASTER_KEY_LENGTH], (client_version >> 8) & 0xff); version_ok &= constant_time_eq(in[inlen - IBMCA_SSL_MAX_MASTER_KEY_LENGTH + 1], client_version & 0xff); /* * The premaster secret must contain the same version number as the * ClientHello to detect version rollback attacks (strangely, the * protocol does not offer such protection for DH ciphersuites). * However, buggy clients exist that send the negotiated protocol * version instead if the server does not support the requested * protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set then we tolerate * such clients. In that case alt_version will be non-zero and set to * the negotiated version. */ if (alt_version > 0) { alt_ok = constant_time_eq(in[inlen - IBMCA_SSL_MAX_MASTER_KEY_LENGTH], (alt_version >> 8) & 0xff); alt_ok &= constant_time_eq( in[inlen - IBMCA_SSL_MAX_MASTER_KEY_LENGTH + 1], alt_version & 0xff); version_ok |= alt_ok; } ok &= version_ok; /* * Now copy the result over to the buffer if good, or random data if * not good. */ *outlen = IBMCA_SSL_MAX_MASTER_KEY_LENGTH; for (i = 0; out != NULL && i < IBMCA_SSL_MAX_MASTER_KEY_LENGTH; i++) { out[i] = constant_time_select_8(ok, in[inlen - IBMCA_SSL_MAX_MASTER_KEY_LENGTH + i], rand_buf[i]); } ibmca_debug_ctx(provctx, "ok: %d outlen: %lu", constant_time_select_int(ok, 1, 0), *outlen); /* * We must not leak whether a decryption failure occurs because of * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, * section 7.4.7.1). The code follows that advice of the TLS RFC and * generates a random premaster secret for the case that the decrypt * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 * So, whether we actually succeeded or not, return success. */ return 1; } static int ibmca_rsa_x931_padding_hash_id(int nid) { switch (nid) { case NID_sha1: return 0x33; case NID_sha256: return 0x34; case NID_sha384: return 0x36; case NID_sha512: return 0x35; } return -1; } int ibmca_rsa_add_x931_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outlen, int digest_nid) { int j, hash_id; unsigned char *p; ibmca_debug_ctx(provctx, "inlen: %lu outlen: %lu digest_nid: %d", inlen, outlen, digest_nid); hash_id = ibmca_rsa_x931_padding_hash_id(digest_nid); if (hash_id == -1) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Unsupported signature digest: %d", digest_nid); return 0; } /* * Absolute minimum amount of padding is 1 header nibble, 1 padding * nibble and 2 trailer bytes. */ j = outlen - inlen - 3; if (j < 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data too large for the key type"); return 0; } p = out; /* If no padding start and end nibbles are in one byte */ if (j == 0) { *p++ = 0x6A; } else { *p++ = 0x6B; if (j > 1) { memset(p, 0xBB, j - 1); p += j - 1; } *p++ = 0xBA; } memcpy(p, in, inlen); p += inlen; *p++ = hash_id; *p = 0xCC; return 1; } int ibmca_rsa_check_X931_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, int inlen, unsigned char *out, size_t outsize, unsigned char **outptr, size_t *outlen, int digest_nid) { int i = 0, j, hash_id; const unsigned char *p; ibmca_debug_ctx(provctx, "inlen: %lu outsize: %lu digest_nid: %d", inlen, outsize, digest_nid); hash_id = ibmca_rsa_x931_padding_hash_id(digest_nid); if (hash_id == -1) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Unsupported signature digest: %d", digest_nid); return 0; } p = in; if (((*p != 0x6A) && (*p != 0x6B))) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid X931 padding"); return 0; } if (*p++ == 0x6B) { j = inlen - 3; for (i = 0; i < j; i++) { unsigned char c = *p++; if (c == 0xBA) break; if (c != 0xBB) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid X931 padding"); return 0; } } j -= i; if (i == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid X931 padding"); return 0; } } else { j = inlen - 2; } if (p[j - 1] != hash_id || p[j] != 0xCC) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid X931 trailer"); return 0; } *outlen = j - 1; if (outsize < *outlen) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Output buffer size too small"); return 0; } if (out != NULL) memcpy(out, p, *outlen); if (outptr != NULL) *outptr = (unsigned char *)p; ibmca_debug_ctx(provctx, "outlen: %lu", *outlen); return 1; } int ibmca_rsa_add_pss_mgf1_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, unsigned char *out, size_t outlen, const EVP_MD *pss_md, const EVP_MD *mgf1_md, int saltlen) { int i, rc = 0, maskeddb_len, msbits; unsigned char *h, *salt = NULL, *p; EVP_MD_CTX *ctx = NULL; static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; if (pss_md == NULL) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "No PSS digest available"); return 0; } if (mgf1_md == NULL) mgf1_md = pss_md; ibmca_debug_ctx(provctx, "inlen: %lu outlen: %lu pss_md: '%s' mgf1_md: '%s' saltlen: %d", inlen, outlen, EVP_MD_get0_name(pss_md), EVP_MD_get0_name(mgf1_md), saltlen); msbits = ((outlen * 8) - 1) & 0x7; if (msbits == 0) { *out++ = 0; outlen--; } if (outlen < inlen + 2) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data too large for the key type"); goto err; } if (inlen != (size_t)EVP_MD_get_size(pss_md)) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data size is not the size of the digest"); goto err; } switch (saltlen) { case RSA_PSS_SALTLEN_DIGEST: saltlen = EVP_MD_get_size(pss_md); break; case RSA_PSS_SALTLEN_MAX_SIGN: case RSA_PSS_SALTLEN_MAX: saltlen = outlen - inlen - 2; break; default: if (saltlen < 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Invalid salt len: %d", saltlen); goto err; } } if ((size_t)saltlen > outlen - inlen - 2) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data too large for the key type"); goto err; } ibmca_debug_ctx(provctx,"saltlen: %d", saltlen); if (saltlen > 0) { salt = P_MALLOC(provctx, saltlen); if (salt == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate salt buffer"); goto err; } if (RAND_bytes_ex(provctx->libctx, salt, saltlen, 0) <= 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "RAND_bytes_ex failed"); goto err; } } maskeddb_len = outlen - inlen - 1; h = out + maskeddb_len; ctx = EVP_MD_CTX_new(); if (ctx == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_new failed"); goto err; } if (EVP_DigestInit_ex(ctx, pss_md, NULL) == 0 || EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes)) == 0 || EVP_DigestUpdate(ctx, in, inlen) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestInit_ex/EVP_DigestUpdate failed"); goto err; } if (saltlen != 0 && EVP_DigestUpdate(ctx, salt, saltlen) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestUpdate failed"); goto err; } if (EVP_DigestFinal_ex(ctx, h, NULL) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestFinal_ex failed"); goto err; } /* Generate dbMask in place then perform XOR on it */ if (ibmca_rsa_pkcs1_mgf1(provctx, out, maskeddb_len, h, inlen, mgf1_md) == 0) goto err; p = out; p += outlen - saltlen - inlen - 2; *p++ ^= 0x1; if (saltlen > 0) { for (i = 0; i < saltlen; i++) *p++ ^= salt[i]; } if (msbits != 0) out[0] &= 0xFF >> (8 - msbits); out[outlen - 1] = 0xbc; rc = 1; err: if (ctx != NULL) EVP_MD_CTX_free(ctx); if (salt != NULL) P_CLEAR_FREE(provctx, salt, (size_t)saltlen); return rc; } int ibmca_rsa_check_pss_mgf1_padding(const struct ibmca_prov_ctx *provctx, const unsigned char *in, size_t inlen, const unsigned char *data, size_t datalen, const EVP_MD *pss_md, const EVP_MD *mgf1_md, int saltlen) { int i, rc = 0, maskeddb_len, msbits; const unsigned char *h; unsigned char *db = NULL; EVP_MD_CTX *ctx = NULL; unsigned char h_[EVP_MAX_MD_SIZE]; static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; if (pss_md == NULL) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "No PSS digest available"); return 0; } if (mgf1_md == NULL) mgf1_md = pss_md; ibmca_debug_ctx(provctx, "inlen: %lu datalen: %lu pss_md: '%s' mgf1_md: '%s' saltlen: %d", inlen, datalen, EVP_MD_get0_name(pss_md), EVP_MD_get0_name(mgf1_md), saltlen); if (datalen != (size_t)EVP_MD_get_size(pss_md)) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data size is not the size of the digest"); goto err; } msbits = ((inlen * 8) - 1) & 0x7; if (in[0] & (0xFF << msbits)) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid PSS encoding"); goto err; } if (msbits == 0) { in++; inlen--; } switch (saltlen) { case RSA_PSS_SALTLEN_DIGEST: saltlen = EVP_MD_get_size(pss_md); break; case RSA_PSS_SALTLEN_MAX: saltlen = inlen - datalen - 2; break; case RSA_PSS_SALTLEN_AUTO: break; default: if (saltlen < 0) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Invalid salt len: %d", saltlen); goto err; } } ibmca_debug_ctx(provctx,"saltlen: %d", saltlen); if (saltlen > (int)(inlen - datalen - 2)) { put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM, "Data too large for the key type"); goto err; } if (in[inlen - 1] != 0xbc) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid PSS encoding"); goto err; } maskeddb_len = inlen - datalen - 1; h = in + maskeddb_len; db = P_MALLOC(provctx, maskeddb_len); if (db == NULL) { put_error_ctx(provctx, IBMCA_ERR_MALLOC_FAILED, "Failed to allocate DB buffer"); goto err; } if (ibmca_rsa_pkcs1_mgf1(provctx, db, maskeddb_len, h, datalen, mgf1_md) < 0) goto err; for (i = 0; i < maskeddb_len; i++) db[i] ^= in[i]; if (msbits != 0) db[0] &= 0xFF >> (8 - msbits); for (i = 0; db[i] == 0 && i < (maskeddb_len - 1); i++) ; if (db[i++] != 0x1) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Saltlen recovery failed"); goto err; } if (saltlen != RSA_PSS_SALTLEN_AUTO && (maskeddb_len - i) != saltlen) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "Saltlen check failed. Expected: %d retrieved: %d", saltlen, maskeddb_len - i); goto err; } ctx = EVP_MD_CTX_new(); if (ctx == NULL) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_new failed"); goto err; } if (EVP_DigestInit_ex(ctx, pss_md, NULL) == 0 || EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes)) == 0 || EVP_DigestUpdate(ctx, data, datalen) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestInit_ex/EVP_DigestUpdate failed"); goto err; } if (maskeddb_len - i > 0) { if (EVP_DigestUpdate(ctx, db + i, maskeddb_len - i) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestUpdate failed"); goto err; } } if (EVP_DigestFinal_ex(ctx, h_, NULL) == 0) { put_error_ctx(provctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestFinal_exe failed"); goto err; } if (memcmp(h_, h, datalen)) { put_error_ctx(provctx, IBMCA_ERR_SIGNATURE_BAD, "Bad signature"); rc = 0; } else { rc = 1; } ibmca_debug_ctx(provctx, "rc: %d", rc); err: if (db != NULL) P_CLEAR_FREE(provctx, db, maskeddb_len); if (ctx != NULL) EVP_MD_CTX_free(ctx); return rc; } openssl-ibmca-2.4.1/src/provider/rsa_signature.c000066400000000000000000002055111450276407300217210ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #include #include #include #include "p_ibmca.h" static OSSL_FUNC_signature_newctx_fn ibmca_signature_rsa_newctx; static OSSL_FUNC_signature_sign_init_fn ibmca_signature_rsa_sign_init; static OSSL_FUNC_signature_sign_fn ibmca_signature_rsa_sign; static OSSL_FUNC_signature_verify_init_fn ibmca_signature_rsa_verify_init; static OSSL_FUNC_signature_verify_fn ibmca_signature_rsa_verify; static OSSL_FUNC_signature_verify_recover_init_fn ibmca_signature_rsa_verifyrecover_init; static OSSL_FUNC_signature_verify_recover_fn ibmca_signature_rsa_verify_recover; static OSSL_FUNC_signature_digest_sign_init_fn ibmca_signature_rsa_digest_sign_init; static OSSL_FUNC_signature_digest_sign_update_fn ibmca_signature_rsa_digest_signverify_update; static OSSL_FUNC_signature_digest_sign_final_fn ibmca_signature_rsa_digest_sign_final; static OSSL_FUNC_signature_digest_verify_init_fn ibmca_signature_rsa_digest_verify_init; static OSSL_FUNC_signature_digest_verify_final_fn ibmca_signature_rsa_digest_verify_final; static OSSL_FUNC_signature_get_ctx_params_fn ibmca_signature_rsa_get_ctx_params; static OSSL_FUNC_signature_gettable_ctx_params_fn ibmca_signature_rsa_gettable_ctx_params; static OSSL_FUNC_signature_set_ctx_params_fn ibmca_signature_rsa_set_ctx_params; static OSSL_FUNC_signature_settable_ctx_params_fn ibmca_signature_rsa_settable_ctx_params; static OSSL_FUNC_signature_get_ctx_md_params_fn ibmca_signature_rsa_get_ctx_md_params; static OSSL_FUNC_signature_gettable_ctx_md_params_fn ibmca_signature_rsa_gettable_ctx_md_params; static OSSL_FUNC_signature_set_ctx_md_params_fn ibmca_signature_rsa_set_ctx_md_params; static OSSL_FUNC_signature_settable_ctx_md_params_fn ibmca_signature_rsa_settable_ctx_md_params; static void ibmca_signature_rsa_free_cb(struct ibmca_op_ctx *ctx); static int ibmca_signature_rsa_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx); static const struct ibmca_pss_params ibmca_rsa_pss_defaults = IBMCA_RSA_PSS_DEFAULTS; static void *ibmca_signature_rsa_newctx(void *vprovctx, const char *propq) { const struct ibmca_prov_ctx *provctx = vprovctx; struct ibmca_op_ctx *opctx; if (provctx == NULL) return NULL; ibmca_debug_ctx(provctx, "provctx: %p", provctx); opctx = ibmca_op_newctx(provctx, propq, EVP_PKEY_RSA, ibmca_signature_rsa_free_cb, ibmca_signature_rsa_dup_cb); if (opctx == NULL) { ibmca_debug_ctx(provctx, "ERROR: ibmca_op_newctx failed"); return NULL; } ibmca_debug_ctx(provctx, "opctx: %p", opctx); return opctx; } static void ibmca_signature_rsa_free_cb(struct ibmca_op_ctx *ctx) { if (ctx == NULL) return; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->rsa.signature.md != NULL) EVP_MD_free(ctx->rsa.signature.md); ctx->rsa.signature.md = NULL; ctx->rsa.signature.set_md_allowed = true; if (ctx->rsa.signature.mgf1_md != NULL) EVP_MD_free(ctx->rsa.signature.mgf1_md); ctx->rsa.signature.mgf1_md = NULL; if (ctx->rsa.signature.md_ctx != NULL) EVP_MD_CTX_free(ctx->rsa.signature.md_ctx); ctx->rsa.signature.md_ctx = NULL; } static int ibmca_signature_rsa_dup_cb(const struct ibmca_op_ctx *ctx, struct ibmca_op_ctx *new_ctx) { if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p new_ctx: %p", ctx, new_ctx); new_ctx->rsa.signature.pad_mode = ctx->rsa.signature.pad_mode; new_ctx->rsa.signature.md = ctx->rsa.signature.md; if (new_ctx->rsa.signature.md != NULL) { if (EVP_MD_up_ref(new_ctx->rsa.signature.md) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_up_ref failed"); return 0; } } new_ctx->rsa.signature.set_md_allowed = ctx->rsa.signature.set_md_allowed; new_ctx->rsa.signature.mgf1_md = ctx->rsa.signature.mgf1_md; if (new_ctx->rsa.signature.mgf1_md != NULL) { if (EVP_MD_up_ref(new_ctx->rsa.signature.mgf1_md) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_up_ref failed"); return 0; } } new_ctx->rsa.signature.saltlen = ctx->rsa.signature.saltlen; new_ctx->rsa.signature.pss = ctx->rsa.signature.pss; if (ctx->rsa.signature.md_ctx != NULL) { new_ctx->rsa.signature.md_ctx = EVP_MD_CTX_new(); if (new_ctx->rsa.signature.md_ctx == NULL || EVP_MD_CTX_copy(new_ctx->rsa.signature.md_ctx, ctx->rsa.signature.md_ctx) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_copy failed"); return 0; } } return 1; } static int ibmca_signature_rsa_set_md(struct ibmca_op_ctx *ctx, const char *mdname, int md_nid, const char *props) { EVP_MD *md; if (mdname == NULL) mdname = OBJ_nid2sn(md_nid); ibmca_debug_op_ctx(ctx, "ctx: %p mdname: '%s'", ctx, mdname); if (!ctx->rsa.signature.set_md_allowed) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest not allowed to be set in the current state"); return 0; } md = EVP_MD_fetch(ctx->provctx->libctx, mdname, props != NULL ? props : ctx->propq); if (md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest '%s' could not be fetched", mdname); return 0; } if (ctx->key->type == EVP_PKEY_RSA_PSS && ctx->rsa.signature.pss.restricted && EVP_MD_get_type(md) != ctx->rsa.signature.pss.digest_nid) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "RSA-PSS key is restricted, digest not allowed"); EVP_MD_free(md); return 0; } if (ctx->rsa.signature.md != NULL) EVP_MD_free(ctx->rsa.signature.md); ctx->rsa.signature.md = md; return 1; } static int ibmca_signature_rsa_set_mgf1_md(struct ibmca_op_ctx *ctx, const char *mdname, int md_nid, const char *props) { EVP_MD *md; if (mdname == NULL) mdname = OBJ_nid2sn(md_nid); ibmca_debug_op_ctx(ctx, "ctx: %p mdname: '%s'", ctx, mdname); md = EVP_MD_fetch(ctx->provctx->libctx, mdname, props != NULL ? props : ctx->propq); if (md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Digest '%s' could not be fetched", mdname); return 0; } if (ctx->key->type == EVP_PKEY_RSA_PSS && ctx->rsa.signature.pss.restricted && EVP_MD_get_type(md) != ctx->rsa.signature.pss.mgf_digest_nid) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "RSA-PSS key is restricted, mgf1 digest not allowed"); EVP_MD_free(md); return 0; } if (ctx->rsa.signature.mgf1_md != NULL) EVP_MD_free(ctx->rsa.signature.mgf1_md); ctx->rsa.signature.mgf1_md = md; return 1; } static int ibmca_signature_rsa_pss_check_params(struct ibmca_op_ctx *ctx) { int saltlen; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); if (ctx->rsa.signature.pss.restricted == false) return 1; if (EVP_MD_get_type(ctx->rsa.signature.md) != ctx->rsa.signature.pss.digest_nid) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "RSA-PSS key is restricted, digest not allowed"); return 0; } if (EVP_MD_get_type(ctx->rsa.signature.mgf1_md != NULL ? ctx->rsa.signature.mgf1_md : ctx->rsa.signature.md) != ctx->rsa.signature.pss.mgf_digest_nid) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "RSA-PSS key is restricted, mgf1 digest not allowed"); return 0; } switch (ctx->rsa.signature.saltlen) { case RSA_PSS_SALTLEN_DIGEST: if (EVP_MD_get_size(ctx->rsa.signature.md) < ctx->rsa.signature.pss.saltlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Saltlen should be >= %d, but digest size is %d", ctx->rsa.signature.pss.saltlen, EVP_MD_get_size( ctx->rsa.signature.md)); return 0; } break; case RSA_PSS_SALTLEN_MAX_SIGN: case RSA_PSS_SALTLEN_MAX: #ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: #endif saltlen = ctx->key->get_max_param_size(ctx->key) - EVP_MD_get_size(ctx->rsa.signature.md) - 2; if ((ctx->key->rsa.bits & 0x7) == 1) saltlen--; #ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX if (ctx->rsa.signature.saltlen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX && saltlen > EVP_MD_get_size(ctx->rsa.signature.md)) saltlen = EVP_MD_get_size(ctx->rsa.signature.md); #endif if (saltlen < ctx->rsa.signature.pss.saltlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Saltlen should be >= %d, but max salt len is %d", ctx->rsa.signature.pss.saltlen, saltlen); return 0; } break; default: if (ctx->rsa.signature.saltlen < ctx->rsa.signature.pss.saltlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Saltlen should be >= %d, but salt len is %d", ctx->rsa.signature.pss.saltlen, ctx->rsa.signature.saltlen); return 0; } break; } return 1; } static int ibmca_signature_rsa_op_init(struct ibmca_op_ctx *ctx, struct ibmca_key *key, const OSSL_PARAM params[], int operation, const char *mdname) { const OSSL_PARAM *p; if (ctx == NULL || key == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p operation: %d mdname: %s", ctx, key, operation, mdname != NULL ? mdname : "(null)"); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); if (ibmca_op_init(ctx, key, operation) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_init failed"); return 0; } /* Setup defaults for this context */ ibmca_signature_rsa_free_cb(ctx); ctx->rsa.signature.pss = ibmca_rsa_pss_defaults; /* Max for sign, auto for verify */ #ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX ctx->rsa.signature.pss.saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; #else ctx->rsa.signature.pss.saltlen = RSA_PSS_SALTLEN_AUTO; #endif if (key->type == EVP_PKEY_RSA_PSS) { ctx->rsa.signature.pad_mode = RSA_PKCS1_PSS_PADDING; ibmca_debug_op_ctx(ctx,"RSA-PSS restricted: %d", key->rsa.pss.restricted); if (key->rsa.pss.restricted) ctx->rsa.signature.pss = key->rsa.pss; if (ibmca_signature_rsa_set_md(ctx, NULL, ctx->rsa.signature.pss.digest_nid, NULL) == 0) return 0; if (ctx->rsa.signature.pss.mgf_digest_nid != ctx->rsa.signature.pss.digest_nid && ibmca_signature_rsa_set_mgf1_md(ctx, NULL, ctx->rsa.signature.pss.mgf_digest_nid, NULL) == 0) return 0; } else { ctx->rsa.signature.pad_mode = RSA_PKCS1_PADDING; } ctx->rsa.signature.set_md_allowed = true; if (mdname != NULL) { if (ibmca_signature_rsa_set_md(ctx, mdname, 0, NULL) == 0) return 0; } ctx->rsa.signature.saltlen = ctx->rsa.signature.pss.saltlen; if (params != NULL) { if (ibmca_signature_rsa_set_ctx_params(ctx, params) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_signature_rsa_set_ctx_params failed"); return 0; } } switch (operation) { case EVP_PKEY_OP_SIGNCTX: case EVP_PKEY_OP_VERIFYCTX: ctx->rsa.signature.md_ctx = EVP_MD_CTX_new(); if (ctx->rsa.signature.md_ctx == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_CTX_new failed"); return 0; } if (EVP_DigestInit_ex2(ctx->rsa.signature.md_ctx, ctx->rsa.signature.md, params) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_DigestInit_ex2 failed"); return 0; } ctx->rsa.signature.set_md_allowed = false; break; } return 1; } static int ibmca_signature_rsa_sign_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_rsa_op_init(ctx, key, params, EVP_PKEY_OP_SIGN, NULL); } static int ibmca_signature_rsa_verify_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_rsa_op_init(ctx, key, params, EVP_PKEY_OP_VERIFY, NULL); } static int ibmca_signature_rsa_verifyrecover_init(void *vctx, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_rsa_op_init(ctx, key, params, EVP_PKEY_OP_VERIFYRECOVER, NULL); } static int ibmca_signature_rsa_sign_x931_post_process(struct ibmca_op_ctx *ctx, unsigned char *data, size_t data_len) { BIGNUM *bn_n = NULL, *bn_new_data = NULL, *bn_data = NULL; int rc = 0; /* Special handling for X.931 */ bn_n = BN_bin2bn(ctx->key->rsa.public.modulus, ctx->key->rsa.public.key_length, NULL); bn_data = BN_bin2bn(data, data_len, NULL); bn_new_data = BN_new(); if(bn_n == NULL || bn_new_data == NULL || bn_data == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn/BN_new failed"); rc = 0; goto out; } if (BN_sub(bn_new_data, bn_n, bn_data) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn failed"); rc = 0; goto out; } if (BN_cmp(bn_data, bn_new_data) > 0) { if (BN_bn2binpad(bn_new_data, data, data_len)<= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "BN_bn2binpad failed"); rc = 0; goto out; } } rc = 1; out: if (bn_n != NULL) BN_free(bn_n); if (bn_data != NULL) BN_free(bn_data); if (bn_new_data != NULL) BN_free(bn_new_data); return rc; } static int ibmca_signature_rsa_verify_x931_post_process( struct ibmca_op_ctx *ctx, unsigned char *data, size_t data_len) { int rc = 0; BIGNUM *bn_n = NULL, *bn_sig = NULL; if ((data[data_len - 1] & 0xf) != 12) { bn_n = BN_bin2bn(ctx->key->rsa.public.modulus, ctx->key->rsa.public.key_length, NULL); bn_sig = BN_bin2bn(data, data_len, NULL); if (bn_n == NULL || bn_sig == NULL || BN_sub(bn_sig, bn_n, bn_sig) == 0 || BN_bn2binpad(bn_sig, data, data_len) <= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "BN_bin2bn/BN_sub/BN_bn2binpad failed"); goto out; } } rc = 1; out: if (bn_n != NULL) BN_free(bn_n); if (bn_sig != NULL) BN_free(bn_sig); return rc; } static int ibmca_signature_rsa_sign_fallback(struct ibmca_op_ctx *ctx, unsigned char *sig, size_t sigsize, const unsigned char *tbs, size_t tbslen) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; size_t siglen; int rc = 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu sig: %p sigsize: %lu", ctx, ctx->key, tbslen, sig, sigsize); pkey = ibmca_new_fallback_pkey(ctx->key); if (pkey == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(ctx->provctx, pkey, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_sign_init(pctx) != 1 || EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_NO_PADDING) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_sign_init/EVP_PKEY_CTX_set_rsa_padding failed"); goto out; } if (ibmca_check_fallback_provider(ctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } siglen = sigsize; if (EVP_PKEY_sign(pctx, sig, &siglen, tbs, tbslen) != 1 || siglen != sigsize) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_sign failed"); goto out; } rc = 1; out: if (pkey != NULL) EVP_PKEY_free(pkey); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); return rc; } static int ibmca_signature_rsa_sign(void *vctx, unsigned char *sig, size_t *siglen, size_t sigsize, const unsigned char *tbs, size_t tbslen) { struct ibmca_op_ctx *ctx = vctx; unsigned char diginfo[MAX_DIGINFO_SIZE + EVP_MAX_MD_SIZE]; unsigned char *enc_data; size_t enc_data_len, diginfo_len, rsa_size; int rc = 1; if (ctx == NULL || siglen == NULL || tbs == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu sigsize: %lu", ctx, ctx->key, tbslen, sigsize); if (ctx->key == NULL || (ctx->operation != EVP_PKEY_OP_SIGN && ctx->operation != EVP_PKEY_OP_SIGNCTX)) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "sign operation not initialized"); return 0; } rsa_size = ctx->key->get_max_param_size(ctx->key); *siglen = rsa_size; if (sig == NULL) /* size query */ goto out; if (sigsize < *siglen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); return 0; } if (ctx->rsa.signature.md != NULL) { if (tbslen != (size_t)EVP_MD_get_size(ctx->rsa.signature.md)) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid input data size: %lu expected: %d", tbslen, EVP_MD_get_size(ctx->rsa.signature.md)); return 0; } } ibmca_debug_op_ctx(ctx, "pad_mode: %d", ctx->rsa.signature.pad_mode); /* Allocate padding buffer, if required by padding mode */ switch (ctx->rsa.signature.pad_mode) { case RSA_NO_PADDING: if (tbslen != rsa_size) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid input length"); return 0; } enc_data = (unsigned char *)tbs; enc_data_len = tbslen; break; case RSA_PKCS1_PADDING: case RSA_PKCS1_PSS_PADDING: case RSA_X931_PADDING: if (ibmca_op_alloc_tbuf(ctx, rsa_size) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); return 0; } enc_data_len = ctx->tbuf_len; enc_data = ctx->tbuf; break; case RSA_PKCS1_OAEP_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid padding mode: %d", ctx->rsa.signature.pad_mode); return 0; } /* Perform padding */ switch (ctx->rsa.signature.pad_mode) { case RSA_NO_PADDING: rc = 1; break; case RSA_PKCS1_PADDING: if (ctx->rsa.signature.md != NULL) { rc = ibmca_rsa_build_digest_info(ctx->key->provctx, ctx->rsa.signature.md, tbs, tbslen, diginfo, sizeof(diginfo), &diginfo_len); if (rc == 0) break; rc = ibmca_rsa_add_pkcs1_padding(ctx->key->provctx, 1, diginfo, diginfo_len, enc_data, enc_data_len); } else { rc = ibmca_rsa_add_pkcs1_padding(ctx->key->provctx, 1, tbs, tbslen, enc_data, enc_data_len); } break; case RSA_X931_PADDING: if (ctx->rsa.signature.md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "X.931 padding requires a digest"); rc = 0; break; } rc = ibmca_rsa_add_x931_padding(ctx->key->provctx, tbs, tbslen, enc_data, enc_data_len, EVP_MD_get_type( ctx->rsa.signature.md)); break; case RSA_PKCS1_PSS_PADDING: rc = ibmca_signature_rsa_pss_check_params(ctx); if (rc == 0) break; rc = ibmca_rsa_add_pss_mgf1_padding(ctx->key->provctx, tbs, tbslen, enc_data, enc_data_len, ctx->rsa.signature.md, ctx->rsa.signature.mgf1_md, ctx->rsa.signature.saltlen); break; case RSA_PKCS1_OAEP_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: default: rc = 0; goto out; } if (rc == 0) goto out; /* Perform private key encrypt */ rc = ibmca_rsa_priv_with_blinding(ctx->key, enc_data, sig, rsa_size); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ibmca_asym_cipher_rsa_with_blinding failed"); rc = ibmca_signature_rsa_sign_fallback(ctx, sig, *siglen, enc_data, enc_data_len); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_signature_rsa_sign_fallback failed"); rc = 0; goto out; } } if (ctx->rsa.signature.pad_mode == RSA_X931_PADDING && ibmca_signature_rsa_sign_x931_post_process(ctx, sig, *siglen) == 0) { rc = 0; goto out; } rc = 1; out: if (ctx->tbuf != NULL) P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); ibmca_debug_op_ctx(ctx, "siglen: %lu rc: %d", *siglen, rc); return rc; } static int ibmca_signature_rsa_verify_fallback(struct ibmca_op_ctx *ctx, unsigned char *out, size_t outsize, const unsigned char *tbs, size_t tbslen) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; size_t outlen; int rc = 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu out: %p outsize: %lu", ctx, ctx->key, tbslen, out, outsize); pkey = ibmca_new_fallback_pkey(ctx->key); if (pkey == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey failed"); goto out; } pctx = ibmca_new_fallback_pkey_ctx(ctx->provctx, pkey, NULL); if (pctx == NULL) { ibmca_debug_op_ctx(ctx,"ERROR: ibmca_new_fallback_pkey_ctx failed"); goto out; } if (EVP_PKEY_verify_recover_init(pctx) != 1 || EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_NO_PADDING) != 1) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_verify_recover_init/EVP_PKEY_CTX_set_rsa_padding failed"); goto out; } if (ibmca_check_fallback_provider(ctx->provctx, pctx) != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_check_fallback_provider failed"); goto out; } outlen = outsize; if (EVP_PKEY_verify_recover(pctx, out, &outlen, tbs, tbslen) != 1 || outlen != outsize) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_PKEY_verify_recover failed"); goto out; } rc = 1; out: if (pkey != NULL) EVP_PKEY_free(pkey); if (pctx != NULL) EVP_PKEY_CTX_free(pctx); return rc; } static int ibmca_signature_rsa_verify(void *vctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { struct ibmca_op_ctx *ctx = vctx; unsigned char diginfo[MAX_DIGINFO_SIZE + EVP_MAX_MD_SIZE]; unsigned char *dec_data, *data = NULL; size_t dec_data_len, data_len = 0, diginfo_len, rsa_size; int rc = 1; if (ctx == NULL || sig == NULL || tbs == NULL) return -1; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu siglen: %lu", ctx, ctx->key, tbslen, siglen); if (ctx->key == NULL || (ctx->operation != EVP_PKEY_OP_VERIFY && ctx->operation != EVP_PKEY_OP_VERIFYCTX)) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "verify operation not initialized"); return -1; } rsa_size = ctx->key->get_max_param_size(ctx->key); if (siglen != rsa_size) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid signature length"); return -1; } ibmca_debug_op_ctx(ctx, "pad_mode: %d", ctx->rsa.signature.pad_mode); /* Allocate decryption buffer */ if (ibmca_op_alloc_tbuf(ctx, rsa_size) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); return -1; } dec_data_len = ctx->tbuf_len; dec_data = ctx->tbuf; /* Perform public key decrypt */ rc = ica_rsa_mod_expo(ctx->provctx->ica_adapter, sig, &ctx->key->rsa.public, dec_data); if (rc != 0) { ibmca_debug_op_ctx(ctx, "ica_rsa_mod_expo failed with: %s", strerror(rc)); rc = ibmca_signature_rsa_verify_fallback(ctx, dec_data, dec_data_len, sig, siglen); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_signature_rsa_verify_fallback failed"); rc = -1; goto out; } } /* Perform padding check */ switch (ctx->rsa.signature.pad_mode) { case RSA_NO_PADDING: data = dec_data; data_len = dec_data_len; rc = 1; break; case RSA_PKCS1_PADDING: if (ctx->rsa.signature.md != NULL) { rc = ibmca_rsa_build_digest_info(ctx->key->provctx, ctx->rsa.signature.md, tbs, tbslen, diginfo, sizeof(diginfo), &diginfo_len); if (rc == 0) break; tbs = diginfo; tbslen = diginfo_len; } rc = ibmca_rsa_check_pkcs1_padding_type1(ctx->key->provctx, dec_data, dec_data_len, NULL, dec_data_len, &data, &data_len); break; case RSA_X931_PADDING: if (ctx->rsa.signature.md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "X.931 padding requires a digest"); rc = 0; break; } rc = ibmca_signature_rsa_verify_x931_post_process(ctx, dec_data, dec_data_len); if (rc == 0) break; rc = ibmca_rsa_check_X931_padding(ctx->key->provctx, dec_data, dec_data_len, NULL, dec_data_len, &data, &data_len, EVP_MD_get_type( ctx->rsa.signature.md)); break; case RSA_PKCS1_PSS_PADDING: rc = ibmca_signature_rsa_pss_check_params(ctx); if (rc == 0) break; rc = ibmca_rsa_check_pss_mgf1_padding(ctx->key->provctx, dec_data, dec_data_len, tbs, tbslen, ctx->rsa.signature.md, ctx->rsa.signature.mgf1_md, ctx->rsa.signature.saltlen); break; case RSA_PKCS1_OAEP_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: default: rc = -1; break; } if (rc == 0) goto out; /* If data is NULL, padding check has already verified the signature */ if (data != NULL && data_len > 0) { if (data_len != tbslen || memcmp(data, tbs, tbslen) != 0) { put_error_op_ctx(ctx, IBMCA_ERR_SIGNATURE_BAD, "Bad signature"); rc = 0; goto out; } } rc = 1; out: P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); ibmca_debug_op_ctx(ctx, "rc: %d", rc); return rc; } static int ibmca_signature_rsa_verify_recover(void *vctx, unsigned char *rout, size_t *routlen, size_t routsize, const unsigned char *sig, size_t siglen) { struct ibmca_op_ctx *ctx = vctx; unsigned char diginfo[MAX_DIGINFO_SIZE + EVP_MAX_MD_SIZE]; unsigned char *dec_data, *msg; size_t dec_data_len, diginfo_len, msg_len, md_len, rsa_size; int rc = 1; if (ctx == NULL || routlen == NULL || sig == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p key: %p routsize: %lu siglen: %lu", ctx, ctx->key, routsize, siglen); if (ctx->key == NULL || ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "verify recover operation not initialized"); return 0; } rsa_size = ctx->key->get_max_param_size(ctx->key); *routlen = rsa_size; if (rout == NULL) /* size query */ goto out; if (routsize < *routlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Output buffer too small"); return 0; } if (siglen != rsa_size) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid signature length"); return 0; } ibmca_debug_op_ctx(ctx, "pad_mode: %d", ctx->rsa.signature.pad_mode); /* Allocate padding buffer, if required by padding mode */ switch (ctx->rsa.signature.pad_mode) { case RSA_NO_PADDING: dec_data = rout; dec_data_len = *routlen; break; case RSA_PKCS1_PADDING: case RSA_X931_PADDING: if (ibmca_op_alloc_tbuf(ctx, rsa_size) == 0) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_op_alloc_tbuf failed"); return 0; } dec_data_len = ctx->tbuf_len; dec_data = ctx->tbuf; break; case RSA_PKCS1_PSS_PADDING: case RSA_PKCS1_OAEP_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid padding mode: %d", ctx->rsa.signature.pad_mode); return 0; } /* Perform public key decrypt */ rc = ica_rsa_mod_expo(ctx->provctx->ica_adapter, sig, &ctx->key->rsa.public, dec_data); if (rc != 0) { ibmca_debug_op_ctx(ctx, "ica_rsa_mod_expo failed with: %s", strerror(rc)); rc = ibmca_signature_rsa_verify_fallback(ctx, dec_data, dec_data_len, sig, siglen); if (rc != 1) { ibmca_debug_op_ctx(ctx, "ERROR: ibmca_signature_rsa_verify_fallback failed"); rc = 0; goto out; } } /* Perform padding check */ switch (ctx->rsa.signature.pad_mode) { case RSA_NO_PADDING: rc = 1; break; case RSA_PKCS1_PADDING: if (ctx->rsa.signature.md != NULL) { rc = ibmca_rsa_check_pkcs1_padding_type1(ctx->key->provctx, dec_data, dec_data_len, NULL, *routlen, &msg, &msg_len); if (rc == 0) break; md_len = EVP_MD_get_size(ctx->rsa.signature.md); if (md_len <= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "EVP_MD_get_size failed"); break; } /* Rightmost md_len bytes of msg is the hash */ rc = ibmca_rsa_build_digest_info(ctx->key->provctx, ctx->rsa.signature.md, msg + msg_len - md_len, md_len, diginfo, sizeof(diginfo), &diginfo_len); if (rc == 0) break; if (diginfo_len != dec_data_len || memcmp(diginfo, dec_data, diginfo_len) != 0) { put_error_op_ctx(ctx, IBMCA_ERR_SIGNATURE_BAD, "Bad signature"); break; } if (routsize < md_len) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Output buffer size too small"); break; } memcpy(rout, msg + msg_len - md_len, md_len); *routlen = md_len; } else { rc = ibmca_rsa_check_pkcs1_padding_type1(ctx->key->provctx, dec_data, dec_data_len, rout, *routlen, NULL, routlen); } break; case RSA_X931_PADDING: if (ctx->rsa.signature.md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "X.931 padding requires a digest"); rc = 0; break; } rc = ibmca_signature_rsa_verify_x931_post_process(ctx, dec_data, dec_data_len); if (rc == 0) break; rc = ibmca_rsa_check_X931_padding(ctx->key->provctx, dec_data, dec_data_len, rout, *routlen, NULL, routlen, EVP_MD_get_type( ctx->rsa.signature.md)); break; case RSA_PKCS1_PSS_PADDING: case RSA_PKCS1_OAEP_PADDING: case RSA_PKCS1_WITH_TLS_PADDING: default: rc = 0; break; } if (rc == 0) goto out; rc = 1; out: P_CLEANSE(ctx->provctx, ctx->tbuf, ctx->tbuf_len); ibmca_debug_op_ctx(ctx, "routlen: %lu rc: %d", *routlen, rc); return rc; } static int ibmca_signature_rsa_digest_sign_init(void *vctx, const char *mdname, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_rsa_op_init(ctx, key, params, EVP_PKEY_OP_SIGNCTX, mdname); } static int ibmca_signature_rsa_digest_verify_init(void *vctx, const char *mdname, void *vkey, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; struct ibmca_key *key = vkey; return ibmca_signature_rsa_op_init(ctx, key, params, EVP_PKEY_OP_VERIFYCTX, mdname); } static int ibmca_signature_rsa_digest_signverify_update(void *vctx, const unsigned char *data, size_t datalen) { struct ibmca_op_ctx *ctx = vctx; return ibmca_digest_signverify_update(ctx, ctx->rsa.signature.md_ctx, data, datalen); } static int ibmca_signature_rsa_digest_sign_final(void *vctx, unsigned char *sig, size_t *siglen, size_t sigsize) { struct ibmca_op_ctx *ctx = vctx; return ibmca_digest_sign_final(ctx, ctx->rsa.signature.md_ctx, ibmca_signature_rsa_sign, sig, siglen, sigsize); } static int ibmca_signature_rsa_digest_verify_final(void *vctx, const unsigned char *sig, size_t siglen) { struct ibmca_op_ctx *ctx = vctx; return ibmca_digest_verify_final(ctx, ctx->rsa.signature.md_ctx, ibmca_signature_rsa_verify, sig, siglen); } static int ibmca_signature_rsa_get_algid_pss_parms(struct ibmca_op_ctx *ctx, int *ptype, void **param) { RSA_PSS_PARAMS *pss = NULL; X509_ALGOR *mgf_md_algo = NULL; ASN1_STRING *mgf_md_alfo_str = NULL; int rc = 0, saltlen; pss = RSA_PSS_PARAMS_new(); if (pss == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_MALLOC_FAILED, "RSA_PSS_PARAMS_new failed"); goto done; } switch (ctx->rsa.signature.saltlen) { case RSA_PSS_SALTLEN_DIGEST: saltlen = EVP_MD_get_size(ctx->rsa.signature.md); break; case RSA_PSS_SALTLEN_AUTO: case RSA_PSS_SALTLEN_MAX: saltlen = ctx->key->get_max_param_size(ctx->key) - EVP_MD_get_size(ctx->rsa.signature.md) - 2; if ((ctx->key->rsa.bits & 0x7) == 1) saltlen--; break; default: saltlen = ctx->rsa.signature.saltlen; if (saltlen < 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid saltlen value"); goto done; } } pss->saltLength = ASN1_INTEGER_new(); if (pss->saltLength == NULL || ASN1_INTEGER_set(pss->saltLength, saltlen) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "ASN1_INTEGER_new/ASN1_INTEGER_set failed"); goto done; } pss->hashAlgorithm = X509_ALGOR_new(); if (pss->hashAlgorithm == NULL || X509_ALGOR_set0(pss->hashAlgorithm, OBJ_nid2obj(EVP_MD_get_type(ctx->rsa.signature.md)), V_ASN1_NULL, NULL) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "X509_ALGOR_new/X509_ALGOR_set0 failed"); goto done; } mgf_md_algo = X509_ALGOR_new(); if (mgf_md_algo == NULL || X509_ALGOR_set0(mgf_md_algo, OBJ_nid2obj(EVP_MD_get_type( ctx->rsa.signature.mgf1_md != NULL ? ctx->rsa.signature.mgf1_md : ctx->rsa.signature.md)), V_ASN1_NULL, NULL) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "X509_ALGOR_new/X509_ALGOR_set0 failed"); goto done; } if (ASN1_item_pack(mgf_md_algo, ASN1_ITEM_rptr(X509_ALGOR), &mgf_md_alfo_str) == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "ASN1_item_pack failed"); goto done; } pss->maskGenAlgorithm = X509_ALGOR_new(); if (pss->maskGenAlgorithm == NULL || X509_ALGOR_set0(pss->maskGenAlgorithm, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, mgf_md_alfo_str) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "X509_ALGOR_new/X509_ALGOR_set0 failed"); goto done; } mgf_md_alfo_str = NULL; pss->maskHash = X509_ALGOR_new(); if (pss->maskHash == NULL || X509_ALGOR_set0(pss->maskHash, OBJ_nid2obj(EVP_MD_get_type( ctx->rsa.signature.mgf1_md != NULL ? ctx->rsa.signature.mgf1_md : ctx->rsa.signature.md)), V_ASN1_NULL, NULL) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "X509_ALGOR_new/X509_ALGOR_set0 failed"); goto done; } /* We always use the default trailer field, so we can omit it */ *ptype = V_ASN1_SEQUENCE; *param = ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), NULL); if (*param == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "ASN1_item_pack failed"); goto done; } rc = 1; done: if (mgf_md_alfo_str != NULL) ASN1_STRING_free(mgf_md_alfo_str); if (mgf_md_algo != NULL) X509_ALGOR_free(mgf_md_algo); RSA_PSS_PARAMS_free(pss); return rc; } static int ibmca_signature_rsa_get_algid(struct ibmca_op_ctx *ctx, OSSL_PARAM *p) { ASN1_OBJECT *oid = NULL; X509_ALGOR * algid = NULL; void *alg_param = NULL; int alg_ptype = V_ASN1_NULL; unsigned char *aid_buf = NULL; size_t aid_len; if (ctx->rsa.signature.md == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "No digest is set"); return 0; } switch (ctx->rsa.signature.pad_mode) { case RSA_PKCS1_PADDING: switch (EVP_MD_get_type(ctx->rsa.signature.md)) { case NID_sha1: oid = OBJ_nid2obj(NID_sha1WithRSAEncryption); break; case NID_sha224: oid = OBJ_nid2obj(NID_sha224WithRSAEncryption); break; case NID_sha256: oid = OBJ_nid2obj(NID_sha256WithRSAEncryption); break; case NID_sha384: oid = OBJ_nid2obj(NID_sha384WithRSAEncryption); break; case NID_sha512: oid = OBJ_nid2obj(NID_sha512WithRSAEncryption); break; case NID_sha512_224: oid = OBJ_nid2obj(NID_sha512_224WithRSAEncryption); break; case NID_sha512_256: oid = OBJ_nid2obj(NID_sha512_256WithRSAEncryption); break; case NID_sha3_224: oid = OBJ_nid2obj(NID_RSA_SHA3_224); break; case NID_sha3_256: oid = OBJ_nid2obj(NID_RSA_SHA3_256); break; case NID_sha3_384: oid = OBJ_nid2obj(NID_RSA_SHA3_384); break; case NID_sha3_512: oid = OBJ_nid2obj(NID_RSA_SHA3_512); break; default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "AlgorithmID not supported for digest '%s'", EVP_MD_get0_name(ctx->rsa.signature.md)); return 0; } break; case RSA_PKCS1_PSS_PADDING: if (ctx->key->type == EVP_PKEY_RSA_PSS) { oid = OBJ_nid2obj(NID_rsassaPss); if (ibmca_signature_rsa_get_algid_pss_parms(ctx, &alg_ptype, &alg_param) == 0) return 0; } else { oid = OBJ_nid2obj(NID_rsaEncryption); } break; default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "AlgorithmID not supported for pad mode %d", ctx->rsa.signature.pad_mode); return 0; } algid = X509_ALGOR_new(); if (algid == NULL || X509_ALGOR_set0(algid, oid, alg_ptype, alg_param) == 0 || (aid_len = i2d_X509_ALGOR(algid, &aid_buf)) <= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "X509_ALGOR_new/X509_ALGOR_set0/i2d_X509_ALGOR failed"); X509_ALGOR_free(algid); return 0; } if (OSSL_PARAM_set_octet_string(p, aid_buf, aid_len) == 0) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "Failed to return param '%s'", OSSL_SIGNATURE_PARAM_ALGORITHM_ID); P_FREE(ctx->provctx, aid_buf); X509_ALGOR_free(algid); return 0; } P_FREE(ctx->provctx, aid_buf); X509_ALGOR_free(algid); ibmca_debug_op_ctx(ctx, "param '%s': [octet string] (%lu bytes)", OSSL_SIGNATURE_PARAM_ALGORITHM_ID, aid_len); return 1; } static int ibmca_signature_rsa_get_ctx_params(void *vctx, OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; OSSL_PARAM *p; const char *name = NULL; int i, rc; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_SIGNATURE_PARAM_ALGORITHM_ID */ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID); if (p != NULL && ibmca_signature_rsa_get_algid(ctx, p) == 0) return 0; /* OSSL_SIGNATURE_PARAM_PAD_MODE */ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE); if (p != NULL) { switch (p->data_type) { case OSSL_PARAM_INTEGER: rc = ibmca_param_build_set_int(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_PAD_MODE, ctx->rsa.signature.pad_mode); if (rc == 0) return 0; break; case OSSL_PARAM_UTF8_STRING: for (i = 0; ibmca_rsa_padding_table[i].id != 0; i++) { if ((int)ibmca_rsa_padding_table[i].id == ctx->rsa.signature.pad_mode) { name = ibmca_rsa_padding_table[i].ptr; break; } } if (name == NULL) { put_error_op_ctx(ctx, IBMCA_ERR_INTERNAL_ERROR, "Invalid RSA padding mode: %d", ctx->rsa.signature.pad_mode); return 0; } rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_PAD_MODE, name); if (rc == 0) return 0; break; default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid param type for: '%s'", OSSL_SIGNATURE_PARAM_PAD_MODE); return 0; } } /* OSSL_SIGNATURE_PARAM_DIGEST */ if (ctx->rsa.signature.md != NULL) name = EVP_MD_get0_name(ctx->rsa.signature.md); else name = ""; rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_DIGEST, name); if (rc == 0) return 0; /* OSSL_SIGNATURE_PARAM_MGF1_DIGEST */ if (ctx->rsa.signature.mgf1_md != NULL) name = EVP_MD_get0_name(ctx->rsa.signature.mgf1_md); else if (ctx->rsa.signature.md != NULL) name = EVP_MD_get0_name(ctx->rsa.signature.md); else name = ""; rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST, name); if (rc == 0) return 0; /* OSSL_SIGNATURE_PARAM_PSS_SALTLEN */ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN); if (p != NULL) { if (p->data_type == OSSL_PARAM_INTEGER) { rc = ibmca_param_build_set_int(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN, ctx->rsa.signature.saltlen); if (rc == 0) return 0; } else if (p->data_type == OSSL_PARAM_UTF8_STRING) { switch (ctx->rsa.signature.saltlen) { case RSA_PSS_SALTLEN_DIGEST: rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN, OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST); break; case RSA_PSS_SALTLEN_MAX: rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN, OSSL_PKEY_RSA_PSS_SALT_LEN_MAX); break; case RSA_PSS_SALTLEN_AUTO: rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO); break; #ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: rc = ibmca_param_build_set_utf8(ctx->provctx, NULL, params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX); break; #endif default: rc = snprintf(p->data, p->data_size, "%d", ctx->rsa.signature.saltlen); if (rc <= 0) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Failed to return param '%s'", OSSL_SIGNATURE_PARAM_PSS_SALTLEN); return 0; } p->return_size = rc; ibmca_debug_op_ctx(ctx, "param '%s': '%s'", OSSL_SIGNATURE_PARAM_PSS_SALTLEN, p->data); break; } if (rc <= 0) return 0; } } return 1; } static int ibmca_signature_rsa_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; const OSSL_PARAM *p; const char *name, *props = NULL; int i, rc, saltlen; if (ctx == NULL) return 0; ibmca_debug_op_ctx(ctx, "ctx: %p", ctx); for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_op_ctx(ctx, "param: %s", p->key); /* OSSL_SIGNATURE_PARAM_PAD_MODE */ p = OSSL_PARAM_locate_const((OSSL_PARAM *)params, OSSL_SIGNATURE_PARAM_PAD_MODE); if (p != NULL) { switch (p->data_type) { case OSSL_PARAM_INTEGER: rc = ibmca_param_get_int(ctx->provctx, params, OSSL_SIGNATURE_PARAM_PAD_MODE, &ctx->rsa.signature.pad_mode); if (rc == 0) return 0; break; case OSSL_PARAM_UTF8_STRING: rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_SIGNATURE_PARAM_PAD_MODE, &name); if (rc == 1) { ctx->rsa.signature.pad_mode = 0; for (i = 0; ibmca_rsa_padding_table[i].id != 0; i++) { if (strcmp(name, ibmca_rsa_padding_table[i].ptr) == 0) { ctx->rsa.signature.pad_mode = ibmca_rsa_padding_table[i].id; break; } } } break; default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid param type for: '%s'", OSSL_SIGNATURE_PARAM_PAD_MODE); return 0; } switch (ctx->rsa.signature.pad_mode) { case RSA_NO_PADDING: case RSA_PKCS1_PADDING: case RSA_X931_PADDING: if (ctx->key->type == EVP_PKEY_RSA_PSS) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Padding mode %d not allowed with RSA-PSS", ctx->rsa.signature.pad_mode); return 0; } break; case RSA_PKCS1_PSS_PADDING: if (ctx->operation != EVP_PKEY_OP_SIGN && ctx->operation != EVP_PKEY_OP_SIGNCTX && ctx->operation != EVP_PKEY_OP_VERIFY && ctx->operation != EVP_PKEY_OP_VERIFYCTX) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "PSS padding only allowed for sign and verify operations"); return 0; } /* Setup md defaults if not already set */ if (ctx->rsa.signature.md == NULL && ibmca_signature_rsa_set_md(ctx, NULL, ctx->rsa.signature.pss.digest_nid, NULL) == 0) return 0; if (ctx->rsa.signature.mgf1_md == NULL && ctx->rsa.signature.pss.mgf_digest_nid != ctx->rsa.signature.pss.digest_nid && ibmca_signature_rsa_set_mgf1_md(ctx, NULL, ctx->rsa.signature.pss.mgf_digest_nid, NULL) == 0) return 0; break; case RSA_PKCS1_OAEP_PADDING: /* OAEP is for encrypt/decrypt only */ case RSA_PKCS1_WITH_TLS_PADDING: /* TLS is for decrypt only */ default: put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid RSA padding mode: %d", ctx->rsa.signature.pad_mode); return 0; } } /* OSSL_SIGNATURE_PARAM_PROPERTIES */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_SIGNATURE_PARAM_PROPERTIES, &props); if (rc == 0) return 0; /* OSSL_SIGNATURE_PARAM_DIGEST */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_SIGNATURE_PARAM_DIGEST, &name); if (rc == 0) return 0; if (rc > 0 && ibmca_signature_rsa_set_md(ctx, name, 0, props) == 0) return 0; /* OSSL_SIGNATURE_PARAM_PSS_SALTLEN */ p = OSSL_PARAM_locate_const((OSSL_PARAM *)params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN); if (p != NULL) { switch (p->data_type) { case OSSL_PARAM_INTEGER: rc = ibmca_param_get_int(ctx->provctx, params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN, &saltlen); if (rc == 0) return 0; break; case OSSL_PARAM_UTF8_STRING: if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST) == 0) saltlen = RSA_PSS_SALTLEN_DIGEST; else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_MAX) == 0) saltlen = RSA_PSS_SALTLEN_MAX; else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0) saltlen = RSA_PSS_SALTLEN_AUTO; #ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX) == 0) saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; #endif else saltlen = atoi(p->data); ibmca_debug_op_ctx(ctx, "param '%s': '%s'", OSSL_SIGNATURE_PARAM_PSS_SALTLEN, p->data); break; default: return 0; } #ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX if (saltlen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { #else if (saltlen < RSA_PSS_SALTLEN_MAX) { #endif put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Invalid salt length: %d", saltlen); return 0; } if (ctx->key->type == EVP_PKEY_RSA_PSS && ctx->rsa.signature.pss.restricted) { switch (saltlen) { case RSA_PSS_SALTLEN_AUTO: #ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: #endif if (ctx->operation == EVP_PKEY_OP_VERIFY) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Cannot use auto-detected salt length"); return 0; } break; case RSA_PSS_SALTLEN_DIGEST: if (ctx->rsa.signature.md != NULL && EVP_MD_get_size(ctx->rsa.signature.md) < ctx->rsa.signature.pss.saltlen ) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Saltlen should be >= %d, but digest size is %d", ctx->rsa.signature.pss.saltlen, EVP_MD_get_size( ctx->rsa.signature.md)); return 0; } break; default: if (saltlen >= 0 && saltlen < ctx->rsa.signature.pss.saltlen) { put_error_op_ctx(ctx, IBMCA_ERR_INVALID_PARAM, "Saltlen should be more than %d, but is %d", ctx->rsa.signature.pss.saltlen, saltlen); return 0; } } } ctx->rsa.signature.saltlen = saltlen; ibmca_debug_op_ctx(ctx, "saltlen: %d", saltlen); } /* OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, &props); if (rc == 0) return 0; /* OSSL_SIGNATURE_PARAM_MGF1_DIGEST */ rc = ibmca_param_get_utf8(ctx->provctx, params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST, &name); if (rc == 0) return 0; if (rc > 0 && ibmca_signature_rsa_set_mgf1_md(ctx, name, 0, props) == 0) return 0; return 1; } static const OSSL_PARAM ibmca_signature_rsa_gettable_params[] = { OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_signature_rsa_gettable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p; ibmca_debug_ctx(provctx, "ctx: %p", ctx); for (p = ibmca_signature_rsa_gettable_params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return ibmca_signature_rsa_gettable_params; } static const OSSL_PARAM ibmca_signature_rsa_settable_params[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM ibmca_signature_rsa_settable_params_no_digest[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), OSSL_PARAM_END }; static const OSSL_PARAM *ibmca_signature_rsa_settable_ctx_params( void *vctx, void *vprovctx) { const struct ibmca_op_ctx *ctx = vctx; const struct ibmca_prov_ctx *provctx = vprovctx; const OSSL_PARAM *p, *params; ibmca_debug_ctx(provctx, "ctx: %p", ctx); if (ctx->rsa.signature.set_md_allowed) params = ibmca_signature_rsa_settable_params; else params = ibmca_signature_rsa_settable_params_no_digest; for (p = params; p != NULL && p->key != NULL; p++) ibmca_debug_ctx(provctx, "param: %s", p->key); return params; } static int ibmca_signature_rsa_get_ctx_md_params(void *vctx, OSSL_PARAM *params) { struct ibmca_op_ctx *ctx = vctx; return ibmca_get_ctx_md_params(ctx, ctx->rsa.signature.md_ctx, params); } static int ibmca_signature_rsa_set_ctx_md_params(void *vctx, const OSSL_PARAM params[]) { struct ibmca_op_ctx *ctx = vctx; return ibmca_set_ctx_md_params(ctx, ctx->rsa.signature.md_ctx, params); } static const OSSL_PARAM *ibmca_signature_rsa_gettable_ctx_md_params(void *vctx) { struct ibmca_op_ctx *ctx = vctx; return ibmca_gettable_ctx_md_params(ctx, ctx->rsa.signature.md); } static const OSSL_PARAM *ibmca_signature_rsa_settable_ctx_md_params(void *vctx) { struct ibmca_op_ctx *ctx = vctx; return ibmca_settable_ctx_md_params(ctx, ctx->rsa.signature.md); } static const OSSL_DISPATCH ibmca_rsa_signature_functions[] = { /* Signature context constructor, destructor */ { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ibmca_signature_rsa_newctx }, { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ibmca_op_freectx }, { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ibmca_op_dupctx }, /* Signing */ { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))ibmca_signature_rsa_sign_init }, { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ibmca_signature_rsa_sign }, /* Verifying */ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))ibmca_signature_rsa_verify_init }, { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))ibmca_signature_rsa_verify }, /* Verify recover */ { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, (void (*)(void))ibmca_signature_rsa_verifyrecover_init }, { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, (void (*)(void))ibmca_signature_rsa_verify_recover }, /* Digest Sign */ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, (void (*)(void))ibmca_signature_rsa_digest_sign_init }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, (void (*)(void))ibmca_signature_rsa_digest_signverify_update }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, (void (*)(void))ibmca_signature_rsa_digest_sign_final }, /* Digest Verify */ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, (void (*)(void))ibmca_signature_rsa_digest_verify_init }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, (void (*)(void))ibmca_signature_rsa_digest_signverify_update }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, (void (*)(void))ibmca_signature_rsa_digest_verify_final }, /* Signature parameters */ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))ibmca_signature_rsa_get_ctx_params }, { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void (*)(void))ibmca_signature_rsa_gettable_ctx_params }, { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))ibmca_signature_rsa_set_ctx_params }, { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, (void (*)(void))ibmca_signature_rsa_settable_ctx_params }, /* MD parameters */ { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, (void (*)(void))ibmca_signature_rsa_get_ctx_md_params }, { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, (void (*)(void))ibmca_signature_rsa_gettable_ctx_md_params }, { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, (void (*)(void))ibmca_signature_rsa_set_ctx_md_params }, { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, (void (*)(void))ibmca_signature_rsa_settable_ctx_md_params }, { 0, NULL } }; const OSSL_ALGORITHM ibmca_rsa_signature[] = { { "RSA:rsaEncryption:1.2.840.113549.1.1.1", NULL, ibmca_rsa_signature_functions, "IBMCA RSA signature implementation" }, { NULL, NULL, NULL, NULL } }; openssl-ibmca-2.4.1/src/provider/rsa_sup_mul.c000066400000000000000000000457061450276407300214140ustar00rootroot00000000000000/* * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2023 International Business Machines Corp. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html * * Copied from OpenSSL crypto/bn/rsa_sup_mul.c and modified to fit to * the providers environment. * * Changes include: * - The intermediate message and the modulus are supplied as byte arrays * instead of BIGNUMs. The code has been adjusted to handle byte arrays as * input. * - Remove parameters 'BN_CTX ctx' and 'BN_BLINDING *blinding' since they are * not used. * - Includes have been adjusted to only include external OpenSSL headers. * - Remove access to internal fields of BN_BLINDING. * - Remove access to internal fields of BIGNUM. Function BN_to_limb() is * replaced by BN_bn2binpad(). Note that the only BIGNUM is containing the * unblinding factor. The message (and the modulus) are passed in in byte * arrays, and thus do not need to be converted. * - This provider only works on Linux on IBM Z, and it's big endian and 64 bit. */ #include #include #include #include #include #include #include #include "constant_time.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #define DECLARE_IS_ENDIAN #define IS_LITTLE_ENDIAN 0 #define IS_BIG_ENDIAN 1 # ifndef INT128_MAX # if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 typedef __int128_t int128_t; typedef __uint128_t uint128_t; # define INT128_MIN __MININT__(int128_t) # define INT128_MAX __MAXINT__(int128_t) # define UINT128_MAX __MAXUINT__(uint128_t) # endif # endif # if BN_BYTES == 8 typedef uint64_t limb_t; # if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 typedef uint128_t limb2_t; # define HAVE_LIMB2_T # endif # define LIMB_BIT_SIZE 64 # define LIMB_BYTE_SIZE 8 # else # error "Not supported" # endif static inline void memcpy_r_allign(void *dest, int dest_bs, const void *src, int src_bs, int size) { memcpy((unsigned char *)dest + (dest_bs - size), (unsigned char *)src + (src_bs - size), size); } /* * For multiplication we're using schoolbook multiplication, * so if we have two numbers, each with 6 "digits" (words) * the multiplication is calculated as follows: * A B C D E F * x I J K L M N * -------------- * N*F * N*E * N*D * N*C * N*B * N*A * M*F * M*E * M*D * M*C * M*B * M*A * L*F * L*E * L*D * L*C * L*B * L*A * K*F * K*E * K*D * K*C * K*B * K*A * J*F * J*E * J*D * J*C * J*B * J*A * I*F * I*E * I*D * I*C * I*B * + I*A * ========================== * N*B N*D N*F * + N*A N*C N*E * + M*B M*D M*F * + M*A M*C M*E * + L*B L*D L*F * + L*A L*C L*E * + K*B K*D K*F * + K*A K*C K*E * + J*B J*D J*F * + J*A J*C J*E * + I*B I*D I*F * + I*A I*C I*E * * 1+1 1+3 1+5 * 1+0 1+2 1+4 * 0+1 0+3 0+5 * 0+0 0+2 0+4 * * 0 1 2 3 4 5 6 * which requires n^2 multiplications and 2n full length additions * as we can keep every other result of limb multiplication in two separate * limbs */ #if defined HAVE_LIMB2_T static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b) { limb2_t t; /* * this is idiomatic code to tell compiler to use the native mul * those three lines will actually compile to single instruction */ t = (limb2_t)a * b; *hi = t >> LIMB_BIT_SIZE; *lo = (limb_t)t; } #elif (BN_BYTES == 8) && (defined _MSC_VER) # if defined(_M_X64) /* * on x86_64 (x64) we can use the _umul128 intrinsic to get one `mul` * instruction to get both high and low 64 bits of the multiplication. * https://learn.microsoft.com/en-us/cpp/intrinsics/umul128?view=msvc-140 */ #include #pragma intrinsic(_umul128) static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b) { *lo = _umul128(a, b, hi); } # elif defined(_M_ARM64) || defined (_M_IA64) /* * We can't use the __umulh() on x86_64 as then msvc generates two `mul` * instructions; so use this more portable intrinsic on platforms that * don't support _umul128 (like aarch64 (ARM64) or ia64) * https://learn.microsoft.com/en-us/cpp/intrinsics/umulh?view=msvc-140 */ #include static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b) { *lo = a * b; *hi = __umulh(a, b); } # else # error Only x64, ARM64 and IA64 supported. # endif /* defined(_M_X64) */ #else /* * if the compiler doesn't have either a 128bit data type nor a "return * high 64 bits of multiplication" */ static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b) { limb_t a_low = (limb_t)(uint32_t)a; limb_t a_hi = a >> 32; limb_t b_low = (limb_t)(uint32_t)b; limb_t b_hi = b >> 32; limb_t p0 = a_low * b_low; limb_t p1 = a_low * b_hi; limb_t p2 = a_hi * b_low; limb_t p3 = a_hi * b_hi; uint32_t cy = (uint32_t)(((p0 >> 32) + (uint32_t)p1 + (uint32_t)p2) >> 32); *lo = p0 + (p1 << 32) + (p2 << 32); *hi = p3 + (p1 >> 32) + (p2 >> 32) + cy; } #endif /* add two limbs with carry in, return carry out */ static ossl_inline limb_t _add_limb(limb_t *ret, limb_t a, limb_t b, limb_t carry) { limb_t carry1, carry2, t; /* * `c = a + b; if (c < a)` is idiomatic code that makes compilers * use add with carry on assembly level */ *ret = a + carry; if (*ret < a) carry1 = 1; else carry1 = 0; t = *ret; *ret = t + b; if (*ret < t) carry2 = 1; else carry2 = 0; return carry1 + carry2; } /* * add two numbers of the same size, return overflow * * add a to b, place result in ret; all arrays need to be n limbs long * return overflow from addition (0 or 1) */ static ossl_inline limb_t add(limb_t *ret, limb_t *a, limb_t *b, size_t n) { limb_t c = 0; ossl_ssize_t i; for(i = n - 1; i > -1; i--) c = _add_limb(&ret[i], a[i], b[i], c); return c; } /* * return number of limbs necessary for temporary values * when multiplying numbers n limbs large */ static ossl_inline size_t mul_limb_numb(size_t n) { return 2 * n * 2; } /* * multiply two numbers of the same size * * multiply a by b, place result in ret; a and b need to be n limbs long * ret needs to be 2*n limbs long, tmp needs to be mul_limb_numb(n) limbs * long */ static void limb_mul(limb_t *ret, limb_t *a, limb_t *b, size_t n, limb_t *tmp) { limb_t *r_odd, *r_even; size_t i, j, k; r_odd = tmp; r_even = &tmp[2 * n]; memset(ret, 0, 2 * n * sizeof(limb_t)); for (i = 0; i < n; i++) { for (k = 0; k < i + n + 1; k++) { r_even[k] = 0; r_odd[k] = 0; } for (j = 0; j < n; j++) { /* * place results from even and odd limbs in separate arrays so that * we don't have to calculate overflow every time we get individual * limb multiplication result */ if (j % 2 == 0) _mul_limb(&r_even[i + j], &r_even[i + j + 1], a[i], b[j]); else _mul_limb(&r_odd[i + j], &r_odd[i + j + 1], a[i], b[j]); } /* * skip the least significant limbs when adding multiples of * more significant limbs (they're zero anyway) */ add(ret, ret, r_even, n + i + 1); add(ret, ret, r_odd, n + i + 1); } } /* modifies the value in place by performing a right shift by one bit */ static ossl_inline void rshift1(limb_t *val, size_t n) { limb_t shift_in = 0, shift_out = 0; size_t i; for (i = 0; i < n; i++) { shift_out = val[i] & 1; val[i] = shift_in << (LIMB_BIT_SIZE - 1) | (val[i] >> 1); shift_in = shift_out; } } /* extend the LSB of flag to all bits of limb */ static ossl_inline limb_t mk_mask(limb_t flag) { flag |= flag << 1; flag |= flag << 2; flag |= flag << 4; flag |= flag << 8; flag |= flag << 16; #if (LIMB_BYTE_SIZE == 8) flag |= flag << 32; #endif return flag; } /* * copy from either a or b to ret based on flag * when flag == 0, then copies from b * when flag == 1, then copies from a */ static ossl_inline void cselect(limb_t flag, limb_t *ret, limb_t *a, limb_t *b, size_t n) { /* * would be more efficient with non volatile mask, but then gcc * generates code with jumps */ volatile limb_t mask; size_t i; mask = mk_mask(flag); for (i = 0; i < n; i++) { #if (LIMB_BYTE_SIZE == 8) ret[i] = constant_time_select_64(mask, a[i], b[i]); #else ret[i] = constant_time_select_32(mask, a[i], b[i]); #endif } } static limb_t _sub_limb(limb_t *ret, limb_t a, limb_t b, limb_t borrow) { limb_t borrow1, borrow2, t; /* * while it doesn't look constant-time, this is idiomatic code * to tell compilers to use the carry bit from subtraction */ *ret = a - borrow; if (*ret > a) borrow1 = 1; else borrow1 = 0; t = *ret; *ret = t - b; if (*ret > t) borrow2 = 1; else borrow2 = 0; return borrow1 + borrow2; } /* * place the result of a - b into ret, return the borrow bit. * All arrays need to be n limbs long */ static limb_t sub(limb_t *ret, limb_t *a, limb_t *b, size_t n) { limb_t borrow = 0; ossl_ssize_t i; for (i = n - 1; i > -1; i--) borrow = _sub_limb(&ret[i], a[i], b[i], borrow); return borrow; } /* return the number of limbs necessary to allocate for the mod() tmp operand */ static ossl_inline size_t mod_limb_numb(size_t anum, size_t modnum) { return (anum + modnum) * 3; } /* * calculate a % mod, place the result in ret * size of a is defined by anum, size of ret and mod is modnum, * size of tmp is returned by mod_limb_numb() */ static void mod(limb_t *ret, limb_t *a, size_t anum, limb_t *mod, size_t modnum, limb_t *tmp) { limb_t *atmp, *modtmp, *rettmp; limb_t res; size_t i; memset(tmp, 0, mod_limb_numb(anum, modnum) * LIMB_BYTE_SIZE); atmp = tmp; modtmp = &tmp[anum + modnum]; rettmp = &tmp[(anum + modnum) * 2]; for (i = modnum; i 0; i--, rp--) { v = _mul_add_limb(rp, mod, modnum, rp[modnum-1] * ni0, tmp2); v = v + carry + rp[-1]; carry |= (v != rp[-1]); carry &= (v <= rp[-1]); rp[-1] = v; } /* perform the final reduction by mod... */ carry -= sub(ret, rp, mod, modnum); /* ...conditionally */ cselect(carry, ret, rp, ret, modnum); } #if LIMB_BYTE_SIZE == 8 static ossl_inline uint64_t be64(uint64_t host) { uint64_t big = 0; DECLARE_IS_ENDIAN; if (!IS_LITTLE_ENDIAN) return host; big |= (host & 0xff00000000000000) >> 56; big |= (host & 0x00ff000000000000) >> 40; big |= (host & 0x0000ff0000000000) >> 24; big |= (host & 0x000000ff00000000) >> 8; big |= (host & 0x00000000ff000000) << 8; big |= (host & 0x0000000000ff0000) << 24; big |= (host & 0x000000000000ff00) << 40; big |= (host & 0x00000000000000ff) << 56; return big; } #else /* Not all platforms have htobe32(). */ static ossl_inline uint32_t be32(uint32_t host) { uint32_t big = 0; DECLARE_IS_ENDIAN; if (!IS_LITTLE_ENDIAN) return host; big |= (host & 0xff000000) >> 24; big |= (host & 0x00ff0000) >> 8; big |= (host & 0x0000ff00) << 8; big |= (host & 0x000000ff) << 24; return big; } #endif /* * We assume that intermediate and unblind are used similar to * BN_BLINDING_invert_ex() arguments. * to_mod is RSA modulus. * buf and num is the serialization buffer and its length. * num is always the RSA modulus size. * * Here we use classic/Montgomery multiplication and modulo. After the calculation finished * we serialize the new structure instead of BIGNUMs taking endianness into account. */ int ossl_bn_rsa_do_unblind(const unsigned char *intermediate, const BIGNUM *unblind, const unsigned char *to_mod, unsigned char *buf, int num, BN_MONT_CTX *m_ctx, BN_ULONG n0) { limb_t *l_im = NULL, *l_mul = NULL, *l_mod = NULL; limb_t *l_ret = NULL, *l_tmp = NULL, l_buf; size_t l_im_count = 0, l_mul_count = 0, l_size = 0, l_mod_count = 0; size_t l_tmp_count = 0; int ret = 0; size_t i; unsigned char *tmp; l_im_count = (num + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; l_mul_count = (BN_num_bytes(unblind) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; l_mod_count = (num + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; l_size = l_im_count > l_mul_count ? l_im_count : l_mul_count; if (l_size * LIMB_BYTE_SIZE == (size_t)num) l_im = (limb_t *)intermediate; else l_im = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE); l_mul = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE); if (l_mod_count * LIMB_BYTE_SIZE == (size_t)num) l_mod = (limb_t *)to_mod; else l_mod = OPENSSL_zalloc(l_mod_count * LIMB_BYTE_SIZE); if ((l_im == NULL) || (l_mul == NULL) || (l_mod == NULL)) goto err; if (l_im != (limb_t *)intermediate) memcpy_r_allign(l_im, l_size * LIMB_BYTE_SIZE, intermediate, num, num); BN_bn2binpad(unblind, (unsigned char *)l_mul, l_size * LIMB_BYTE_SIZE); if (l_mod != (limb_t *)to_mod) memcpy_r_allign(l_mod, l_mod_count * LIMB_BYTE_SIZE, to_mod, num, num); l_ret = OPENSSL_malloc(2 * l_size * LIMB_BYTE_SIZE); if (m_ctx != NULL) { l_tmp_count = mul_limb_numb(l_size) > mod_montgomery_limb_numb(l_mod_count) ? mul_limb_numb(l_size) : mod_montgomery_limb_numb(l_mod_count); l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE); } else { l_tmp_count = mul_limb_numb(l_size) > mod_limb_numb(2 * l_size, l_mod_count) ? mul_limb_numb(l_size) : mod_limb_numb(2 * l_size, l_mod_count); l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE); } if ((l_ret == NULL) || (l_tmp == NULL)) goto err; if (m_ctx != NULL) { limb_mul(l_ret, l_im, l_mul, l_size, l_tmp); mod_montgomery(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count, n0, l_tmp); } else { limb_mul(l_ret, l_im, l_mul, l_size, l_tmp); mod(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count, l_tmp); } memset(buf, 0, num); tmp = buf; for (i = 0; i < l_mod_count; i++) { #if LIMB_BYTE_SIZE == 8 l_buf = be64(l_ret[i]); #else l_buf = be32(l_ret[i]); #endif if (i == 0) { int delta = LIMB_BYTE_SIZE - ((l_mod_count * LIMB_BYTE_SIZE) - num); memcpy(tmp, ((char *)&l_buf) + LIMB_BYTE_SIZE - delta, delta); tmp += delta; } else { memcpy(tmp, &l_buf, LIMB_BYTE_SIZE); tmp += LIMB_BYTE_SIZE; } } ret = num; err: if (l_im != (limb_t *)intermediate) OPENSSL_free(l_im); OPENSSL_free(l_mul); if (l_mod != (limb_t *)to_mod) OPENSSL_free(l_mod); OPENSSL_free(l_tmp); OPENSSL_free(l_ret); return ret; } #pragma GCC diagnostic pop openssl-ibmca-2.4.1/test/000077500000000000000000000000001450276407300152415ustar00rootroot00000000000000openssl-ibmca-2.4.1/test/Makefile.am000066400000000000000000000001351450276407300172740ustar00rootroot00000000000000SUBDIRS= if IBMCA_ENGINE SUBDIRS += engine endif if IBMCA_PROVIDER SUBDIRS += provider endif openssl-ibmca-2.4.1/test/engine/000077500000000000000000000000001450276407300165065ustar00rootroot00000000000000openssl-ibmca-2.4.1/test/engine/3des-cbc-test.pl000077500000000000000000000001371450276407300214070ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ede3-cbc", 24, 8); openssl-ibmca-2.4.1/test/engine/3des-cfb-test.pl000077500000000000000000000001371450276407300214120ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ede3-cfb", 24, 8); openssl-ibmca-2.4.1/test/engine/3des-ecb-test.pl000077500000000000000000000002661450276407300214140ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; # No iv needed, but openssl app version 3 somehow requires one... test::cipher("des-ede3", 24, test::osslversion3 ? 8 : 0); openssl-ibmca-2.4.1/test/engine/3des-ofb-test.pl000077500000000000000000000001371450276407300214260ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("des-ede3-ofb", 24, 8); openssl-ibmca-2.4.1/test/engine/Makefile.am000066400000000000000000000043431450276407300205460ustar00rootroot00000000000000TESTS_CIPHERS = \ 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 if FULL_LIBICA TESTS_CIPHERS_EXEC=${TESTS_CIPHERS} endif TESTS_PERL = \ rsa2k.pl \ rsa4k.pl \ rsa8k.pl \ rsa16k.pl \ dsa2k.pl \ dsa4k.pl \ dsa8k.pl \ dsamax.pl TESTS = ${TESTS_PERL} \ ${TESTS_CIPHERS_EXEC} \ loadtest \ loadtest-ec \ threadtest \ libica-link.sh \ eckey \ enginectrl check_PROGRAMS = loadtest loadtest-ec threadtest eckey enginectrl check_SCRIPTS = libica-link.sh loadtest_SOURCES = loadtest.c loadtest_LDADD = -lssl -lcrypto loadtest_ec_SOURCES = loadtest-ec.c loadtest_ec_LDADD = -lssl -lcrypto threadtest_SOURCES = threadtest.c threadtest_LDADD = -lcrypto -lpthread eckey_SOURCES = eckey.c eckey_LDADD = -lcrypto enginectrl_SOURCES = enginectrl.c enginectrl_LDADD = -lcrypto -ldl AM_TESTS_ENVIRONMENT = export IBMCA_TEST_PATH=${top_builddir}/src/engine/.libs/ibmca.so IBMCA_OPENSSL_TEST_CONF=${srcdir}/openssl-test.cnf IBMCA_OPENSSL_TEST_NOINIT_CONF=${srcdir}/openssl-test-noinit.cnf PERL5LIB=${srcdir}; EXTRA_DIST = ${TESTS_PERL} ${TESTS_CIPHERS} test.pm openssl-test.cnf \ openssl-test-noinit.cnf dsa2k.key dsa2k_pub.key dsa4k.key \ dsa4k_pub.key dsa8k.key dsa8k_pub.key dsamax.key dsamax_pub.key \ rsa2k.key rsa4k.key rsa8k.key rsa16k.key dsaparam2k.key \ dsaparam4k.key dsaparam8k.key dsaparammax.key libica-link.sh: @echo '#!/bin/bash' > libica-link.sh @echo "IBMCA_SO=\"${abs_top_builddir}/src/engine/.libs/ibmca.so\"" > libica-link.sh @echo "if ldd \"\$${IBMCA_SO}\" | grep -q libica; then" >> libica-link.sh @echo " echo \"Linking against libica detected\"" >> libica-link.sh @echo " echo \"Check these ica symbols:\"" >> libica-link.sh @echo " nm --undefined-only \"\$${IBMCA_SO}\" | grep 'ica_'" >> libica-link.sh @echo " exit 99" >> libica-link.sh @echo "fi" >> libica-link.sh @echo "exit 0" >> libica-link.sh @chmod u+x libica-link.sh CLEANFILES = *.out *.dec libica-link.sh openssl-ibmca-2.4.1/test/engine/aes-128-cbc-test.pl000077500000000000000000000001371450276407300216310ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-128-cbc", 16, 16); openssl-ibmca-2.4.1/test/engine/aes-128-cfb-test.pl000077500000000000000000000001371450276407300216340ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-128-cfb", 16, 16); openssl-ibmca-2.4.1/test/engine/aes-128-ecb-test.pl000077500000000000000000000001361450276407300216320ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-128-ecb", 16, 0); openssl-ibmca-2.4.1/test/engine/aes-128-ofb-test.pl000077500000000000000000000001371450276407300216500ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-128-ofb", 16, 16); openssl-ibmca-2.4.1/test/engine/aes-192-cbc-test.pl000077500000000000000000000001371450276407300216320ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-192-cbc", 24, 16); openssl-ibmca-2.4.1/test/engine/aes-192-cfb-test.pl000077500000000000000000000001371450276407300216350ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-192-cfb", 24, 16); openssl-ibmca-2.4.1/test/engine/aes-192-ecb-test.pl000077500000000000000000000001361450276407300216330ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-192-ecb", 24, 0); openssl-ibmca-2.4.1/test/engine/aes-192-ofb-test.pl000077500000000000000000000001371450276407300216510ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-192-ofb", 24, 16); openssl-ibmca-2.4.1/test/engine/aes-256-cbc-test.pl000077500000000000000000000001371450276407300216330ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-256-cbc", 32, 16); openssl-ibmca-2.4.1/test/engine/aes-256-cfb-test.pl000077500000000000000000000001371450276407300216360ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-256-cfb", 32, 16); openssl-ibmca-2.4.1/test/engine/aes-256-ecb-test.pl000077500000000000000000000001361450276407300216340ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-256-ecb", 32, 0); openssl-ibmca-2.4.1/test/engine/aes-256-ofb-test.pl000077500000000000000000000001371450276407300216520ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::cipher("aes-256-ofb", 32, 16); openssl-ibmca-2.4.1/test/engine/des-cbc-test.pl000077500000000000000000000003051450276407300213210ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; # Version 3 only supports DES in legacy mode which might not be available. test::osslversion1 || exit (77); test::cipher("des-cbc", 8, 8); openssl-ibmca-2.4.1/test/engine/des-cfb-test.pl000077500000000000000000000003051450276407300213240ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; # Version 3 only supports DES in legacy mode which might not be available. test::osslversion1 || exit (77); test::cipher("des-cfb", 8, 8); openssl-ibmca-2.4.1/test/engine/des-ecb-test.pl000077500000000000000000000003051450276407300213230ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; # Version 3 only supports DES in legacy mode which might not be available. test::osslversion1 || exit (77); test::cipher("des-ecb", 8, 0); openssl-ibmca-2.4.1/test/engine/des-ofb-test.pl000077500000000000000000000003051450276407300213400ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; # Version 3 only supports DES in legacy mode which might not be available. test::osslversion1 || exit (77); test::cipher("des-ofb", 8, 8); openssl-ibmca-2.4.1/test/engine/dsa2k.key000066400000000000000000000023101450276407300202200ustar00rootroot00000000000000-----BEGIN DSA PRIVATE KEY----- MIIDVQIBAAKCAQEA9PsXA/O3soomi8tuZOLnjLSH8lBkpfSvOsnrKjegF/wGafTp AIwxucPyRvC3B03lI6IHH/pTH42/Lbkk46Qnm7nLOQKkBq5SOvx4DecZfewtNXvP Z4KcqrFCs/xjR+qHJ10HntcHBW7yKzoNX7Q2TXj78FUSIQe0f4PCaiHJwMgzibcJ UBfOxegjY38/MQkTGyaOEzFwTrcTCO6O5xokhTmqbPP3Zw2FOqEwcm7vnCXmUU+f fE5Eb6HIpUYOy947A6hEHz4mbFAPx3/IqslKICegqmu6sVtWAVVPhn7BCbjvNFZT znuW3nkp7bGoeOG1q6ssM096OxLs9MZS7aGeOwIhAInYRUBxrHUZ3ji+E3MflNjw T7pWQV50gthrPe8k+Ov/AoIBAQCcqYFWlR3hVHtlLtewB85Wo/vbyq/NvilF+RyT q6Q0U0R+9+1E/wmoBvhRpiyYh75fDVD838rVq8FeCdk3drdZ0PlvnReLQN25AJeO I5uNYWIjAlPwhpsYUA9f/GaD6zJPldCv9xCHeB7KyJwl2L9bcUFs+S0S8IK3Gh2l guURh4byBcPSKUmnZf0EELXe2tf/U+wNd0xJh/inRnFfZ6LgxY3KTun5Xv7efEQh CaXEaSfQDqEDaAfC1VVhJVF+jKTNaqwpwWWe+OWj83IseFOFOyRGz2YrlEFcPDMU bG20FocKan8RjKDAmo8zBD15Ieid9NceJzujetJF8VFGHVd4AoIBAA9Qm42Yz7KA lkTAjVgRsx6x8+Rf6Yc1I46hRd0Ei1qBVxDec95I3YW+zR2eMJPQbjr5uN2/eLNv Dv7Ud4NQfAz0mQOHSJen9OjqZagpYWOe6uYmshHkQPwO15TGsxjdfE4MLGk/1dO8 pUowsMYomCah6QQQhGQSHJaKRx7/2AYOulcsSNdDWLKE0S7uud1OgTynIigCv1q5 vc/u1gM7euE5RMsOofsunBOjP6vRmF9B2I2uveTas4oiCfZSjHtY0gfDCutGx2US FgpWVZLNEiNDQ49Gb4pQafp4QyBa8N9/MFE8L5BfrvXaEchH/phYCt6uLHpf8OzF r8Zg499aMAwCH12/vkIjCtnRI3k85QuQEITQr6ADFQx2K6IOT2vsIk8= -----END DSA PRIVATE KEY----- openssl-ibmca-2.4.1/test/engine/dsa2k.pl000077500000000000000000000001261450276407300200510ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::dsasignverify("2k"); openssl-ibmca-2.4.1/test/engine/dsa2k_pub.key000066400000000000000000000022521450276407300210730ustar00rootroot00000000000000-----BEGIN PUBLIC KEY----- MIIDRzCCAjoGByqGSM44BAEwggItAoIBAQD0+xcD87eyiiaLy25k4ueMtIfyUGSl 9K86yesqN6AX/AZp9OkAjDG5w/JG8LcHTeUjogcf+lMfjb8tuSTjpCebucs5AqQG rlI6/HgN5xl97C01e89ngpyqsUKz/GNH6ocnXQee1wcFbvIrOg1ftDZNePvwVRIh B7R/g8JqIcnAyDOJtwlQF87F6CNjfz8xCRMbJo4TMXBOtxMI7o7nGiSFOaps8/dn DYU6oTBybu+cJeZRT598TkRvocilRg7L3jsDqEQfPiZsUA/Hf8iqyUogJ6Cqa7qx W1YBVU+GfsEJuO80VlPOe5beeSntsah44bWrqywzT3o7Euz0xlLtoZ47AiEAidhF QHGsdRneOL4Tcx+U2PBPulZBXnSC2Gs97yT46/8CggEBAJypgVaVHeFUe2Uu17AH zlaj+9vKr82+KUX5HJOrpDRTRH737UT/CagG+FGmLJiHvl8NUPzfytWrwV4J2Td2 t1nQ+W+dF4tA3bkAl44jm41hYiMCU/CGmxhQD1/8ZoPrMk+V0K/3EId4HsrInCXY v1txQWz5LRLwgrcaHaWC5RGHhvIFw9IpSadl/QQQtd7a1/9T7A13TEmH+KdGcV9n ouDFjcpO6fle/t58RCEJpcRpJ9AOoQNoB8LVVWElUX6MpM1qrCnBZZ745aPzcix4 U4U7JEbPZiuUQVw8MxRsbbQWhwpqfxGMoMCajzMEPXkh6J301x4nO6N60kXxUUYd V3gDggEFAAKCAQAPUJuNmM+ygJZEwI1YEbMesfPkX+mHNSOOoUXdBItagVcQ3nPe SN2Fvs0dnjCT0G46+bjdv3izbw7+1HeDUHwM9JkDh0iXp/To6mWoKWFjnurmJrIR 5ED8DteUxrMY3XxODCxpP9XTvKVKMLDGKJgmoekEEIRkEhyWikce/9gGDrpXLEjX Q1iyhNEu7rndToE8pyIoAr9aub3P7tYDO3rhOUTLDqH7LpwToz+r0ZhfQdiNrr3k 2rOKIgn2Uox7WNIHwwrrRsdlEhYKVlWSzRIjQ0OPRm+KUGn6eEMgWvDffzBRPC+Q X6712hHIR/6YWArerix6X/Dsxa/GYOPfWjAM -----END PUBLIC KEY----- openssl-ibmca-2.4.1/test/engine/dsa4k.key000066400000000000000000000043301450276407300202260ustar00rootroot00000000000000-----BEGIN DSA PRIVATE KEY----- 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 -----END DSA PRIVATE KEY----- openssl-ibmca-2.4.1/test/engine/dsa4k.pl000077500000000000000000000001251450276407300200520ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::dsasignverify("4k"); openssl-ibmca-2.4.1/test/engine/dsa4k_pub.key000066400000000000000000000042721450276407300211010ustar00rootroot00000000000000-----BEGIN PUBLIC KEY----- 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 gptbWDuK0KStmNKNpOwAuXzHBTih6ZIpsxg= -----END PUBLIC KEY----- openssl-ibmca-2.4.1/test/engine/dsa8k.key000066400000000000000000000103701450276407300202330ustar00rootroot00000000000000-----BEGIN DSA PRIVATE KEY----- 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 -----END DSA PRIVATE KEY----- openssl-ibmca-2.4.1/test/engine/dsa8k.pl000077500000000000000000000001251450276407300200560ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::dsasignverify("8k"); openssl-ibmca-2.4.1/test/engine/dsa8k_pub.key000066400000000000000000000103321450276407300210770ustar00rootroot00000000000000-----BEGIN PUBLIC KEY----- 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 WeJznXOmjWhQE935s8DC4XY43509e/5gon8= -----END PUBLIC KEY----- openssl-ibmca-2.4.1/test/engine/dsamax.key000066400000000000000000000122231450276407300204750ustar00rootroot00000000000000-----BEGIN DSA PRIVATE KEY----- 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 UQ== -----END DSA PRIVATE KEY----- openssl-ibmca-2.4.1/test/engine/dsamax.pl000077500000000000000000000001261450276407300203220ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::dsasignverify("max"); openssl-ibmca-2.4.1/test/engine/dsamax_pub.key000066400000000000000000000121601450276407300213430ustar00rootroot00000000000000-----BEGIN PUBLIC KEY----- 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 -----END PUBLIC KEY----- openssl-ibmca-2.4.1/test/engine/dsaparam2k.key000066400000000000000000000014641450276407300212520ustar00rootroot00000000000000-----BEGIN DSA PARAMETERS----- MIICLQKCAQEA9PsXA/O3soomi8tuZOLnjLSH8lBkpfSvOsnrKjegF/wGafTpAIwx ucPyRvC3B03lI6IHH/pTH42/Lbkk46Qnm7nLOQKkBq5SOvx4DecZfewtNXvPZ4Kc qrFCs/xjR+qHJ10HntcHBW7yKzoNX7Q2TXj78FUSIQe0f4PCaiHJwMgzibcJUBfO xegjY38/MQkTGyaOEzFwTrcTCO6O5xokhTmqbPP3Zw2FOqEwcm7vnCXmUU+ffE5E b6HIpUYOy947A6hEHz4mbFAPx3/IqslKICegqmu6sVtWAVVPhn7BCbjvNFZTznuW 3nkp7bGoeOG1q6ssM096OxLs9MZS7aGeOwIhAInYRUBxrHUZ3ji+E3MflNjwT7pW QV50gthrPe8k+Ov/AoIBAQCcqYFWlR3hVHtlLtewB85Wo/vbyq/NvilF+RyTq6Q0 U0R+9+1E/wmoBvhRpiyYh75fDVD838rVq8FeCdk3drdZ0PlvnReLQN25AJeOI5uN YWIjAlPwhpsYUA9f/GaD6zJPldCv9xCHeB7KyJwl2L9bcUFs+S0S8IK3Gh2lguUR h4byBcPSKUmnZf0EELXe2tf/U+wNd0xJh/inRnFfZ6LgxY3KTun5Xv7efEQhCaXE aSfQDqEDaAfC1VVhJVF+jKTNaqwpwWWe+OWj83IseFOFOyRGz2YrlEFcPDMUbG20 FocKan8RjKDAmo8zBD15Ieid9NceJzujetJF8VFGHVd4 -----END DSA PARAMETERS----- openssl-ibmca-2.4.1/test/engine/dsaparam4k.key000066400000000000000000000027531450276407300212560ustar00rootroot00000000000000-----BEGIN DSA PARAMETERS----- MIIELAKCAgEAyJscZddSVlbzJWUul/6UyYNMDQ5Tw1Hw7qCKGWmpAAZlASED5TPD 60SgxOBMZK37oce07VBxe/pqXLdMEGN52Fo7ST1mil5/Rb4JUvexLX9NCyz7LBNg hIXQtb7826dK79Q6t5nXAHmUl/1WeHOIgwSDD9ECU6km/O10CPKrWlN187ob8lk/ /zA0uU/J7ZN8jFei8d0+E+tSRRhDtNjJPXw9uHc+Vd2H8rfGh2riP0x7mH/h+32U hcPbKyRtzgweeCYbdS5rLaWCoKAawNg2QbpotFf9LFWqohnkHINpgHQuBCDAuriN euRX4yNR/SA1BXx/esKRxqnHs34qxSSZzHea1uIWi/IbmU0xFT02tWwZ2MKFpmfr ky3eJY/L6wSyIrrbRp42m6sV4R5jjTg8nTOl1d4N/JVe6ttXH4fx/VDc/3vLktiv 69+dKCgsGrEo+vBKpqY/6CXuHFYSVZM+7NTMKGilsT59gP3Oc9I4ApF/Z/MuN9jv k3Uyz1uUDszbmVYjHhWg5g/O56G8wj+QH4XPfW4IS0AiaHkuo008xJDRcJbBVzbx z+gxZqL143OQG9ciXxw+imnbSNsyB+a5cpKOEwgoeU3lIRhe8eRtvWfzfT8T94LN 8xU7w6tzoSk0JxLTdIBKHDST17jmato/SA4uwz31uaWA7eU3gv4u1DECIQDHoioD Wzjed2EIPznryUN1YsmeTbyn53t4Ud4o4DLOmQKCAgA104Ps34soiOkNr9e+e8tb kbOhix2Brr2OM2c0V5CGU6Oofjila1hNp0DfoN/jrPzZT/qeiyuIleqVjlpaV/f6 PJn2FX9Amx3g8Yhy4ywP3PPU71Orbj+LiP56cHanvHEe941HKxUpXcYSHOskE6AQ gl/pz6leBqfnWUjAPQbO7jeYVhuaz8ovfke7G6gZNDpiVV8BLdJ9c4OF+83SimDJ CdFnRYrbtDXsYHCv2FK7bLDaujJEOqjNFjQX5/7OCSb7f17zJtM7BZkAZR89+N8K uOjQKVqzCFqGaNAB/7VPgzHjzAoi9YGNHoM2Jy+aY0kv1hBjkwdw9m/gnNZAREMo tXtVbxnV9+ppHpacA9eqHE1XIeIE7SN8D1snQAGhRmvlOUAuyhnDOnkBvvCXnoAm lprDX4P+WtBdGXFDKGkYz7LRZt6jT1GasgXdjscYlEUb/Y7Hklyn56tTlLEVICpZ qWt+mRB0gXrt5NDpq6rvq2Xv7A545H48dQ4Q8HisOkn6VoedhR6jMfXCM93SOx0l g20cmfYMp3H2OYW1z+j1K4Lgsqdf+RX1t1glvS+1vP/Mp/xqFvc0T8D7YYMYnjQj ZE8zgDKqlGeeXYKxzD9EOeVAzftS37E2A3TGSG0JOPN/c4jtO1EAIXJobRmPkTFa AbIF7OuseZPHf6QYGuelbg== -----END DSA PARAMETERS----- openssl-ibmca-2.4.1/test/engine/dsaparam8k.key000066400000000000000000000055241450276407300212610ustar00rootroot00000000000000-----BEGIN DSA PARAMETERS----- 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 -----END DSA PARAMETERS----- openssl-ibmca-2.4.1/test/engine/dsaparammax.key000066400000000000000000000066721450276407300215310ustar00rootroot00000000000000-----BEGIN DSA PARAMETERS----- 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 Scz1Kw== -----END DSA PARAMETERS----- openssl-ibmca-2.4.1/test/engine/eckey.c000066400000000000000000000105471450276407300177610ustar00rootroot00000000000000#include #include #include #include #include #include void setup(void) { OPENSSL_load_builtin_modules(); ENGINE_load_builtin_engines(); /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and 0.9.8e */ #ifndef CONF_MFLAGS_DEFAULT_SECTION #define CONF_MFLAGS_DEFAULT_SECTION 0x0 #endif CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.0+ takes care of initialization itself */ #else OpenSSL_add_all_algorithms(); #endif } int check_eckey(int nid, const char *name, int error) { int ret = !error; ECDSA_SIG *sig = NULL; EC_KEY *eckey = NULL; unsigned char digest[20]; ENGINE *engine = NULL; memset(digest, 0, sizeof(digest)); engine = ENGINE_by_id("ibmca"); if (engine == NULL) { fprintf(stderr, "ibmca engine not loaded\n"); goto out; } if (ENGINE_get_EC(engine) == NULL) { fprintf(stderr, "ibmca does not support EC_KEY. Skipping...\n"); exit(77); } eckey = EC_KEY_new_by_curve_name(nid); if (eckey == NULL) { /* curve not supported => test passed */ fprintf(stderr, "Curve %s not supported by OpenSSL\n", name); ret = 1; goto out; } if (EC_KEY_get0_engine(eckey) != engine) { fprintf(stderr, "EC_KEY for %s does not use ibmca engine\n", name); goto out; } if (!EC_KEY_generate_key(eckey)) { /* error */ fprintf(stderr, "Failed to generate EC_KEY for %s\n", name); goto out; } sig = ECDSA_do_sign(digest, sizeof(digest), eckey); if (sig == NULL) { if (error) fprintf(stderr, "Failed to sign with %s\n", name); else fprintf(stderr, "Assuming %s is not supported and skipping test\n", name); goto out; } ret = ECDSA_do_verify(digest, sizeof(digest), sig, eckey); if (ret == -1) { /* error */ fprintf(stderr, "Failed to verify signature with %s\n", name); goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Signature incorrect with %s\n", name); goto out; } else { /* signature ok */ ret = 1; } out: if (engine) ENGINE_free(engine); if (sig) ECDSA_SIG_free(sig); if (eckey) EC_KEY_free(eckey); return ret; } int main(int argc, char **argv) { static const struct testparams { int nid; const char *name; int error; } params[] = { {NID_X9_62_prime192v1, "NID_X9_62_prime192v1", 0}, {NID_secp224r1, "NID_secp224r1", 0}, {NID_X9_62_prime256v1, "NID_X9_62_prime256v1", 1}, {NID_secp384r1, "NID_secp384r1", 1}, {NID_secp521r1, "NID_secp521r1", 1}, {NID_brainpoolP160r1, "NID_brainpoolP160r1", 0}, {NID_brainpoolP192r1, "NID_brainpoolP192r1", 0}, {NID_brainpoolP224r1, "NID_brainpoolP224r1", 0}, {NID_brainpoolP256r1, "NID_brainpoolP256r1", 0}, {NID_brainpoolP320r1, "NID_brainpoolP320r1", 0}, {NID_brainpoolP384r1, "NID_brainpoolP384r1", 0}, {NID_brainpoolP512r1, "NID_brainpoolP512r1", 0} }; int ret = 0, i; /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_CONF"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } setup(); for (i = 0; i < sizeof(params) / sizeof(struct testparams); ++i) { if (!check_eckey(params[i].nid, params[i].name, params[i].error)) { fprintf(stderr, "Failure for %s\n", params[i].name); ret = 99; } } return ret; } openssl-ibmca-2.4.1/test/engine/enginectrl.c000066400000000000000000000070151450276407300210070ustar00rootroot00000000000000#include #include #include #include #include #include #include void setup(void) { OPENSSL_load_builtin_modules(); ENGINE_load_builtin_engines(); /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and 0.9.8e */ #ifndef CONF_MFLAGS_DEFAULT_SECTION #define CONF_MFLAGS_DEFAULT_SECTION 0x0 #endif CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.0+ takes care of initialization itself */ #else OpenSSL_add_all_algorithms(); #endif } int initwithlib(ENGINE *e, const char *lib, int checkexists, int expectedinitval) { void *hdl; if (checkexists) { hdl = dlopen(lib, RTLD_LAZY); if (hdl == NULL) { fprintf(stderr, "Skipping initialization with non-existent library \"%s\"\n", lib); return 1; } dlclose(hdl); } if (ENGINE_ctrl_cmd_string(e, "libica", lib, 0) != 1) { fprintf(stderr, "\"libica\" ctrl failed to set \"%s\" on un-initialized ibmca!\n", lib); return 0; } if (ENGINE_init(e) != expectedinitval) { fprintf(stderr, "ibmca unexpted initialization result for libica=%s (expected: %d)!\n", lib, expectedinitval); return 0; } ENGINE_finish(e); return 1; } int testctrl(void) { ENGINE *engine; int ret = 99, i; static const struct testparams { const char *lib; int checkexists; int expectedinitval; } params[] = { {"doesnotexist", 0, 0}, {"libica.so.3", 1, 1}, {"libica-cex.so.3", 1, 1}, {"libica.so.4", 1, 1}, {"libica-cex.so.4", 1, 1} }; engine = ENGINE_by_id("ibmca"); if (engine == NULL) { fprintf(stderr, "ibmca engine not loaded! Skipping...\n"); return 77; } if (!ENGINE_init(engine)) { fprintf(stderr, "ibmca engine initialization failed!\n"); goto out; } /* Engine ctrl "libica" only works if engine is not initialized. */ if (ENGINE_ctrl_cmd_string(engine, "libica", "doesnotexist", 0) == 1) { fprintf(stderr, "\"libica\" ctrl succeeded despite initialized ibmca!\n"); goto out; } ENGINE_finish(engine); ret = 0; for (i = 0; i < sizeof(params) / sizeof(struct testparams); ++i) { if (!initwithlib(engine, params[i].lib, params[i].checkexists, params[i].expectedinitval)) ret = 99; } /* We have to restore the correct libica and init ibmca here to restore the double free above. This might leak resources, but should be okay for a test. */ ENGINE_ctrl_cmd_string(engine, "libica", LIBICA_SHARED_LIB, 0); ENGINE_init(engine); out: ENGINE_free(engine); return ret; } int main(int argc, char **argv) { /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_NOINIT_CONF"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } setup(); return testctrl(); } openssl-ibmca-2.4.1/test/engine/loadtest-ec.c000066400000000000000000000113561450276407300210640ustar00rootroot00000000000000#include #include #include #include #include #include #include #include int setup() { const SSL_METHOD *req_method; SSL_CTX *ctx; EC_KEY *eckey = NULL; ENGINE *ibmca; ENGINE *actual; int ret = 0; /* Start code copy from libcurl 7.61.1 Curl_ossl_init function */ OPENSSL_load_builtin_modules(); /* MOD start */ #ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES //ENGINE_load_builtin_engines(); #endif ENGINE_load_builtin_engines(); /* MOD end */ /* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately that function makes an exit() call on wrongly formatted config files which makes it hard to use in some situations. OPENSSL_config() itself calls CONF_modules_load_file() and we use that instead and we ignore its return code! */ /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and 0.9.8e */ #ifndef CONF_MFLAGS_DEFAULT_SECTION #define CONF_MFLAGS_DEFAULT_SECTION 0x0 #endif CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.0+ takes care of initialization itself */ #else /* Lets get nice error messages */ SSL_load_error_strings(); /* Init the global ciphers and digests */ if(!SSLeay_add_ssl_algorithms()) return 0; OpenSSL_add_all_algorithms(); #endif /* End code copy from libcurl 7.61.1 Curl_ossl_init function */ ibmca = ENGINE_by_id("ibmca"); if (ibmca == NULL) { fprintf(stderr, "Failed to retrieve ibmca engine\n"); goto out; } eckey = EC_KEY_new_by_curve_name(NID_secp384r1); if (eckey == NULL) { /* error */ fprintf(stderr, "Failed to create EC_KEY for secp384r1\n"); goto out; } actual = EC_KEY_get0_engine(eckey); if (ibmca != actual) { fprintf(stderr, "EC_KEY not associated with ibmca\n"); goto out; } /* Start extraction from libcurl 7.61.1 ossl_connect_step1 */ req_method = TLS_client_method(); /* This initializes libssl which initializes libcrypto for the second time. */ ctx = SSL_CTX_new(req_method); SSL_CTX_free(ctx); ret = 1; out: if (eckey) EC_KEY_free(eckey); return ret; } int check_globals() { int ret = 0; ECDSA_SIG *sig = NULL; EC_KEY *eckey = NULL; unsigned char digest[20]; ENGINE *ibmca; ENGINE *actual; memset(digest, 0, sizeof(digest)); ibmca = ENGINE_by_id("ibmca"); if (ibmca == NULL) { fprintf(stderr, "Failed to retrieve ibmca engine\n"); goto out; } eckey = EC_KEY_new_by_curve_name(NID_secp384r1); if (eckey == NULL) { /* error */ fprintf(stderr, "Failed to create EC_KEY for secp384r1\n"); goto out; } if (!EC_KEY_generate_key(eckey)) { /* error */ fprintf(stderr, "Failed to generate EC_KEY\n"); goto out; } actual = EC_KEY_get0_engine(eckey); if (ibmca != actual) { fprintf(stderr, "EC_KEY not associated with ibmca\n"); goto out; } sig = ECDSA_do_sign(digest, sizeof(digest), eckey); if (sig == NULL) { /* error */ fprintf(stderr, "Failed to sign\n"); goto out; } ret = ECDSA_do_verify(digest, sizeof(digest), sig, eckey); if (ret == -1) { /* error */ fprintf(stderr, "Failed to verify signature\n"); goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Signature incorrect\n"); goto out; } else { /* signature ok */ ret = 1; } out: if (sig) ECDSA_SIG_free(sig); if (eckey) EC_KEY_free(eckey); return ret; } int main(int argc, char **argv) { /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_CONF"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } if (!setup()) { fprintf(stderr, "Setup failed! Skipping...\n"); return 77; } if (!check_globals()) { fprintf(stderr, "Check for global variables failed!\n"); return 99; } return 0; } openssl-ibmca-2.4.1/test/engine/loadtest.c000066400000000000000000000072231450276407300204750ustar00rootroot00000000000000#include #include #include #include #include #include #include #include int setup() { const SSL_METHOD *req_method; SSL_CTX *ctx; ENGINE *engine; EVP_PKEY_CTX *pctx = NULL; /* Start code copy from libcurl 7.61.1 Curl_ossl_init function */ OPENSSL_load_builtin_modules(); /* MOD start */ #ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES //ENGINE_load_builtin_engines(); #endif ENGINE_load_builtin_engines(); /* MOD end */ /* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately that function makes an exit() call on wrongly formatted config files which makes it hard to use in some situations. OPENSSL_config() itself calls CONF_modules_load_file() and we use that instead and we ignore its return code! */ /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and 0.9.8e */ #ifndef CONF_MFLAGS_DEFAULT_SECTION #define CONF_MFLAGS_DEFAULT_SECTION 0x0 #endif CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.0+ takes care of initialization itself */ #else /* Lets get nice error messages */ SSL_load_error_strings(); /* Init the global ciphers and digests */ if(!SSLeay_add_ssl_algorithms()) return 0; OpenSSL_add_all_algorithms(); #endif /* End code copy from libcurl 7.61.1 Curl_ossl_init function */ engine = ENGINE_by_id("ibmca"); pctx = EVP_PKEY_CTX_new_id(NID_X25519, engine); if (pctx == NULL) { return 0; } EVP_PKEY_CTX_free(pctx); /* Start extraction from libcurl 7.61.1 ossl_connect_step1 */ req_method = TLS_client_method(); /* This initializes libssl which initializes libcrypto for the second time. */ ctx = SSL_CTX_new(req_method); SSL_CTX_free(ctx); return 1; } int check_globals() { int ret = 0; EVP_PKEY *eckey = NULL; ENGINE *engine; EVP_PKEY_CTX *pctx = NULL; engine = ENGINE_by_id("ibmca"); if (engine == NULL) { fprintf(stderr, "Failed to retrieve ibmca engine\n"); goto out; } pctx = EVP_PKEY_CTX_new_id(NID_X25519, engine); if (pctx == NULL) { fprintf(stderr, "Failed to create PKEY_CTX\n"); return 0; } if (EVP_PKEY_keygen_init(pctx) != 1 || EVP_PKEY_keygen(pctx, &eckey) != 1) { fprintf(stderr, "keygen initialization failed\n"); goto out; } if (eckey == NULL) { /* error */ fprintf(stderr, "Failed to create ec key for X25519\n"); goto out; } ret = 1; out: if (pctx) EVP_PKEY_CTX_free(pctx); if (eckey) EVP_PKEY_free(eckey); return ret; } int main(int argc, char **argv) { /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_CONF"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } if (!setup()) { fprintf(stderr, "Setup failed! Skipping...\n"); return 77; } if (!check_globals()) { fprintf(stderr, "Check for global variables failed!\n"); return 99; } return 0; } openssl-ibmca-2.4.1/test/engine/openssl-test-noinit.cnf000066400000000000000000000006541450276407300231410ustar00rootroot00000000000000openssl_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 = 0 # 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.4.1/test/engine/openssl-test.cnf000066400000000000000000000006541450276407300216430ustar00rootroot00000000000000openssl_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.4.1/test/engine/rsa16k.key000066400000000000000000000304731450276407300203360ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY----- openssl-ibmca-2.4.1/test/engine/rsa16k.pl000077500000000000000000000002011450276407300201460ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::rsaencdec("16k", 2, 2037); test::rsasignverify("16k", 2, 2037); openssl-ibmca-2.4.1/test/engine/rsa2k.key000066400000000000000000000032171450276407300202450ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEApvjwHFoxHNoLvRafqgbcMHXn/kUxe2VxwmkbMg3u9sYXjZ1I UoyKN4GIy6VqLdZDFGfbDL4ijXOh3ak0pGD/H65dbfaaK/+oggfIgpPWbtF+K5VO sXY/fkt+16IcKlxU9+Pzve9eDDFchKr6McVvZBTF0D41XxX3uf9SZkag4W6f0iEj UzOLOLRI1OeVS3Sjiz/qQYxXqcNqAu7AH1yrepCzjCflaSYDX85ivJqoqWsNsBcq iPG2FnkxMtqGBwZzhuldcnLnBG6XNvKEJnw5OkbtukhtE3Clh83E7fs3QN9ZkV1x wtQtPPOOVM/GehpqkhcQLXl+ePV7ZkXr8L1V8wIDAQABAoIBAC71LZnbp5pEnC6G cUrA+SXL0v3Ied0JL5AMPTC7iGvwU+loxVEp4ykvDciv8YeIjX7sokcYJeGAFpKf JoXgHX/MaswlIUCkesBu7e4DI7gwxHn/WI1CAyNCmh6Mob0sEF1Sx1awPdPSAgHx j8F1lBkiWmtxQ1NFe1DcxFCtJkufe5GaOpzX642++1XIzNdD20ueG2HEidPpLxla eQ7rw0Aisg/W92UMLGM5US1ZX7jhq79mwCiLcQfGf74Gd66/lPy+xlZAP/3boj2U BiV9vRl94pv+FJXK8Xli076CCKo3BTevIOJwZTsQp2uZXfPWp7qHVZ/vG4tZvlnj IwQWgjECgYEA0/WHfyrAmxvQWrVHvOGaEoUZUEpP4N1q1FL6rhNtRoTDx6qtPXyp sDFCFKqYF9UFPGaQP/bvz6QAUViifC+Kb0Zy/60dCeYeyvqF9beyCey4IrfXPX4T vWTRA1dSV7L6E/9hNybqwh5CVG+1aqyoAHO+ti7Innt5Y6q2l0mt6okCgYEAyap9 OFTqjM5503j5fovt5KISAMrjPhu9M35057SdClFZDSAJpYVKpkctsnEJCY4OHA3d NHH7xFE6FgdUXQ00tfqoBUeSB8ITZ33Top8EJuWCvEKsEect8TO4XJ67jWvezpwM 6pjIYSsjljO1GG9WDtHBuum/wg03u2ZBvpX0bZsCgYEAwEDQafQpR4du8RfEvfoT egDn+P+ufFPZdkTdw88zKud5fT2+bSsJ7xp+yagC1HsPiL2u0ZX15uzmrOIsX1/v vQa1gFtRH41vGMUrhLjd8EqaqkL+JHSbCwrK2rD1qz5XvpPBZfkSrogrudKpRtzc dayGq1C7/6QXcuOBQrA946ECgYEAlhvPZXTfubufNuffXnCtvPdeSzS5/WsMZB4G ysnH8vwmOvzT8V7L+AUXYLF+tpwEqKExPG5zpueHQwplo3XG/IX9NyDU8+1kIC6q r2uJ3aIMtDE0f4cCzX1gB6EnndbjXAsQGjdrP9iqfo0yiWOmPRWpDIYddEX+bAFr gn+AF20CgYB/oV4xXkWZ4j4jbHPBOLCH41S8eGWfrKDc/8o9uu91w6psKhFTqyLE go0fL/amg122kpGpCL6SHxLDPeeTCvInvaUfLx5LL4l3XgmJuq1kQ1GN3/qm5ObM kfVkgDK18CsQkQQxmWg2sgEnuACCXDCXPNwNQFgd0P6F8CjoL9JPsA== -----END RSA PRIVATE KEY----- openssl-ibmca-2.4.1/test/engine/rsa2k.pl000077500000000000000000000001761450276407300200740ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::rsaencdec("2k", 50, 245); test::rsasignverify("2k", 50, 245); openssl-ibmca-2.4.1/test/engine/rsa4k.key000066400000000000000000000062531450276407300202520ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY----- openssl-ibmca-2.4.1/test/engine/rsa4k.pl000077500000000000000000000001771450276407300200770ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::rsaencdec("4k", 50, 501); test::rsasignverify("4k", 50, 501); openssl-ibmca-2.4.1/test/engine/rsa8k.key000066400000000000000000000143331450276407300202540ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY----- openssl-ibmca-2.4.1/test/engine/rsa8k.pl000077500000000000000000000002001450276407300200660ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use test; test::rsaencdec("8k", 10, 1013); test::rsasignverify("8k", 10, 1013); openssl-ibmca-2.4.1/test/engine/test.pm000066400000000000000000000134421450276407300200270ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; use FindBin; package test; sub osslversion1 { my $vstr = `openssl version -v`; return $vstr =~ /OpenSSL 1\..*/; } sub osslversion3 { my $vstr = `openssl version -v`; return $vstr =~ /OpenSSL 3\..*/; } 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 > ${cipher}.${i}.data.in`; `$eng openssl $cipher -e -K $key $iv -in ${cipher}.${i}.data.in -out ${cipher}.${i}.data.enc`; `openssl $cipher -d -K $key $iv -in ${cipher}.${i}.data.enc -out ${cipher}.${i}.data.dec`; `cmp ${cipher}.${i}.data.in ${cipher}.${i}.data.dec`; exit(99) if ($?); `rm -f ${cipher}.${i}.data.in ${cipher}.${i}.data.enc ${cipher}.${i}.data.dec`; # no-engine enc, engine dec `openssl rand $bytes > ${cipher}.${i}.data.in`; `openssl $cipher -e -K $key $iv -in ${cipher}.${i}.data.in -out ${cipher}.${i}.data.enc`; `$eng openssl $cipher -d -K $key $iv -in ${cipher}.${i}.data.enc -out ${cipher}.${i}.data.dec`; `cmp ${cipher}.${i}.data.in ${cipher}.${i}.data.dec`; exit(99) if ($?); `rm -f ${cipher}.${i}.data.in ${cipher}.${i}.data.enc ${cipher}.${i}.data.dec`; } } sub rsaencdec { my $eng = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF}"; my @hex = ("a".."f", "0".."9"); my ($keylen, $tests, $max_file_size) = @_; # 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)); # engine enc, no-engine dec `openssl rand $bytes > rsaencdec.${i}.${keylen}.data.in`; `$eng openssl rsautl -encrypt -inkey $FindBin::Bin/rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.in -out rsaencdec.${i}.${keylen}.data.out`; `openssl rsautl -decrypt -inkey $FindBin::Bin/rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.out -out rsaencdec.${i}.${keylen}.data.dec`; `cmp rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.data.dec`; exit(99) if ($?); `rm -f rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.out rsaencdec.${i}.${keylen}.dec`; # no-engine enc, engine dec `openssl rand $bytes > rsaencdec.${i}.${keylen}.data.in`; `openssl rsautl -encrypt -inkey $FindBin::Bin/rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.in -out rsaencdec.${i}.${keylen}.data.out`; `$eng openssl rsautl -decrypt -inkey $FindBin::Bin/rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.out -out rsaencdec.${i}.${keylen}.data.dec`; `cmp rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.data.dec`; exit(99) if ($?); `rm -f rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.out rsaencdec.${i}.${keylen}.dec`; } } sub rsasignverify { my $eng = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF}"; my @hex = ("a".."f", "0".."9"); my ($keylen, $tests, $max_file_size) = @_; # 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); # engine sign, no-engine verify `openssl rand $bytes > rsasignverify.${i}.${keylen}.data.in`; `$eng openssl rsautl -sign -inkey $FindBin::Bin/rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.in -out rsasignverify.${i}.${keylen}.data.out`; `openssl rsautl -verify -inkey $FindBin::Bin/rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.out -out rsasignverify.${i}.${keylen}.data.rec`; `cmp rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.rec`; exit(99) if ($?); `rm -f rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.out rsasignverify.${i}.${keylen}.data.rec`; # no-engine sign, engine verify `openssl rand $bytes > rsasignverify.${i}.${keylen}.data.in`; `openssl rsautl -sign -inkey $FindBin::Bin/rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.in -out rsasignverify.${i}.${keylen}.data.out`; `$eng openssl rsautl -verify -inkey $FindBin::Bin/rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.out -out rsasignverify.${i}.${keylen}.data.rec`; `cmp rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.rec`; exit(99) if ($?); `rm -f rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.out rsasignverify.${i}.${keylen}.data.rec`; } } sub dsasignverify { my $tests = 50; my $max_file_size = 1024; my $eng = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF}"; my @hex = ("a".."f", "0".."9"); my ($keylen) = @_; # 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)); # engine sign, no-engine verify `openssl rand $bytes > dsa.${i}.${keylen}.data.in`; `$eng openssl dgst -sign $FindBin::Bin/dsa$keylen.key -out dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`; `openssl dgst -verify $FindBin::Bin/dsa${keylen}_pub.key -signature dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`; exit(99) if ($?); `rm -f dsa.${i}.${keylen}.data.in dsa.${i}.${keylen}.data.out`; # no-engine sign, engine verify `openssl rand $bytes > dsa.${i}.${keylen}.data.in`; `openssl dgst -sign $FindBin::Bin/dsa$keylen.key -out dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`; `$eng openssl dgst -verify $FindBin::Bin/dsa${keylen}_pub.key -signature dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`; exit(99) if ($?); `rm -f dsa.${i}.${keylen}.data.in dsa.${i}.${keylen}.data.out`; } } 1; openssl-ibmca-2.4.1/test/engine/threadtest.c000066400000000000000000000111531450276407300210220ustar00rootroot00000000000000#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include /* This is just a random number of threads to stimulate engine configuration. */ #define DEFAULT_MAX_THREADS 20 static int setup() { ENGINE *engine; EVP_PKEY_CTX *pctx = NULL; OPENSSL_load_builtin_modules(); ENGINE_load_builtin_engines(); /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and 0.9.8e */ #ifndef CONF_MFLAGS_DEFAULT_SECTION #define CONF_MFLAGS_DEFAULT_SECTION 0x0 #endif CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.0+ takes care of initialization itself */ #else OpenSSL_add_all_algorithms(); #endif engine = ENGINE_by_id("ibmca"); pctx = EVP_PKEY_CTX_new_id(NID_X25519, engine); if (pctx == NULL) { return 0; } EVP_PKEY_CTX_free(pctx); return 1; } static int check_globals() { int ret = 0; EVP_PKEY *eckey = NULL; ENGINE *engine; EVP_PKEY_CTX *pctx = NULL; engine = ENGINE_by_id("ibmca"); if (engine == NULL) { fprintf(stderr, "Failed to retrieve ibmca engine\n"); goto out; } pctx = EVP_PKEY_CTX_new_id(NID_X25519, engine); if (pctx == NULL) { fprintf(stderr, "Failed to create PKEY_CTX\n"); return 0; } if (EVP_PKEY_keygen_init(pctx) != 1 || EVP_PKEY_keygen(pctx, &eckey) != 1) { fprintf(stderr, "keygen initialization failed\n"); goto out; } if (eckey == NULL) { /* error */ fprintf(stderr, "Failed to create ec key for X25519\n"); goto out; } ret = 1; out: if (pctx) EVP_PKEY_CTX_free(pctx); if (eckey) EVP_PKEY_free(eckey); return ret; } static void *threadfn(void *arg) { unsigned long res = 0; (void) arg; if (check_globals() != 1) { res = 1; } return (void *)res; } int main(int argc, char **argv) { pthread_t *threads; unsigned long int i, maxthreads = 0, errors = 0; int c; pthread_t me; /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_CONF"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } // arg parse while (1) { int option_index; static struct option long_options[] = { {"threads", required_argument, 0, 't'}, {0, 0, 0, 0 } }; c = getopt_long(argc, argv, "t:", long_options, &option_index); if (c == -1) { break; } else if (c == 't') { maxthreads = strtoul(optarg, NULL, 0); } else { fprintf(stderr, "USAGE: %s [-t|--threads ]\n", argv[0]); fprintf(stderr, "where\t specifies the number of threads to use (default: 20)\n"); return 1; } } if (maxthreads == 0) maxthreads = DEFAULT_MAX_THREADS; threads = calloc(sizeof(pthread_t), maxthreads); if (threads == NULL) { fprintf(stderr, "Thread array allocation failed!\n"); return 1; } if (setup() != 1) { fprintf(stderr, "Failed to set up test. Skipping...\n"); return 77; } me = pthread_self(); // Start threads for (i = 0; i < maxthreads; ++i) { int s = pthread_create(&threads[i], NULL, &threadfn, NULL); if (s != 0) { fprintf(stderr, "Failed to create thread %lu: %s\n", i, strerror(s)); threads[i] = me; } } // Now join threads for (i = 0; i < maxthreads; ++i) { if (!pthread_equal(threads[i], me)) { void *retval; int s = pthread_join(threads[i], &retval); if (s != 0) { fprintf(stderr, "Failed to join thread %lu: %s\n", i, strerror(s)); } else if ((unsigned long)retval != 0) { fprintf(stderr, "Error in thread %lu\n", i); ++errors; } } } return errors ? 99 : 0; } openssl-ibmca-2.4.1/test/provider/000077500000000000000000000000001450276407300170735ustar00rootroot00000000000000openssl-ibmca-2.4.1/test/provider/Makefile.am000066400000000000000000000025031450276407300211270ustar00rootroot00000000000000TESTS_PERL = \ tls.pl \ ecsign.pl \ ecderive.pl \ dhderive.pl \ rsa512.pl \ rsa1k.pl \ rsa2k.pl \ rsa4k.pl \ rsa8k.pl #rsa16k.pl if OPENSSL_IMPLICIT_REJECTION TESTS_PERL += rsaimplrej.pl endif TESTS = \ rsakey \ eckey \ dhkey \ threadtest \ ${TESTS_PERL} check_PROGRAMS = rsakey eckey dhkey threadtest dhkey_SOURCES = dhkey.c if PROVIDER_FULL_LIBICA dhkey_LDADD = -lcrypto -lica else dhkey_LDADD = -lcrypto -lica-cex endif eckey_SOURCES = eckey.c if PROVIDER_FULL_LIBICA eckey_LDADD = -lcrypto -lica else eckey_LDADD = -lcrypto -lica-cex endif rsakey_SOURCES = rsakey.c if PROVIDER_FULL_LIBICA rsakey_LDADD = -lcrypto -lica else rsakey_LDADD = -lcrypto -lica-cex endif threadtest_SOURCES = threadtest.c threadtest_LDADD = -lcrypto -lpthread AM_TESTS_ENVIRONMENT = export IBMCA_TEST_PATH=${top_builddir}/src/provider/.libs/ IBMCA_OPENSSL_TEST_CONF=${srcdir}/openssl-test.cnf PERL5LIB=${srcdir}; EXTRA_DIST = ${TESTS_PERL} test.pm openssl-test.cnf server-cert-rsa.pem \ server-key-rsa.pem server-cert-ec.pem server-key-ec.pem \ rsa-implrej-bad-empty-in.bin rsa-implrej-bad-empty-out.bin \ rsa-implrej-bad-max-in.bin rsa-implrej-bad-max-out.bin \ rsa-implrej-bad-prf-in.bin rsa-implrej-bad-prf-out.bin \ rsa-implrej-good-in.bin rsa-implrej-good-out.bin \ rsa-implrej-key.pem rsa16k.pl CLEANFILES = *.out *.dec *.pub *.key openssl-ibmca-2.4.1/test/provider/dhderive.pl000077500000000000000000000036471450276407300212370ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::dhderive("ffdhe2048", 2); test::dhderivekdf("ffdhe2048", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("ffdhe3072", 2); test::dhderivekdf("ffdhe3072", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("ffdhe4096", 2); test::dhderivekdf("ffdhe4096", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("ffdhe6144", 2); test::dhderivekdf("ffdhe6144", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("ffdhe8192", 2); test::dhderivekdf("ffdhe8192", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("modp_1536", 2); test::dhderivekdf("modp_1536", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("modp_2048", 2); test::dhderivekdf("modp_2048", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("modp_3072", 2); test::dhderivekdf("modp_3072", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("modp_4096", 2); test::dhderivekdf("modp_4096", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("modp_6144", 2); test::dhderivekdf("modp_6144", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); test::dhderive("modp_8192", 2); test::dhderivekdf("modp_8192", 2, 200, "X942KDF-ASN1", "SHA-256", "id-aes256-wrap"); openssl-ibmca-2.4.1/test/provider/dhkey.c000066400000000000000000000324711450276407300203520ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #define UNUSED(var) ((void)(var)) void setup(void) { OPENSSL_load_builtin_modules(); CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); } int check_dhkey(int nid, const char *name, const char *algo) { int ret = 0; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *dh_pkey = NULL; EVP_PKEY *peer_pkey = NULL; size_t keylen1, keylen2; unsigned char keybuf1[1024], keybuf2[1024]; const OSSL_PROVIDER *provider; const char *provname; /* Keygen with IBMCA provider */ ctx = EVP_PKEY_CTX_new_from_name(NULL, algo, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_name failed\n"); goto out; } if (EVP_PKEY_keygen_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_keygen_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_CTX_set_dh_nid(ctx, nid) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_dh_nid failed\n"); goto out; } if (EVP_PKEY_keygen(ctx, &dh_pkey) <= 0) { if (ERR_GET_REASON(ERR_peek_last_error()) == 7) { /* curve not supported => test passed */ fprintf(stderr, "Group %s not supported by OpenSSL\n", name); ret = 1; } else { fprintf(stderr, "EVP_PKEY_keygen failed\n"); } goto out; } EVP_PKEY_CTX_free(ctx); /* Keygen with IBMCA provider (using dh_pkey as template) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_keygen_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_keygen_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_keygen(ctx, &peer_pkey) <= 0) { if (ERR_GET_REASON(ERR_peek_last_error()) == 7) { /* curve not supported => test passed */ fprintf(stderr, "Group %s not supported by OpenSSL\n", name); ret = 1; } else { fprintf(stderr, "EVP_PKEY_keygen failed\n"); } goto out; } EVP_PKEY_CTX_free(ctx); /* Derive with IBMCA provider (no KDF) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_derive_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_derive_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_derive_set_peer_ex(ctx, peer_pkey, 1) != 1) { fprintf(stderr, "EVP_PKEY_derive_set_peer_ex failed\n"); goto out; } keylen1 = sizeof(keybuf1); if (EVP_PKEY_derive(ctx, keybuf1, &keylen1) <= 0) { fprintf(stderr, "EVP_PKEY_derive failed\n"); goto out; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Derive with default provider (no KDF) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_pkey, "provider=default"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_derive_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_derive_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "default") != 0) { fprintf(stderr, "Context is not using the default provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_derive_set_peer_ex(ctx, peer_pkey, 1) != 1) { fprintf(stderr, "EVP_PKEY_derive_set_peer_ex failed\n"); goto out; } keylen2 = sizeof(keybuf2); if (EVP_PKEY_derive(ctx, keybuf2, &keylen2) <= 0) { fprintf(stderr, "EVP_PKEY_derive failed\n"); goto out; } if (keylen1 != keylen2 || memcmp(keybuf1, keybuf2, keylen1) != 0) { fprintf(stderr, "Derived keys are not equal\n"); goto out; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Derive with IBMCA provider (X9_63 KDF) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_derive_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_derive_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_CTX_set_dh_kdf_type(ctx, EVP_PKEY_DH_KDF_X9_42) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_dh_kdf_type failed\n"); goto out; } if (EVP_PKEY_CTX_set_dh_kdf_md(ctx, EVP_get_digestbyname("SHA256")) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_dh_kdf_md failed\n"); goto out; } if (EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, OBJ_nid2obj(NID_id_aes256_wrap)) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set0_dh_kdf_oid failed\n"); goto out; } if (EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, sizeof(keybuf1)) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_dh_kdf_outlen failed\n"); goto out; } if (EVP_PKEY_derive_set_peer_ex(ctx, peer_pkey, 1) != 1) { fprintf(stderr, "EVP_PKEY_derive_set_peer_ex failed\n"); goto out; } keylen1 = sizeof(keybuf1); if (EVP_PKEY_derive(ctx, keybuf1, &keylen1) <= 0) { fprintf(stderr, "EVP_PKEY_derive failed\n"); goto out; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Derive with default provider (X9_63 KDF) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_pkey, "provider=default"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_derive_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_derive_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "default") != 0) { fprintf(stderr, "Context is not using the default provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_CTX_set_dh_kdf_type(ctx, EVP_PKEY_DH_KDF_X9_42) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_dh_kdf_type failed\n"); goto out; } if (EVP_PKEY_CTX_set_dh_kdf_md(ctx, EVP_get_digestbyname("SHA256")) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_dh_kdf_md failed\n"); goto out; } if (EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, OBJ_nid2obj(NID_id_aes256_wrap)) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set0_dh_kdf_oid failed\n"); goto out; } if (EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, sizeof(keybuf2)) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_dh_kdf_outlen failed\n"); goto out; } if (EVP_PKEY_derive_set_peer_ex(ctx, peer_pkey, 1) != 1) { fprintf(stderr, "EVP_PKEY_derive_set_peer_ex failed\n"); goto out; } keylen2 = sizeof(keybuf2); if (EVP_PKEY_derive(ctx, keybuf2, &keylen2) <= 0) { fprintf(stderr, "EVP_PKEY_derive failed\n"); goto out; } if (keylen1 != keylen2 || memcmp(keybuf1, keybuf2, keylen1) != 0) { fprintf(stderr, "Derived keys are not equal\n"); goto out; } ret = 1; out: if (peer_pkey) EVP_PKEY_free(peer_pkey); if (dh_pkey) EVP_PKEY_free(dh_pkey); if (ctx) EVP_PKEY_CTX_free(ctx); ERR_print_errors_fp(stderr); return ret; } static const unsigned int required_ica_mechs[] = { RSA_ME }; static const unsigned int required_ica_mechs_len = sizeof(required_ica_mechs) / sizeof(unsigned int); int check_libica() { unsigned int mech_len, i, k, found = 0; libica_func_list_element *mech_list = NULL; int rc; rc = ica_get_functionlist(NULL, &mech_len); if (rc != 0) { fprintf(stderr, "Failed to get function list from libica!\n"); return 77; } mech_list = calloc(sizeof(libica_func_list_element), mech_len); if (mech_list == NULL) { fprintf(stderr, "Failed to allocate memory for function list!\n"); return 77; } rc = ica_get_functionlist(mech_list, &mech_len); if (rc != 0) { fprintf(stderr, "Failed to get function list from libica!\n"); free(mech_list); return 77; } for (i = 0; i < mech_len; i++) { for (k = 0; k < required_ica_mechs_len; k++) { if (mech_list[i].mech_mode_id == required_ica_mechs[k]) { if (mech_list[i].flags & (ICA_FLAG_SW | ICA_FLAG_SHW | ICA_FLAG_DHW)) found++; } } } free(mech_list); if (found < required_ica_mechs_len) { fprintf(stderr, "Libica does not support the required algorithms, skipping.\n"); return 77; } return 0; } int main(int argc, char **argv) { static const struct testparams { int nid; const char *name; } params[] = { {NID_ffdhe2048, "NID_ffdhe2048"}, {NID_ffdhe3072, "NID_ffdhe3072"}, {NID_ffdhe4096, "NID_ffdhe4096"}, {NID_ffdhe6144, "NID_ffdhe6144"}, {NID_ffdhe8192, "NID_ffdhe8192"}, {NID_modp_1536, "NID_modp_1536"}, {NID_modp_2048, "NID_modp_2048"}, {NID_modp_3072, "NID_modp_3072"}, {NID_modp_4096, "NID_modp_4096"}, {NID_modp_6144, "NID_modp_6144"}, {NID_modp_8192, "NID_modp_8192"}, }; UNUSED(argc); UNUSED(argv); int ret = 0, i; /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_CONF"); char *testpath = getenv("IBMCA_TEST_PATH"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } if (testpath && setenv("OPENSSL_MODULES", testpath, 0)) { fprintf(stderr, "Failed to set OPENSSL_MODULES environment variable!\n"); return 77; } ret = check_libica(); if (ret != 0) return ret; setup(); for (i = 0; i < (int)(sizeof(params) / sizeof(struct testparams)); ++i) { if (!check_dhkey(params[i].nid, params[i].name, "DH")) { fprintf(stderr, "Failure for %s (DH)\n", params[i].name); ret = 99; } if (!check_dhkey(params[i].nid, params[i].name, "DHX")) { fprintf(stderr, "Failure for %s (DHX)\n", params[i].name); ret = 99; } } return ret; } openssl-ibmca-2.4.1/test/provider/ecderive.pl000077500000000000000000000035401450276407300212230ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::ecderive("prime192v1", 2); test::ecderivekdf("prime192v1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("secp224r1", 2); test::ecderivekdf("secp224r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("prime256v1", 2); test::ecderivekdf("prime256v1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("secp384r1", 2); test::ecderivekdf("secp384r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("secp521r1", 2); test::ecderivekdf("secp521r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("brainpoolP160r1", 2); test::ecderivekdf("brainpoolP160r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("brainpoolP192r1", 2); test::ecderivekdf("brainpoolP192r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("brainpoolP224r1", 2); test::ecderivekdf("brainpoolP224r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("brainpoolP256r1", 2); test::ecderivekdf("brainpoolP256r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("brainpoolP320r1", 2); test::ecderivekdf("brainpoolP320r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("brainpoolP384r1", 2); test::ecderivekdf("brainpoolP384r1", 2, 200, "X963KDF", "SHA-256"); test::ecderive("brainpoolP512r1", 2); test::ecderivekdf("brainpoolP512r1", 2, 200, "X963KDF", "SHA-256"); openssl-ibmca-2.4.1/test/provider/eckey.c000066400000000000000000000635401450276407300203470ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #include #define UNUSED(var) ((void)(var)) void setup(void) { OPENSSL_load_builtin_modules(); CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); } int check_eckey(int nid, const char *name) { int ret = 0; size_t siglen; unsigned char sigbuf[1024]; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *ec_pkey = NULL; EVP_PKEY *peer_pkey = NULL; size_t keylen1, keylen2; unsigned char keybuf1[512], keybuf2[512]; EVP_MD_CTX *md_ctx = NULL; unsigned char digest[32]; const OSSL_PROVIDER *provider; const char *provname; memset(digest, 0, sizeof(digest)); /* Keygen with IBMCA provider */ ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_name failed\n"); goto out; } if (EVP_PKEY_keygen_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_keygen_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) <= 0) { if (ERR_GET_REASON(ERR_peek_last_error()) == 7) { /* curve not supported => test passed */ fprintf(stderr, "Curve %s not supported by OpenSSL\n", name); ret = 1; } else { fprintf(stderr, "EVP_PKEY_CTX_set_ec_paramgen_curve_nid failed\n"); } goto out; } if (EVP_PKEY_keygen(ctx, &ec_pkey) <= 0) { if (ERR_GET_REASON(ERR_peek_last_error()) == 7) { /* curve not supported => test passed */ fprintf(stderr, "Curve %s not supported by OpenSSL\n", name); ret = 1; } else { fprintf(stderr, "EVP_PKEY_keygen failed\n"); } goto out; } EVP_PKEY_CTX_free(ctx); /* Sign with IBMCA provider */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ec_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_sign_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_sign_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } siglen = sizeof(sigbuf); if (EVP_PKEY_sign(ctx, sigbuf, &siglen, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_PKEY_sign failed\n"); goto out; } EVP_PKEY_CTX_free(ctx); /* Verify with default provider */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ec_pkey, "provider=default"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_verify_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_verify_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "default") != 0) { fprintf(stderr, "Context is not using the default provider, but '%s'\n", provname); goto out; } ret = EVP_PKEY_verify(ctx, sigbuf, siglen, digest, sizeof(digest)); if (ret == -1) { /* error */ fprintf(stderr, "Failed to verify signature with %s (default provider)\n", name); goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Signature incorrect with %s (default provider)\n", name); goto out; } else { /* signature ok */ printf("Signature correct with %s (default provider)\n", name); ret = 0; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Verify with IBMCA provider */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ec_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_verify_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_verify_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } ret = EVP_PKEY_verify(ctx, sigbuf, siglen, digest, sizeof(digest)); if (ret == -1) { /* error */ fprintf(stderr, "Failed to verify signature with %s (ibmca provider)\n", name); goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Signature incorrect with %s (ibmca provider)\n", name); goto out; } else { /* signature ok */ printf("Signature correct with %s (ibmca provider)\n", name); ret = 0; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Digest-Sign with IBMCA provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestSignInit_ex(md_ctx, &ctx, "SHA256", NULL, "?provider=ibmca", ec_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestSignInit_ex failed\n"); ctx = NULL; goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); ctx = NULL; goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_DigestSignUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestSignUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestSignUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestSignUpdate (2) failed\n"); ctx = NULL; goto out; } siglen = sizeof(sigbuf); if (EVP_DigestSignFinal(md_ctx, sigbuf, &siglen) <= 0) { fprintf(stderr, "EVP_DigestSignFinal failed\n"); ctx = NULL; goto out; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Verify with default provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestVerifyInit_ex(md_ctx, &ctx, "SHA256", NULL, "provider=default", ec_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestVerifyInit_ex failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (2) failed\n"); ctx = NULL; goto out; } ret = EVP_DigestVerifyFinal(md_ctx, sigbuf, siglen); if (ret == -1) { /* error */ fprintf(stderr, "Failed to digest-verify signature with %s (default provider)\n", name); ctx = NULL; goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Digest-Signature incorrect with %s (default provider)\n", name); ctx = NULL; goto out; } else { /* signature ok */ printf("Digest-Signature correct with %s (default provider)\n", name); ret = 0; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Verify with IBMCA provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestVerifyInit_ex(md_ctx, &ctx, "SHA256", NULL, "?provider=ibmca", ec_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestVerifyInit_ex failed\n"); ctx = NULL; goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (2) failed\n"); ctx = NULL; goto out; } ret = EVP_DigestVerifyFinal(md_ctx, sigbuf, siglen); if (ret == -1) { /* error */ fprintf(stderr, "Failed to digest-verify signature with %s (IBMCA provider)\n", name); ctx = NULL; goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Digest-Signature incorrect with %s (IBMCA provider)\n", name); ctx = NULL; goto out; } else { /* signature ok */ printf("Digest-Signature correct with %s (IBMCA provider)\n", name); ret = 0; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Sign with default provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestSignInit_ex(md_ctx, &ctx, "SHA256", NULL, "provider=default", ec_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestSignInit_ex failed\n"); ctx = NULL; goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); ctx = NULL; goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "default") != 0) { fprintf(stderr, "Context is not using the default provider, but '%s'\n", provname); goto out; } if (EVP_DigestSignUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestSignUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestSignUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestSignUpdate (2) failed\n"); ctx = NULL; goto out; } siglen = sizeof(sigbuf); if (EVP_DigestSignFinal(md_ctx, sigbuf, &siglen) <= 0) { fprintf(stderr, "EVP_DigestSignFinal failed\n"); ctx = NULL; goto out; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Verify with default provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestVerifyInit_ex(md_ctx, &ctx, "SHA256", NULL, "provider=default", ec_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestVerifyInit_ex failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (2) failed\n"); ctx = NULL; goto out; } ret = EVP_DigestVerifyFinal(md_ctx, sigbuf, siglen); if (ret == -1) { /* error */ fprintf(stderr, "Failed to digest-verify signature with %s (default provider)\n", name); ctx = NULL; goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Digest-Signature incorrect with %s (default provider)\n", name); ctx = NULL; goto out; } else { /* signature ok */ printf("Digest-Signature correct with %s (default provider)\n", name); ret = 0; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Verify with IBMCA provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestVerifyInit_ex(md_ctx, &ctx, "SHA256", NULL, "?provider=ibmca", ec_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestVerifyInit_ex failed\n"); ctx = NULL; goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (2) failed\n"); ctx = NULL; goto out; } ret = EVP_DigestVerifyFinal(md_ctx, sigbuf, siglen); if (ret == -1) { /* error */ fprintf(stderr, "Failed to digest-verify signature with %s (IBMCA provider)\n", name); ctx = NULL; goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Digest-Signature incorrect with %s (IBMCA provider)\n", name); ctx = NULL; goto out; } else { /* signature ok */ printf("Digest-Signature correct with %s (IBMCA provider)\n", name); ret =0; } ctx = NULL; /* Keygen with IBMCA provider (using ec_pkey as template) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ec_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_keygen_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_keygen_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_keygen(ctx, &peer_pkey) <= 0) { if (ERR_GET_REASON(ERR_peek_last_error()) == 7) { /* curve not supported => test passed */ fprintf(stderr, "Curve %s not supported by OpenSSL\n", name); ret = 1; } else { fprintf(stderr, "EVP_PKEY_keygen failed\n"); } goto out; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Derive with IBMCA provider (no KDF) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ec_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_derive_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_derive_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_derive_set_peer_ex(ctx, peer_pkey, 1) != 1) { fprintf(stderr, "EVP_PKEY_derive_set_peer_ex failed\n"); goto out; } keylen1 = sizeof(keybuf1); if (EVP_PKEY_derive(ctx, keybuf1, &keylen1) <= 0) { fprintf(stderr, "EVP_PKEY_derive failed\n"); goto out; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Derive with default provider (no KDF) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ec_pkey, "provider=default"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_derive_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_derive_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "default") != 0) { fprintf(stderr, "Context is not using the default provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_derive_set_peer_ex(ctx, peer_pkey, 1) != 1) { fprintf(stderr, "EVP_PKEY_derive_set_peer_ex failed\n"); goto out; } keylen2 = sizeof(keybuf2); if (EVP_PKEY_derive(ctx, keybuf2, &keylen2) <= 0) { fprintf(stderr, "EVP_PKEY_derive failed\n"); goto out; } if (keylen1 != keylen2 || memcmp(keybuf1, keybuf2, keylen1) != 0) { fprintf(stderr, "Derived keys are not equal\n"); goto out; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Derive with IBMCA provider (X9_63 KDF) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ec_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_derive_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_derive_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, EVP_PKEY_ECDH_KDF_X9_63) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_ecdh_kdf_type failed\n"); goto out; } if (EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, EVP_get_digestbyname("SHA256")) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_ecdh_kdf_md failed\n"); goto out; } if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, sizeof(keybuf1)) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_ecdh_kdf_outlen failed\n"); goto out; } if (EVP_PKEY_derive_set_peer_ex(ctx, peer_pkey, 1) != 1) { fprintf(stderr, "EVP_PKEY_derive_set_peer_ex failed\n"); goto out; } keylen1 = sizeof(keybuf1); if (EVP_PKEY_derive(ctx, keybuf1, &keylen1) <= 0) { fprintf(stderr, "EVP_PKEY_derive failed\n"); goto out; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Derive with default provider (X9_63 KDF) */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ec_pkey, "provider=default"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_derive_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_derive_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "default") != 0) { fprintf(stderr, "Context is not using the default provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, EVP_PKEY_ECDH_KDF_X9_63) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_ecdh_kdf_type failed\n"); goto out; } if (EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, EVP_get_digestbyname("SHA256")) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_ecdh_kdf_md failed\n"); goto out; } if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, sizeof(keybuf2)) != 1) { fprintf(stderr, "EVP_PKEY_CTX_set_ecdh_kdf_outlen failed\n"); goto out; } if (EVP_PKEY_derive_set_peer_ex(ctx, peer_pkey, 1) != 1) { fprintf(stderr, "EVP_PKEY_derive_set_peer_ex failed\n"); goto out; } keylen2 = sizeof(keybuf2); if (EVP_PKEY_derive(ctx, keybuf2, &keylen2) <= 0) { fprintf(stderr, "EVP_PKEY_derive failed\n"); goto out; } if (keylen1 != keylen2 || memcmp(keybuf1, keybuf2, keylen1) != 0) { fprintf(stderr, "Derived keys are not equal\n"); goto out; } ret = 1; out: if (peer_pkey) EVP_PKEY_free(peer_pkey); if (ec_pkey) EVP_PKEY_free(ec_pkey); if (ctx) EVP_PKEY_CTX_free(ctx); if (md_ctx) EVP_MD_CTX_free(md_ctx); ERR_print_errors_fp(stderr); return ret; } static const unsigned int required_ica_mechs[] = { EC_DH, EC_DSA_SIGN, EC_DSA_VERIFY, EC_KGEN, }; static const unsigned int required_ica_mechs_len = sizeof(required_ica_mechs) / sizeof(unsigned int); int check_libica() { unsigned int mech_len, i, k, found = 0; libica_func_list_element *mech_list = NULL; int rc; rc = ica_get_functionlist(NULL, &mech_len); if (rc != 0) { fprintf(stderr, "Failed to get function list from libica!\n"); return 77; } mech_list = calloc(sizeof(libica_func_list_element), mech_len); if (mech_list == NULL) { fprintf(stderr, "Failed to allocate memory for function list!\n"); return 77; } rc = ica_get_functionlist(mech_list, &mech_len); if (rc != 0) { fprintf(stderr, "Failed to get function list from libica!\n"); free(mech_list); return 77; } for (i = 0; i < mech_len; i++) { for (k = 0; k < required_ica_mechs_len; k++) { if (mech_list[i].mech_mode_id == required_ica_mechs[k]) { if (mech_list[i].flags & (ICA_FLAG_SW | ICA_FLAG_SHW | ICA_FLAG_DHW)) found++; } } } free(mech_list); if (found < required_ica_mechs_len) { fprintf(stderr, "Libica does not support the required algorithms, skipping.\n"); return 77; } return 0; } int main(int argc, char **argv) { static const struct testparams { int nid; const char *name; } params[] = { {NID_X9_62_prime192v1, "NID_X9_62_prime192v1"}, {NID_secp224r1, "NID_secp224r1"}, {NID_X9_62_prime256v1, "NID_X9_62_prime256v1"}, {NID_secp384r1, "NID_secp384r1"}, {NID_secp521r1, "NID_secp521r1"}, {NID_brainpoolP160r1, "NID_brainpoolP160r1"}, {NID_brainpoolP192r1, "NID_brainpoolP192r1"}, {NID_brainpoolP224r1, "NID_brainpoolP224r1"}, {NID_brainpoolP256r1, "NID_brainpoolP256r1"}, {NID_brainpoolP320r1, "NID_brainpoolP320r1"}, {NID_brainpoolP384r1, "NID_brainpoolP384r1"}, {NID_brainpoolP512r1, "NID_brainpoolP512r1"} }; UNUSED(argc); UNUSED(argv); int ret = 0, i; /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_CONF"); char *testpath = getenv("IBMCA_TEST_PATH"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } if (testpath && setenv("OPENSSL_MODULES", testpath, 0)) { fprintf(stderr, "Failed to set OPENSSL_MODULES environment variable!\n"); return 77; } ret = check_libica(); if (ret != 0) return ret; setup(); for (i = 0; i < (int)(sizeof(params) / sizeof(struct testparams)); ++i) { if (!check_eckey(params[i].nid, params[i].name)) { fprintf(stderr, "Failure for %s\n", params[i].name); ret = 99; } } return ret; } openssl-ibmca-2.4.1/test/provider/ecsign.pl000077500000000000000000000024741450276407300207120ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::ecsignverify("prime192v1", 8, 200, "SHA-256"); test::ecsignverify("secp224r1", 8, 200, "SHA-256"); test::ecsignverify("prime256v1", 8, 200, "SHA-256"); test::ecsignverify("secp384r1", 8, 200, "SHA-256"); test::ecsignverify("secp521r1", 8, 200, "SHA-256"); test::ecsignverify("brainpoolP160r1", 8, 200, "SHA-256"); test::ecsignverify("brainpoolP192r1", 8, 200, "SHA-256"); test::ecsignverify("brainpoolP224r1", 8, 200, "SHA-256"); test::ecsignverify("brainpoolP256r1", 8, 200, "SHA-256"); test::ecsignverify("brainpoolP320r1", 8, 200, "SHA-256"); test::ecsignverify("brainpoolP384r1", 8, 200, "SHA-256"); test::ecsignverify("brainpoolP512r1", 8, 200, "SHA-256"); openssl-ibmca-2.4.1/test/provider/openssl-test.cnf000066400000000000000000000007161450276407300222270ustar00rootroot00000000000000openssl_conf = openssl_def [openssl_def] providers = provider_sect alg_section = evp_properties [provider_sect] default = default_sect ibmca_provider = ibmca_sect [default_sect] activate = 1 [ibmca_sect] identity = ibmca module = ibmca-provider.so activate = 1 #debug = yes #debug-path = /dir/to/debug/directory #fips=yes #algorithms = RSA,EC,DH algorithms = ALL #fallback-properties = provider=default [evp_properties] default_properties = ?provider=ibmca openssl-ibmca-2.4.1/test/provider/rsa-implrej-bad-empty-in.bin000066400000000000000000000004001450276407300242700ustar00rootroot00000000000000 ª¨­»Å“©$º\yµÂ$*乿6¡šL÷Tí¼îwNG/à(Ô&4ø†IËQ@Úd,®jèÇЇÊëϦÚÑUá04I‰¡ÔbÔEö993E g¼m9Øõ ʼ%sy%¡Ï!åÆªW·vŸj*X=—ÌàÀø¶­Õð²½€¾æ7ª9» qŸçWIô¼NBFnõ¨a®:’9\}…C þ8D^©?¢•‹P59€ú\åøÏQúq©6ËOEuèÞkM? ná@¹8ý/PîðÐP".*r°£Ÿó¦sŽ‚ÈpÊ¥®Ôü¾ˆ,Idj¢P¹øy쪅:!õC~{­ `H.`˜ùØi##œ‡†îr‚…¯Ð“}Þq(8˜C×7Y°{™OÛü틦e1CgèÅùÒ˜Q(þëFËPü#~dCІßÐ “d®:„-wS+f·ï&;ƒ±TÖq± ßÖ`F.!¤î{–NsJ{ÖݦpeŠ<$)HS-£&Hh~(dsöu´ÖF?×`£XßÊÓÍ¢¯îÅâh£}% 7÷"ôh§ ý’×)L<áçø„;}ùó~óWH\ÜßëNxVsopenssl-ibmca-2.4.1/test/provider/rsa-implrej-bad-max-out.bin000066400000000000000000000003651450276407300241320ustar00rootroot00000000000000"ØP{žëà’²O`-Å»yÁkØÛòg±ÒùÂä½}%’ÏS!àó5WVY#Ç:Ôðœ "¾¨‘H>`1p(³ª&‘Éy91×á_@gæ9y³'QeŽ÷iaé|ùÎó'‹1Ó„;‚ÂQÂ0TÈö„0æ1ªÖ>pâ[ÍŽûTÉ.ÆÓ±¢øæNï÷Ó„•°üPÉq8¯K g¡Äâ{{„93.ߨ`þ®e<Ö¦(¬U•÷çCä,h"4‡ %vÏ.㽦Ÿg?ø·É\—™ç£¾¥çä¡ÃYw/¶±ÆæÅfþ0Ãopenssl-ibmca-2.4.1/test/provider/rsa-implrej-bad-prf-in.bin000066400000000000000000000004001450276407300237210ustar00rootroot000000000000009àŒ?„Á§þÇLàv²öúNŒ*lÿÜ5 ؈ž]š• d%y…Ô¾8ÓêV•ñ>ÍL³‰Ñÿ[‚HKIMb€«§ŽdY3˜¹4Ìè¿ÍLÀæï¤z® ¯cŠÑcÒÓ6a†Ð }ðÈlŸ1qÏ5aG.˜¦k÷]ÛE{ímÌá™6çÙNòÆŽ„gî”y*x‘º\@ʱIáÄ8Ën®¤÷lâ<ÎH?ðéo§ê¾gg4- #ô¢b¶.ró¦|Ò‰qÈU©í"T"ù‹o°€¨ ½o߈ØÏÖ|’C¾×…§ªö¼™×Úq¼ßb~sTopenssl-ibmca-2.4.1/test/provider/rsa-implrej-bad-prf-out.bin000066400000000000000000000000021450276407300241200ustar00rootroot00000000000000›openssl-ibmca-2.4.1/test/provider/rsa-implrej-good-in.bin000066400000000000000000000004001450276407300233360ustar00rootroot00000000000000‹þ&N…ӽꦸ…Ž;•nãÒ&ý?i:†ˆs¢sÙòƒ²î½Ñí5÷à-‘Åq˜g7Õ2 Ø9k:Õ°Úì «<»À&9_OÑOg?-üù¶`ì&¬8m³)›NF Cú¹•]ò³Ïª éᜅb8ý7™Â¿,èÈh·gTåÛ;e3ý`7F¾Á N>`"ëÉÒ *2²¤ÍS³ôL¡Ã'Ò¶QX!Àƒ–Èqöe4œ%äM'3Í“˜\îöC <õzõú"@‰"ú4s|yÄFÒŠ”Ä–äé*Å?¼ó„Þ¨Až ‰øxDE¤’Èë @”g÷Zý}Mxˆb fopenssl-ibmca-2.4.1/test/provider/rsa-implrej-good-out.bin000066400000000000000000000000321450276407300235400ustar00rootroot00000000000000lorem ipsum dolor sit ametopenssl-ibmca-2.4.1/test/provider/rsa-implrej-key.pem000066400000000000000000000041161450276407300226130ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAyMyDlxQJjaVsqiNkD5PciZfBY3KWj8Gwxt9RE8HJTosh5IrS KX5lQZARtObY9ec7G3iyV0ADIdHva2AtTsjOjRQclJBetK0wZjmkkgZTS25/JgdC Ppff/RM8iNchOZ3vvH6WzNy9fzquH+iScSv7SSmBfVEWZkQKH6y3ogj16hZZEK3Y o/LUlyAjYMy2MgJPDQcWnBkY8xb3lLFDrvVOyHUipMApePlomYC/+/ZJwwfoGBm/ +IQJY41IvZS+FStZ/2SfoL1inQ/6GBPDq/S1a9PC6lRl3/oUWJKSqdiiStJr5+4F EHQbY4LUPIPVv6QKRmE9BivkRVF9vK8MtOGnaQIDAQABAoIBABRVAQ4PLVh2Y6Zm pv8czbvw7dgQBkbQKgI5IpCJksStOeVWWSlybvZQjDpxFY7wtv91HTnQdYC7LS8G MhBELQYD/1DbvXs1/iybsZpHoa+FpMJJAeAsqLWLeRmyDt8yqs+/Ua20vEthubfp aMqk1XD3DvGNgGMiiJPkfUOe/KeTJZvPLNEIo9hojN8HjnrHmZafIznSwfUiuWlo RimpM7quwmgWJeq4T05W9ER+nYj7mhmc9xAj4OJXsURBszyE07xnyoAx0mEmGBA6 egpAhEJi912IkM1hblH5A1SI/W4Jnej/bWWk/xGCVIB8n1jS+7qLoVHcjGi+NJyX eiBOBMECgYEA+PWta6gokxvqRZuKP23AQdI0gkCcJXHpY/MfdIYColY3GziD7UWe z5cFJkWe3RbgVSL1pF2UdRsuwtrycsf4gWpSwA0YCAFxY02omdeXMiL1G5N2MFSG lqn32MJKWUl8HvzUVc+5fuhtK200lyszL9owPwSZm062tcwLsz53Yd0CgYEAznou O0mpC5YzChLcaCvfvfuujdbcA7YUeu+9V1dD8PbaTYYjUGG3Gv2crS00Al5WrIaw 93Q+s14ay8ojeJVCRGW3Bu0iF15XGMjHC2cD6o9rUQ+UW+SOWja7PDyRcytYnfwF 1y2AkDGURSvaITSGR+xylD8RqEbmL66+jrU2sP0CgYB2/hXxiuI5zfHfa0RcpLxr uWjXiMIZM6T13NKAAz1nEgYswIpt8gTB+9C+RjB0Q+bdSmRWN1Qp1OA4yiVvrxyb 3pHGsXt2+BmV+RxIy768e/DjSUwINZ5OjNalh9e5bWIh/X4PtcVXXwgu5XdpeYBx sru0oyI4FRtHMUu2VHkDEQKBgQCZiEiwVUmaEAnLx9KUs2sf/fICDm5zZAU+lN4a AA3JNAWH9+JydvaM32CNdTtjN3sDtvQITSwCfEs4lgpiM7qe2XOLdvEOp1vkVgeL 9wH2fMaz8/3BhuZDNsdrNy6AkQ7ICwrcwj0C+5rhBIaigkgHW06n5W3fzziC5FFW FHGikQKBgGQ790ZCn32DZnoGUwITR++/wF5jUfghqd67YODszeUAWtnp7DHlWPfp LCkyjnRWnXzvfHTKvCs1XtQBoaCRS048uwZITlgZYFEWntFMqi76bqBE4FTSYUTM FinFUBBVigThM/RLfCRNrCW/kTxXuJDuSfVIJZzWNAT+9oWdz5da -----END RSA PRIVATE KEY----- -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMyDlxQJjaVsqiNkD5Pc iZfBY3KWj8Gwxt9RE8HJTosh5IrSKX5lQZARtObY9ec7G3iyV0ADIdHva2AtTsjO jRQclJBetK0wZjmkkgZTS25/JgdCPpff/RM8iNchOZ3vvH6WzNy9fzquH+iScSv7 SSmBfVEWZkQKH6y3ogj16hZZEK3Yo/LUlyAjYMy2MgJPDQcWnBkY8xb3lLFDrvVO yHUipMApePlomYC/+/ZJwwfoGBm/+IQJY41IvZS+FStZ/2SfoL1inQ/6GBPDq/S1 a9PC6lRl3/oUWJKSqdiiStJr5+4FEHQbY4LUPIPVv6QKRmE9BivkRVF9vK8MtOGn aQIDAQAB -----END PUBLIC KEY----- openssl-ibmca-2.4.1/test/provider/rsa16k.pl000077500000000000000000000016061450276407300205450ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::rsaencdec("16384", 2, 2037); test::rsaoaepencdec("16384", 2, 200, "SHA-256"); test::rsasignverify("16384", 2, 64); test::rsapsssignverify("16384", 2, 100, "SHA-256", 25); test::rsax931signverify("16384", 2, 100, "SHA-256"); openssl-ibmca-2.4.1/test/provider/rsa1k.pl000077500000000000000000000016021450276407300204530ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::rsaencdec("1024", 10, 64); test::rsaoaepencdec("1024", 10, 60, "SHA-256"); test::rsasignverify("1024", 10, 64); test::rsapsssignverify("1024", 10, 100, "SHA-256", 25); test::rsax931signverify("1024", 10, 100, "SHA-256"); openssl-ibmca-2.4.1/test/provider/rsa2k.pl000077500000000000000000000016041450276407300204560ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::rsaencdec("2048", 10, 245); test::rsaoaepencdec("2048", 10, 180, "SHA-256"); test::rsasignverify("2048", 10, 64); test::rsapsssignverify("2048", 10, 100, "SHA-256", 25); test::rsax931signverify("2048", 10, 100, "SHA-256"); openssl-ibmca-2.4.1/test/provider/rsa4k.pl000077500000000000000000000016051450276407300204610ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::rsaencdec("4096", 10, 501); test::rsaoaepencdec("4096", 10, 200, "SHA-256"); test::rsasignverify("4096", 10, 64); test::rsapsssignverify("4096", 10, 100, "SHA-256", 25); test::rsax931signverify("4096", 10, 100, "SHA-256"); openssl-ibmca-2.4.1/test/provider/rsa512.pl000077500000000000000000000015731450276407300204560ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::rsaencdec("512", 10, 20); test::rsaoaepencdec("512", 10, 10, "SHA-1"); test::rsasignverify("512", 10, 20); test::rsapsssignverify("512", 10, 100, "SHA-256", 25); test::rsax931signverify("512", 10, 100, "SHA-256"); openssl-ibmca-2.4.1/test/provider/rsa8k.pl000077500000000000000000000016001450276407300204600ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; test::rsaencdec("8192", 2, 1013); test::rsaoaepencdec("8192", 2, 200, "SHA-256"); test::rsasignverify("8192", 2, 64); test::rsapsssignverify("8192", 2, 100, "SHA-256", 25); test::rsax931signverify("8192", 2, 100, "SHA-256"); openssl-ibmca-2.4.1/test/provider/rsaimplrej.pl000077500000000000000000000030361450276407300216050ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2023-2023] 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. # use strict; use warnings; use test; use FindBin; # RSA implicit rejection - random positive test case test::rsaimplrej("$FindBin::Bin/rsa-implrej-key.pem", "$FindBin::Bin/rsa-implrej-good-in.bin", "$FindBin::Bin/rsa-implrej-good-out.bin"); # RSA implicit rejection - random negative test case decrypting to empty test::rsaimplrej("$FindBin::Bin/rsa-implrej-key.pem", "$FindBin::Bin/rsa-implrej-bad-empty-in.bin", "$FindBin::Bin/rsa-implrej-bad-empty-out.bin"); # RSA implicit rejection - invalid decrypting to max length message test::rsaimplrej("$FindBin::Bin/rsa-implrej-key.pem", "$FindBin::Bin/rsa-implrej-bad-max-in.bin", "$FindBin::Bin/rsa-implrej-bad-max-out.bin"); # RSA implicit rejection - invalid decrypting to message with length specified by second to last value from PRF test::rsaimplrej("$FindBin::Bin/rsa-implrej-key.pem", "$FindBin::Bin/rsa-implrej-bad-prf-in.bin", "$FindBin::Bin/rsa-implrej-bad-prf-out.bin"); openssl-ibmca-2.4.1/test/provider/rsakey.c000066400000000000000000000614211450276407300205410ustar00rootroot00000000000000/* * Copyright [2021-2022] 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 #include #define UNUSED(var) ((void)(var)) void setup(void) { OPENSSL_load_builtin_modules(); CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); } int check_rsakey(int bits, const char *algo, const char *name) { int ret = 0; size_t siglen; unsigned char sigbuf[1024]; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *rsa_pkey = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char digest[32]; const OSSL_PROVIDER *provider; const char *provname; memset(digest, 0, sizeof(digest)); /* Keygen with IBMCA provider */ ctx = EVP_PKEY_CTX_new_from_name(NULL, algo, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_name failed\n"); goto out; } if (EVP_PKEY_keygen_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_keygen_init failed\n"); goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_keygen_bits failed\n"); goto out; } if (strcmp(algo, "RSA-PSS") == 0) { /* generate a PSS restricted RSA-PSS key */ if (EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(ctx, "SHA256", NULL) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_keygen_md_name failed\n"); goto out; } if (EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(ctx, "SHA256") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name failed\n"); goto out; } if (EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen failed\n"); goto out; } } if (EVP_PKEY_keygen(ctx, &rsa_pkey) <= 0) { fprintf(stderr, "EVP_PKEY_keygen failed\n"); goto out; } EVP_PKEY_CTX_free(ctx); /* Sign with IBMCA provider */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, rsa_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_sign_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_sign_init failed\n"); goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "?provider=ibmca") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); goto out; } } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } siglen = sizeof(sigbuf); if (EVP_PKEY_sign(ctx, sigbuf, &siglen, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_PKEY_sign failed\n"); goto out; } EVP_PKEY_CTX_free(ctx); /* Verify with default provider */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, rsa_pkey, "provider=default"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_verify_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_verify_init failed\n"); goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "provider=default") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); goto out; } } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "default") != 0) { fprintf(stderr, "Context is not using the default provider, but '%s'\n", provname); goto out; } ret = EVP_PKEY_verify(ctx, sigbuf, siglen, digest, sizeof(digest)); if (ret == -1) { /* error */ fprintf(stderr, "Failed to verify signature with %s (default provider)\n", name); goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Signature incorrect with %s (default provider)\n", name); goto out; } else { /* signature ok */ printf("Signature correct with %s (default provider)\n", name); ret = 0; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Verify with IBMCA provider */ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, rsa_pkey, "?provider=ibmca"); if (ctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_verify_init(ctx) <= 0) { fprintf(stderr, "EVP_PKEY_verify_init failed\n"); goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "provider=default") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); goto out; } } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } ret = EVP_PKEY_verify(ctx, sigbuf, siglen, digest, sizeof(digest)); if (ret == -1) { /* error */ fprintf(stderr, "Failed to verify signature with %s (ibmca provider)\n", name); goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Signature incorrect with %s (ibmca provider)\n", name); goto out; } else { /* signature ok */ printf("Signature correct with %s (ibmca provider)\n", name); ret = 0; } EVP_PKEY_CTX_free(ctx); ctx = NULL; /* Digest-Sign with IBMCA provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestSignInit_ex(md_ctx, &ctx, "SHA256", NULL, "?provider=ibmca", rsa_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestSignInit_ex failed\n"); ctx = NULL; goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); ctx = NULL; goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "?provider=ibmca") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); ctx = NULL; goto out; } } if (EVP_DigestSignUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestSignUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestSignUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestSignUpdate (2) failed\n"); ctx = NULL; goto out; } siglen = sizeof(sigbuf); if (EVP_DigestSignFinal(md_ctx, sigbuf, &siglen) <= 0) { fprintf(stderr, "EVP_DigestSignFinal failed\n"); ctx = NULL; goto out; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Verify with default provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestVerifyInit_ex(md_ctx, &ctx, "SHA256", NULL, "provider=default", rsa_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestVerifyInit_ex failed\n"); ctx = NULL; goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "?provider=ibmca") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); ctx = NULL; goto out; } } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (2) failed\n"); ctx = NULL; goto out; } ret = EVP_DigestVerifyFinal(md_ctx, sigbuf, siglen); if (ret == -1) { /* error */ fprintf(stderr, "Failed to digest-verify signature with %s (default provider)\n", name); ctx = NULL; goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Digest-Signature incorrect with %s (default provider)\n", name); ctx = NULL; goto out; } else { /* signature ok */ printf("Digest-Signature correct with %s (default provider)\n", name); ret = 0; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Verify with IBMCA provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestVerifyInit_ex(md_ctx, &ctx, "SHA256", NULL, "?provider=ibmca", rsa_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestVerifyInit_ex failed\n"); ctx = NULL; goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "?provider=ibmca") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); ctx = NULL; goto out; } } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (2) failed\n"); ctx = NULL; goto out; } ret = EVP_DigestVerifyFinal(md_ctx, sigbuf, siglen); if (ret == -1) { /* error */ fprintf(stderr, "Failed to digest-verify signature with %s (IBMCA provider)\n", name); ctx = NULL; goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Digest-Signature incorrect with %s (IBMCA provider)\n", name); ctx = NULL; goto out; } else { /* signature ok */ printf("Digest-Signature correct with %s (IBMCA provider)\n", name); ret = 0; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Sign with default provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestSignInit_ex(md_ctx, &ctx, "SHA256", NULL, "provider=default", rsa_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestSignInit_ex failed\n"); ctx = NULL; goto out; } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); ctx = NULL; goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "default") != 0) { fprintf(stderr, "Context is not using the default provider, but '%s'\n", provname); goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "?provider=ibmca") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); ctx = NULL; goto out; } } if (EVP_DigestSignUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestSignUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestSignUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestSignUpdate (2) failed\n"); ctx = NULL; goto out; } siglen = sizeof(sigbuf); if (EVP_DigestSignFinal(md_ctx, sigbuf, &siglen) <= 0) { fprintf(stderr, "EVP_DigestSignFinal failed\n"); ctx = NULL; goto out; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Verify with default provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestVerifyInit_ex(md_ctx, &ctx, "SHA256", NULL, "provider=default", rsa_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestVerifyInit_ex failed\n"); ctx = NULL; goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "?provider=ibmca") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); ctx = NULL; goto out; } } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (2) failed\n"); ctx = NULL; goto out; } ret = EVP_DigestVerifyFinal(md_ctx, sigbuf, siglen); if (ret == -1) { /* error */ fprintf(stderr, "Failed to digest-verify signature with %s (default provider)\n", name); ctx = NULL; goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Digest-Signature incorrect with %s (default provider)\n", name); ctx = NULL; goto out; } else { /* signature ok */ printf("Digest-Signature correct with %s (default provider)\n", name); ret = 0; } EVP_MD_CTX_free(md_ctx); ctx = NULL; /* Digest-Verify with IBMCA provider */ md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { fprintf(stderr, "EVP_MD_CTX_new failed\n"); goto out; } if (EVP_DigestVerifyInit_ex(md_ctx, &ctx, "SHA256", NULL, "?provider=ibmca", rsa_pkey, NULL) == 0) { fprintf(stderr, "EVP_DigestVerifyInit_ex failed\n"); ctx = NULL; goto out; } if (strcmp(algo, "RSA-PSS") == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_padding failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, "SHA256", "?provider=ibmca") <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_mgf1_md_name failed\n"); ctx = NULL; goto out; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 24) <= 0) { fprintf(stderr, "EVP_PKEY_CTX_set_rsa_pss_saltlen failed\n"); ctx = NULL; goto out; } } provider = EVP_PKEY_CTX_get0_provider(ctx); if (provider == NULL) { fprintf(stderr, "Context is not a provider-context\n"); goto out; } provname = OSSL_PROVIDER_get0_name(provider); if (strcmp(provname, "ibmca") != 0) { fprintf(stderr, "Context is not using the IBMCA provider, but '%s'\n", provname); goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (1) failed\n"); ctx = NULL; goto out; } if (EVP_DigestVerifyUpdate(md_ctx, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_DigestVerifyUpdate (2) failed\n"); ctx = NULL; goto out; } ret = EVP_DigestVerifyFinal(md_ctx, sigbuf, siglen); if (ret == -1) { /* error */ fprintf(stderr, "Failed to digest-verify signature with %s (IBMCA provider)\n", name); ctx = NULL; goto out; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Digest-Signature incorrect with %s (IBMCA provider)\n", name); ctx = NULL; goto out; } else { /* signature ok */ printf("Digest-Signature correct with %s (IBMCA provider)\n", name); ret = 0; } ctx = NULL; ret = 1; out: if (rsa_pkey) EVP_PKEY_free(rsa_pkey); if (ctx) EVP_PKEY_CTX_free(ctx); if (md_ctx) EVP_MD_CTX_free(md_ctx); ERR_print_errors_fp(stderr); return ret; } static const unsigned int required_ica_mechs[] = { RSA_ME, RSA_CRT }; static const unsigned int required_ica_mechs_len = sizeof(required_ica_mechs) / sizeof(unsigned int); int check_libica() { unsigned int mech_len, i, k, found = 0; libica_func_list_element *mech_list = NULL; int rc; rc = ica_get_functionlist(NULL, &mech_len); if (rc != 0) { fprintf(stderr, "Failed to get function list from libica!\n"); return 77; } mech_list = calloc(sizeof(libica_func_list_element), mech_len); if (mech_list == NULL) { fprintf(stderr, "Failed to allocate memory for function list!\n"); return 77; } rc = ica_get_functionlist(mech_list, &mech_len); if (rc != 0) { fprintf(stderr, "Failed to get function list from libica!\n"); free(mech_list); return 77; } for (i = 0; i < mech_len; i++) { for (k = 0; k < required_ica_mechs_len; k++) { if (mech_list[i].mech_mode_id == required_ica_mechs[k]) { if (mech_list[i].flags & (ICA_FLAG_SW | ICA_FLAG_SHW | ICA_FLAG_DHW)) found++; } } } free(mech_list); if (found < required_ica_mechs_len) { fprintf(stderr, "Libica does not support the required algorithms, skipping.\n"); return 77; } return 0; } int main(int argc, char **argv) { static const struct testparams { int bits; const char *algo; const char *name; } params[] = { {512, "RSA", "RSA-512"}, {1024, "RSA", "RSA-1024"}, {2048, "RSA", "RSA-2048"}, {4096, "RSA", "RSA-4096"}, {512, "RSA-PSS", "RSA-PSS-512"}, {1024, "RSA-PSS", "RSA-PSS-1024"}, {2048, "RSA-PSS", "RSA-PSS-2048"}, {4096, "RSA-PSS", "RSA-PSS-4096"}, }; UNUSED(argc); UNUSED(argv); int ret = 0, i; /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_CONF"); char *testpath = getenv("IBMCA_TEST_PATH"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } if (testpath && setenv("OPENSSL_MODULES", testpath, 0)) { fprintf(stderr, "Failed to set OPENSSL_MODULES environment variable!\n"); return 77; } ret = check_libica(); if (ret != 0) return ret; setup(); for (i = 0; i < (int)(sizeof(params) / sizeof(struct testparams)); ++i) { if (!check_rsakey(params[i].bits, params[i].algo, params[i].name)) { fprintf(stderr, "Failure for %s\n", params[i].name); ret = 99; } } return ret; } openssl-ibmca-2.4.1/test/provider/server-cert-ec.pem000066400000000000000000000017511450276407300224300ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICtjCCAlugAwIBAgIUZKDDTgiMEBhW4cW1fDdYk8Zp4RMwCgYIKoZIzj0EAwIw fzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMREwDwYDVQQHDAhOZXcgWW9yazEV MBMGA1UECgwMRXhhbXBsZSwgTExDMRgwFgYDVQQDDA9FeGFtcGxlIENvbXBhbnkx HzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wHhcNMjIwMTEyMDkwNTE4 WhcNMjQxMDA4MDkwNTE4WjB/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkxETAP BgNVBAcMCE5ldyBZb3JrMRUwEwYDVQQKDAxFeGFtcGxlLCBMTEMxGDAWBgNVBAMM D0V4YW1wbGUgQ29tcGFueTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNv bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGZd6YEJHN/KruZK9+R+5KOhVMvD 3MTbi7dDuPBTnBGpyS151/LvH6QMAtq08uMvePGIXYG4G0kwVoL7nXEGomKjgbQw gbEwHQYDVR0OBBYEFDTzrZFKewJscQkcECACxyU4rcHHMAkGA1UdEwQCMAAwCwYD VR0PBAQDAgWgMEoGA1UdEQRDMEGCC2V4YW1wbGUuY29tgg93d3cuZXhhbXBsZS5j b22CEG1haWwuZXhhbXBsZS5jb22CD2Z0cC5leGFtcGxlLmNvbTAsBglghkgBhvhC AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwCgYIKoZIzj0EAwID SQAwRgIhAMYwfXPr7QWZp2uZ6PeYy7kUSr9OmC7bRGLDWVi5Y8XWAiEA91Hh8UOa KCOo8mbFyeRrrgFMt+82P3baa9pzKhl+KF0= -----END CERTIFICATE----- openssl-ibmca-2.4.1/test/provider/server-cert-rsa.pem000066400000000000000000000030011450276407300226140ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEQTCCAymgAwIBAgIUEb+BhAFigO+vYunYfkVYVoCpVkcwDQYJKoZIhvcNAQEL BQAwfzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMREwDwYDVQQHDAhOZXcgWW9y azEVMBMGA1UECgwMRXhhbXBsZSwgTExDMRgwFgYDVQQDDA9FeGFtcGxlIENvbXBh bnkxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wHhcNMjIwMTEyMDg0 MjM2WhcNMjQxMDA4MDg0MjM2WjB/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkx ETAPBgNVBAcMCE5ldyBZb3JrMRUwEwYDVQQKDAxFeGFtcGxlLCBMTEMxGDAWBgNV BAMMD0V4YW1wbGUgQ29tcGFueTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxl LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMeMOu0OlFMmDD35 HYS4SHY3U7Z2NlYhhx7UIuBVLJ5sXleynXtCXBSKic4/jYV8wvGPxAlxTpA1JgrO SCvSPkw/6hcC3UjvdXaFBYm0dYNSkaSzU5mK7jB1oj1RmOBoojyXm09Wou6kW4yb Rg/z7vP2tbICa8EV4EiRmI8YM0BWaHOyAQiUMQRSKmrmQX8oTyKPeGS/Au+8md2S nxF1XHFDiK1+5vpE22DA7F0ErkSbPuLssuthni+W0xWPNMFBlV6pt9gdEsSYlkGr YpMIB6oevWGxMQa3+79f2rxjKz4B3b/xlU/V+ANeB8C3MEx7XTWE71TM68pPILRI 9fXN6mMCAwEAAaOBtDCBsTAdBgNVHQ4EFgQUjyFE+3GAhb9y5p/qY38tVO4uMiow CQYDVR0TBAIwADALBgNVHQ8EBAMCBaAwSgYDVR0RBEMwQYILZXhhbXBsZS5jb22C D3d3dy5leGFtcGxlLmNvbYIQbWFpbC5leGFtcGxlLmNvbYIPZnRwLmV4YW1wbGUu Y29tMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0 ZTANBgkqhkiG9w0BAQsFAAOCAQEAGua+EFwg8RUK80AA2uJzT/KAsqn0uLTX2kCs ca/tkOT7ou2jsJDoAZnpCQYGUgCgroEcmVexesUjFcOUjv4xZJuiXqIKhP7d5vqQ NIZOOwx56PqqEcwADRkeHEsEGbOSQS02Ts0+D4pMVwfYrvMmsLfwC+X0szQTaLu8 SMFgSaUg89sC+qpCsEsS+R06NEfzEnz3fgT+F5uKpBMGwMPel6LpVLsMNyidEnAW L4hPXZKUSY4jbKUxfS9b9vpsZbGvBuU+evMe8XABAjTcxLbSDWxzQ4VdQzIhRx6d V/kWkUl6pZg1hL9393UbNjSEILbdLtsdc/t3S/yFh5d03F40BA== -----END CERTIFICATE----- openssl-ibmca-2.4.1/test/provider/server-key-ec.pem000066400000000000000000000003611450276407300222570ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgrsX231aJljHPR1Xf 135Xz+Ll0f86PE0es2bfiI4oRxOhRANCAARmXemBCRzfyq7mSvfkfuSjoVTLw9zE 24u3Q7jwU5wRqcktedfy7x+kDALatPLjL3jxiF2BuBtJMFaC+51xBqJi -----END PRIVATE KEY----- openssl-ibmca-2.4.1/test/provider/server-key-rsa.pem000066400000000000000000000032501450276407300224550ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHjDrtDpRTJgw9 +R2EuEh2N1O2djZWIYce1CLgVSyebF5Xsp17QlwUionOP42FfMLxj8QJcU6QNSYK zkgr0j5MP+oXAt1I73V2hQWJtHWDUpGks1OZiu4wdaI9UZjgaKI8l5tPVqLupFuM m0YP8+7z9rWyAmvBFeBIkZiPGDNAVmhzsgEIlDEEUipq5kF/KE8ij3hkvwLvvJnd kp8RdVxxQ4itfub6RNtgwOxdBK5Emz7i7LLrYZ4vltMVjzTBQZVeqbfYHRLEmJZB q2KTCAeqHr1hsTEGt/u/X9q8Yys+Ad2/8ZVP1fgDXgfAtzBMe101hO9UzOvKTyC0 SPX1zepjAgMBAAECggEBAJMyxmUIVDHh5zXwBe5ZYlqSBZabLQnsQZhkNDX3nqpe lllq0PCTywj8CRuzldnaZpN60cmFY8bM7fsan/JzbLEilLPU0Rd0TNnY1nT2QZlV 10n/XrPs4DevDrbc8kDX7pVz4IVuC1KuuznFcLFj5+jfHLjrQEF2ubPOcxNbbrMN vRXK3AyXaapPCXlwzhIivRDX9p63Bfi16B6ckdHHdRw4Qlb3CajexSw7dH8JUlUS w2S4cTMm10VPrFNce0IdXqSTIK770a9z4EyYSbnybF+O12alr/GTL/niG/Iut4g8 PpGiywn58l0kqtti6N49e6U4DKqdDaYIRvy9HUaZF0ECgYEA5I3G30swteDTFozG kyCjYLw3yqIXWxn042zdhsfcXgbuolrZjXCUrSOIwV42UkJ1RzssrdCe6cBemqlx LJpeb+LAJh8vVUrz65WoBcMDsXVgcD51/ztMPyadzwrJ8BIiJG8uBVP6pCj4Wfiu UjIBk+hQEeHspSfvi+IvCO5JvtUCgYEA34K/MQkoZM3gfhyY4mr4P2vdjIMqR0qD H1mCja8tcJtROMP1tY0IWTjEmP+/6AbdsYwREk2C5Kn7lxZ0dbXRI1sHffhShLD7 eEy8SUV3vhy03CBS1y8VpZEUSKyAOlRlN1tY88QUny3xOQdLZb5t9QGGyQQAuYGu GIsUPRNt0FcCgYAg8u+AsW5MSiUkUxctjr7+6yN/6u5DC/Lp9n/ZNmbmh0lPzpke cuR8MWs9tT9PjJUrt7QxOqouOLVqxpKyQ27p4l6hIE3KlgukIuceLYcSxkEo7VhF e176m66UcpG6MmMJrZ2M1xaDJATps5gt8VeY4xzn9xIOnTtDh1AQkYnAIQKBgHM9 OFKSBC+lLoAXQoRK3t/kP4B5CE1lj6GURwnCLk2G5yO7dW473vgRmtu/0TRShe9K 5mpnaHt5YOyPeVBPhBsUjhJW/ETJ834dIl8s4AY3StDMIaos7p5E5Q5rUlnAtccK 5BwbFv7TczISHr/ApXTTaqkt1SnQQPEKlE7BO7dVAoGBAIK68ZrPFeQBwv7NWPXw 4iAt6p9NMdLJoBdS3zOjP1vKUGuR97B1diQeMmAsoQxxXJt0TABiDF3YJLE+bm65 sb1b7k8C8g9TN0ZcgIBTK1IBrI3SY4zDCzFoww5bdzs5eDaKs1KYmsd4Zou6trmU Zm/9Qsaoe59t6BaPwAVwzasz -----END PRIVATE KEY----- openssl-ibmca-2.4.1/test/provider/test.pm000066400000000000000000000460771450276407300204260ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; package test; sub rsaencdec { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($keylen, $tests, $max_file_size) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); `$prov openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:$keylen -out rsaencdec$keylen.key`; `$prov openssl rsa -in rsaencdec$keylen.key -check -pubout -out rsaencdec$keylen.pub`; exit(99) if ($?); for my $i (1..$tests) { my $bytes = 1 + int(rand($max_file_size)); # provider enc, no-provider dec `openssl rand $bytes > rsaencdec.${i}.${keylen}.data.in`; `$prov openssl pkeyutl -encrypt -pubin -inkey rsaencdec$keylen.pub -in rsaencdec.${i}.${keylen}.data.in -out rsaencdec.${i}.${keylen}.data.out`; `openssl pkeyutl -decrypt -inkey rsaencdec$keylen.key -in rsaencdec.${i}.${keylen}.data.out -out rsaencdec.${i}.${keylen}.data.dec`; `cmp rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.data.dec`; exit(99) if ($?); `rm -f rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.data.out rsaencdec.${i}.${keylen}.data.dec`; # no-provider enc, provider dec `openssl rand $bytes > rsaencdec.${i}.${keylen}.data.in`; `openssl pkeyutl -encrypt -pubin -inkey rsaencdec$keylen.pub -in rsaencdec.${i}.${keylen}.data.in -out rsaencdec.${i}.${keylen}.data.out`; `$prov openssl pkeyutl -decrypt -inkey rsaencdec$keylen.key -in rsaencdec.${i}.${keylen}.data.out -out rsaencdec.${i}.${keylen}.data.dec`; `cmp rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.data.dec`; exit(99) if ($?); `rm -f rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.data.out rsaencdec.${i}.${keylen}.data.dec`; } `rm -f rsaencdec$keylen.key rsaencdec$keylen.pub`; } sub rsaoaepencdec { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($keylen, $tests, $max_file_size, $md) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); `$prov openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:$keylen -out rsaoaepencdec$keylen.key`; `$prov openssl rsa -in rsaoaepencdec$keylen.key -check -pubout -out rsaoaepencdec$keylen.pub`; exit(99) if ($?); for my $i (1..$tests) { my $bytes = 1 + int(rand($max_file_size)); # provider enc, no-provider dec `openssl rand $bytes > rsaoaepencdec.${i}.${keylen}.data.in`; `$prov openssl pkeyutl -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:$md -pubin -inkey rsaoaepencdec$keylen.pub -in rsaoaepencdec.${i}.${keylen}.data.in -out rsaoaepencdec.${i}.${keylen}.data.out`; `openssl pkeyutl -decrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:$md -inkey rsaoaepencdec$keylen.key -in rsaoaepencdec.${i}.${keylen}.data.out -out rsaoaepencdec.${i}.${keylen}.data.dec`; `cmp rsaoaepencdec.${i}.${keylen}.data.in rsaoaepencdec.${i}.${keylen}.data.dec`; exit(99) if ($?); `rm -f rsaoaepencdec.${i}.${keylen}.data.in rsaoaepencdec.${i}.${keylen}.data.out rsaoaepencdec.${i}.${keylen}.data.dec`; # no-provider enc, provider dec `openssl rand $bytes > rsaoaepencdec.${i}.${keylen}.data.in`; `openssl pkeyutl -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:$md -pubin -inkey rsaoaepencdec$keylen.pub -in rsaoaepencdec.${i}.${keylen}.data.in -out rsaoaepencdec.${i}.${keylen}.data.out`; `$prov openssl pkeyutl -decrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:$md -inkey rsaoaepencdec$keylen.key -in rsaoaepencdec.${i}.${keylen}.data.out -out rsaoaepencdec.${i}.${keylen}.data.dec`; `cmp rsaoaepencdec.${i}.${keylen}.data.in rsaoaepencdec.${i}.${keylen}.data.dec`; exit(99) if ($?); `rm -f rsaoaepencdec.${i}.${keylen}.data.in rsaoaepencdec.${i}.${keylen}.data.out rsaoaepencdec.${i}.${keylen}.data.dec`; } `rm -f rsa$keylen.key rsa$keylen.pub`; } sub rsasignverify { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($keylen, $tests, $input_size) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); `$prov openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:$keylen -out rsasignverify$keylen.key`; `$prov openssl rsa -in rsasignverify$keylen.key -check -pubout -out rsasignverify$keylen.pub`; exit(99) if ($?); for my $i (1..$tests) { my $bytes = 1 + int(rand($input_size)); # provider sign, no-provider verify `openssl rand $bytes > rsasignverify.${i}.${keylen}.data.in`; `$prov openssl pkeyutl -sign -inkey rsasignverify$keylen.key -in rsasignverify.${i}.${keylen}.data.in -out rsasignverify.${i}.${keylen}.data.out`; `openssl pkeyutl -verifyrecover -pubin -inkey rsasignverify$keylen.pub -in rsasignverify.${i}.${keylen}.data.out -out rsasignverify.${i}.${keylen}.data.rec`; `cmp rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.rec`; exit(99) if ($?); `rm -f rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.out rsasignverify.${i}.${keylen}.data.rec`; # no-provider sign, provider verify `openssl rand $bytes > rsasignverify.${i}.${keylen}.data.in`; `openssl pkeyutl -sign -inkey rsasignverify$keylen.key -in rsasignverify.${i}.${keylen}.data.in -out rsasignverify.${i}.${keylen}.data.out`; `$prov openssl pkeyutl -verifyrecover -pubin -inkey rsasignverify$keylen.pub -in rsasignverify.${i}.${keylen}.data.out -out rsasignverify.${i}.${keylen}.data.rec`; `cmp rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.rec`; exit(99) if ($?); `rm -f rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.out rsasignverify.${i}.${keylen}.data.rec`; } `rm -f rsasignverify$keylen.key rsasignverify$keylen.pub`; } sub rsapsssignverify { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($keylen, $tests, $input_size, $md, $saltlen) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); `$prov openssl genpkey -algorithm RSA-PSS -pkeyopt rsa_keygen_bits:$keylen -pkeyopt rsa_pss_keygen_md:$md -pkeyopt rsa_pss_keygen_mgf1_md:$md -pkeyopt rsa_pss_keygen_saltlen:$saltlen -out rsapss$keylen.key`; # bug in OpenSSL 3.0: `$prov openssl rsa -in rsapss$keylen.key -check -pubout -out rsapss$keylen.pub`; exit(99) if ($?); for my $i (1..$tests) { my $bytes = 1 + int(rand($input_size)); # provider sign, no-provider verify `openssl rand $bytes > rsapsssignverify.${i}.${keylen}.data.in`; `$prov openssl pkeyutl -sign -digest $md -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:$saltlen -pkeyopt rsa_mgf1_md:$md -inkey rsapss$keylen.key -rawin -in rsapsssignverify.${i}.${keylen}.data.in -out rsapsssignverify.${i}.${keylen}.data.out`; # use pub key: `openssl pkeyutl -verify -digest $md -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:$saltlen -pkeyopt rsa_mgf1_md:$md -pubin -inkey rsapss$keylen.pub -rawin -in rsapsssignverify.${i}.${keylen}.data.in -sigfile rsapsssignverify.${i}.${keylen}.data.out`; `openssl pkeyutl -verify -digest $md -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:$saltlen -pkeyopt rsa_mgf1_md:$md -inkey rsapss$keylen.key -rawin -in rsapsssignverify.${i}.${keylen}.data.in -sigfile rsapsssignverify.${i}.${keylen}.data.out`; exit(99) if ($?); `rm -f rsapsssignverify.${i}.${keylen}.data.in rsapsssignverify.${i}.${keylen}.data.out`; # no-provider sign, provider verify `openssl rand $bytes > rsapsssignverify.${i}.${keylen}.data.in`; `openssl pkeyutl -sign -digest $md -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:$saltlen -pkeyopt rsa_mgf1_md:$md -inkey rsapss$keylen.key -rawin -in rsapsssignverify.${i}.${keylen}.data.in -out rsapsssignverify.${i}.${keylen}.data.out`; # use pub key: `$prov openssl pkeyutl -verify -digest $md -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:$saltlen -pkeyopt rsa_mgf1_md:$md -pubin -inkey rsapss$keylen.pub -rawin -in rsapsssignverify.${i}.${keylen}.data.in -sigfile rsapsssignverify.${i}.${keylen}.data.out`; `$prov openssl pkeyutl -verify -digest $md -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:$saltlen -pkeyopt rsa_mgf1_md:$md -inkey rsapss$keylen.key -rawin -in rsapsssignverify.${i}.${keylen}.data.in -sigfile rsapsssignverify.${i}.${keylen}.data.out`; exit(99) if ($?); `rm -f rsapsssignverify.${i}.${keylen}.data.in rsapsssignverify.${i}.${keylen}.data.out`; } `rm -f rsapss$keylen.key rsapss$keylen.pub`; } sub rsax931signverify { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($keylen, $tests, $input_size, $md) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); `$prov openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:$keylen -out rsax931$keylen.key`; `$prov openssl rsa -in rsax931$keylen.key -check -pubout -out rsax931$keylen.pub`; exit(99) if ($?); for my $i (1..$tests) { my $bytes = 1 + int(rand($input_size)); # provider sign, no-provider verify `openssl rand $bytes > rsax931signverify.${i}.${keylen}.data.in`; `$prov openssl pkeyutl -sign -digest $md -pkeyopt rsa_padding_mode:x931 -inkey rsax931$keylen.key -rawin -in rsax931signverify.${i}.${keylen}.data.in -out rsax931signverify.${i}.${keylen}.data.out`; `openssl pkeyutl -verify -digest $md -pkeyopt rsa_padding_mode:x931 -pubin -inkey rsax931$keylen.pub -rawin -in rsax931signverify.${i}.${keylen}.data.in -sigfile rsax931signverify.${i}.${keylen}.data.out`; exit(99) if ($?); `rm -f rsax931signverify.${i}.${keylen}.data.in rsax931signverify.${i}.${keylen}.data.out`; # no-provider sign, provider verify `openssl rand $bytes > rsax931signverify.${i}.${keylen}.data.in`; `openssl pkeyutl -sign -digest $md -pkeyopt rsa_padding_mode:x931 -inkey rsax931$keylen.key -rawin -in rsax931signverify.${i}.${keylen}.data.in -out rsax931signverify.${i}.${keylen}.data.out`; `$prov openssl pkeyutl -verify -digest $md -pkeyopt rsa_padding_mode:x931 -pubin -inkey rsax931$keylen.pub -rawin -in rsax931signverify.${i}.${keylen}.data.in -sigfile rsax931signverify.${i}.${keylen}.data.out`; exit(99) if ($?); `rm -f rsax931signverify.${i}.${keylen}.data.in rsax931signverify.${i}.${keylen}.data.out`; } `rm -f rsax931$keylen.key rsax931$keylen.pub`; } sub ecsignverify { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($curve, $tests, $input_size, $md) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); # skip if OpenSSL does not support the curve `openssl ecparam -list_curves | grep $curve`; return if ($?); `$prov openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$curve -out ecsignverify$curve.key`; `$prov openssl ec -in ecsignverify$curve.key -check -pubout -out ecsignverify$curve.pub`; exit(99) if ($?); for my $i (1..$tests) { my $bytes = 1 + int(rand($input_size)); # provider sign, no-provider verify `openssl rand $bytes > ecsignverify.${i}.${curve}.data.in`; `$prov openssl pkeyutl -sign -digest $md -inkey ecsignverify$curve.key -rawin -in ecsignverify.${i}.${curve}.data.in -out ecsignverify.${i}.${curve}.data.out`; `openssl pkeyutl -verify -digest $md -pubin -inkey ecsignverify$curve.pub -rawin -in ecsignverify.${i}.${curve}.data.in -sigfile ecsignverify.${i}.${curve}.data.out`; exit(99) if ($?); `rm -f ecsignverify.${i}.${curve}.data.in ecsignverify.${i}.${curve}.data.out`; # no-provider sign, provider verify `openssl rand $bytes > ecsignverify.${i}.${curve}.data.in`; `openssl pkeyutl -sign -digest $md -inkey ecsignverify$curve.key -rawin -in ecsignverify.${i}.${curve}.data.in -out ecsignverify.${i}.${curve}.data.out`; `$prov openssl pkeyutl -verify -digest $md -pubin -inkey ecsignverify$curve.pub -rawin -in ecsignverify.${i}.${curve}.data.in -sigfile ecsignverify.${i}.${curve}.data.out`; exit(99) if ($?); `rm -f ecsignverify.${i}.${curve}.data.in ecsignverify.${i}.${curve}.data.out`; } `rm -f ec$curve.key ec$curve.pub`; } sub ecderive { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($curve, $tests) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); # skip if OpenSSL does not support the curve `openssl ecparam -list_curves | grep $curve`; return if ($?); `$prov openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$curve -out ec$curve.key`; `$prov openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$curve -out peer$curve.key`; `$prov openssl ec -in peer$curve.key -check -pubout -out peer$curve.pub`; exit(99) if ($?); for my $i (1..$tests) { `$prov openssl pkeyutl -derive -inkey ec$curve.key -peerkey peer$curve.pub -out ecderive.${i}.${curve}.data.out1`; `openssl pkeyutl -derive -inkey ec$curve.key -peerkey peer$curve.pub -out ecderive.${i}.${curve}.data.out2`; `cmp ecderive.${i}.${curve}.data.out1 ecderive.${i}.${curve}.data.out2`; exit(99) if ($?); `rm -f ecderive.${i}.${curve}.data.out1 ecderive.${i}.${curve}.data.out2`; } `rm -f ec$curve.key peer$curve.key peer$curve.pub`; } sub ecderivekdf { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($curve, $tests, $outlen, $kdf, $md) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); # skip if OpenSSL does not support the curve `openssl ecparam -list_curves | grep $curve`; return if ($?); `$prov openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$curve -out ec$curve.key`; `$prov openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$curve -out peer$curve.key`; `$prov openssl ec -in peer$curve.key -check -pubout -out peer$curve.pub`; exit(99) if ($?); for my $i (1..$tests) { `$prov openssl pkeyutl -derive -inkey ec$curve.key -peerkey peer$curve.pub -pkeyopt kdf-type:$kdf -pkeyopt kdf-outlen:$outlen -pkeyopt kdf-digest:$md -out ecderive.${i}.${curve}.data.out1`; `openssl pkeyutl -derive -inkey ec$curve.key -peerkey peer$curve.pub -pkeyopt kdf-type:$kdf -pkeyopt kdf-outlen:$outlen -pkeyopt kdf-digest:$md -out ecderive.${i}.${curve}.data.out2`; `cmp ecderive.${i}.${curve}.data.out1 ecderive.${i}.${curve}.data.out2`; exit(99) if ($?); `rm -f ecderive.${i}.${curve}.data.out1 ecderive.${i}.${curve}.data.out2`; } `rm -f ec$curve.key peer$curve.key peer$curve.pub`; } sub dhderive { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($group, $tests) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); `$prov openssl genpkey -algorithm DH -pkeyopt group:$group -out dhderive$group.key`; `$prov openssl genpkey -algorithm DH -pkeyopt group:$group -out peerderive$group.key`; `$prov openssl pkey -in peerderive$group.key -check -pubout -out peerderive$group.pub`; exit(99) if ($?); for my $i (1..$tests) { `$prov openssl pkeyutl -derive -inkey dhderive$group.key -peerkey peerderive$group.pub -out dhderive.${i}.${group}.data.out1`; `openssl pkeyutl -derive -inkey dhderive$group.key -peerkey peerderive$group.pub -out dhderive.${i}.${group}.data.out2`; `cmp dhderive.${i}.${group}.data.out1 dhderive.${i}.${group}.data.out2`; exit(99) if ($?); `rm -f dhderive.${i}.${group}.data.out1 dhderive.${i}.${group}.data.out2`; } `rm -f dhderive$group.key peerderive$group.key peerderive$group.pub`; } sub dhderivekdf { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($group, $tests, $outlen, $kdf, $md, $cekalg) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); `$prov openssl genpkey -algorithm DH -pkeyopt group:$group -out dhderivekdf$group.key`; `$prov openssl genpkey -algorithm DH -pkeyopt group:$group -out peerderivekdf$group.key`; `$prov openssl pkey -in peerderivekdf$group.key -check -pubout -out peerderivekdf$group.pub`; exit(99) if ($?); for my $i (1..$tests) { `$prov openssl pkeyutl -derive -inkey dhderivekdf$group.key -peerkey peerderivekdf$group.pub -pkeyopt kdf-type:$kdf -pkeyopt kdf-outlen:$outlen -pkeyopt kdf-digest:$md -pkeyopt cekalg:$cekalg -out dhderivekdf.${i}.${group}.data.out1`; `openssl pkeyutl -derive -inkey dhderivekdf$group.key -peerkey peerderivekdf$group.pub -pkeyopt kdf-type:$kdf -pkeyopt kdf-outlen:$outlen -pkeyopt kdf-digest:$md -pkeyopt cekalg:$cekalg -out dhderivekdf.${i}.${group}.data.out2`; `cmp dhderivekdf.${i}.${group}.data.out1 dhderivekdf.${i}.${group}.data.out2`; exit(99) if ($?); `rm -f dhderivekdf.${i}.${group}.data.out1 dhderivekdf.${i}.${group}.data.out2`; } `rm -f dhderivekdf$group.key peerderivekdf$group.key peerderivekdf$group.pub`; } sub tls { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($port, $privkey, $cert, $cipher, $ciphersuites, $opts) = @_; my ($pid, $ret); `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); if ($pid = fork) { sleep 1; `echo "Hello World" | $prov openssl s_client -connect localhost:$port -cipher $cipher -ciphersuites $ciphersuites $opts`; $ret = $?; sleep 1; kill 15, $pid; waitpid $pid, 0; } else { exec "$prov openssl s_server -accept $port -naccept 1 -brief -cert $cert -key $privkey -cipher $cipher -ciphersuites $ciphersuites $opts 1>server-$port.out 2>&1"; } exit(99) if ($ret); `rm -f server-$port.out`; } sub rsaimplrej { my $prov = "OPENSSL_CONF=$ENV{IBMCA_OPENSSL_TEST_CONF} OPENSSL_MODULES=$ENV{IBMCA_TEST_PATH}"; my ($key, $in, $out) = @_; `$prov openssl list -providers | grep "name: ibmca"`; exit(99) if ($?); `$prov openssl pkeyutl -decrypt -inkey $key -in $in -out rsaimplrej.out`; exit(99) if ($?); `cmp $out rsaimplrej.out`; exit(99) if ($?); `rm -f rsaimplrej.out`; } `bash -c unset OPENSSL_CONF`; `bash -c unset OPENSSL_MODULES`; 1; openssl-ibmca-2.4.1/test/provider/threadtest.c000066400000000000000000000153161450276407300214140ustar00rootroot00000000000000/* * Copyright [2021-2022] 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. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include /* This is just a random number of threads to stimulate provider configuration. */ #define DEFAULT_MAX_THREADS 20 void setup(void) { OPENSSL_load_builtin_modules(); CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION| CONF_MFLAGS_IGNORE_MISSING_FILE); } static int do_sign_verify(EVP_PKEY *eckey) { int ret = 0, i; EVP_PKEY_CTX *pctx = NULL; size_t siglen; unsigned char sigbuf[1024]; unsigned char digest[32]; memset(digest, 0, sizeof(digest)); for (i = 0; i < 100; i++) { /* Sign with IBMCA provider */ pctx = EVP_PKEY_CTX_new_from_pkey(NULL, eckey, "?provider=ibmca"); if (pctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_sign_init(pctx) <= 0) { fprintf(stderr, "EVP_PKEY_sign_init failed\n"); goto out; } siglen = sizeof(sigbuf); if (EVP_PKEY_sign(pctx, sigbuf, &siglen, digest, sizeof(digest)) <= 0) { fprintf(stderr, "EVP_PKEY_sign failed\n"); goto out; } EVP_PKEY_CTX_free(pctx); /* Verify with IBMCA provider */ pctx = EVP_PKEY_CTX_new_from_pkey(NULL, eckey, "?provider=ibmca"); if (pctx == NULL) { fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey failed\n"); goto out; } if (EVP_PKEY_verify_init(pctx) <= 0) { fprintf(stderr, "EVP_PKEY_verify_init failed\n"); goto out; } ret = EVP_PKEY_verify(pctx, sigbuf, siglen, digest, sizeof(digest)); if (ret == -1) { /* error */ fprintf(stderr, "Failed to verify signature\n"); ret = 0; } else if (ret == 0) { /* incorrect signature */ fprintf(stderr, "Signature incorrect\n"); ret = 0; } else { /* signature ok */ ret = 1; } EVP_PKEY_CTX_free(pctx); pctx = NULL; } out: if (pctx) EVP_PKEY_CTX_free(pctx); ERR_print_errors_fp(stderr); return ret; } static void *threadfn(void *arg) { unsigned long res = 0; EVP_PKEY *eckey = arg; if (do_sign_verify(eckey) != 1) { res = 1; } return (void *)res; } int main(int argc, char **argv) { pthread_t *threads; unsigned long int i, maxthreads = 0, errors = 0; int c; pthread_t me; EVP_PKEY *eckey = NULL; EVP_PKEY_CTX *pctx = NULL; /* First fix the environment */ char *testcnf = getenv("IBMCA_OPENSSL_TEST_CONF"); char *testpath = getenv("IBMCA_TEST_PATH"); /* Do not overwrite a user-provided OPENSSL_CONF in the environment. This allows us to execute this test also on an installation with a user-provided engine configuration. */ if (testcnf && setenv("OPENSSL_CONF", testcnf, 0)) { fprintf(stderr, "Failed to set OPENSSL_CONF environment variable!\n"); return 77; } if (testpath && setenv("OPENSSL_MODULES", testpath, 0)) { fprintf(stderr, "Failed to set OPENSSL_MODULES environment variable!\n"); return 77; } // arg parse while (1) { int option_index; static struct option long_options[] = { { "threads", required_argument, 0, 't'}, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, "t:", long_options, &option_index); if (c == -1) { break; } else if (c == 't') { maxthreads = strtoul(optarg, NULL, 0); } else { fprintf(stderr, "USAGE: %s [-t|--threads ]\n", argv[0]); fprintf(stderr, "where\t specifies the number of threads to use (default: 20)\n"); return 1; } } setup(); pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", "?provider=ibmca"); if (pctx == NULL) { fprintf(stderr, "Failed to create PKEY_CTX\n"); ERR_print_errors_fp(stderr); return 1; } /* * Generate an EC key with a curve that libica does not support, so that * it uses SW-fallbacks, and thus stresses the fallback pkey cache */ if (EVP_PKEY_keygen_init(pctx) != 1 || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_secp256k1) != 1 || EVP_PKEY_keygen(pctx, &eckey) != 1) { fprintf(stderr, "keygen initialization failed\n"); EVP_PKEY_CTX_free(pctx); ERR_print_errors_fp(stderr); return 1; } if (eckey == NULL) { /* error */ fprintf(stderr, "Failed to create ec key for NID_secp256k1\n"); EVP_PKEY_CTX_free(pctx); ERR_print_errors_fp(stderr); return 1; } EVP_PKEY_CTX_free(pctx); if (maxthreads == 0) maxthreads = DEFAULT_MAX_THREADS; threads = calloc(sizeof(pthread_t), maxthreads); if (threads == NULL) { fprintf(stderr, "Thread array allocation failed!\n"); return 1; } me = pthread_self(); // Start threads for (i = 0; i < maxthreads; ++i) { int s = pthread_create(&threads[i], NULL, &threadfn, eckey); if (s != 0) { fprintf(stderr, "Failed to create thread %lu: %s\n", i, strerror(s)); threads[i] = me; } } // Now join threads for (i = 0; i < maxthreads; ++i) { if (!pthread_equal(threads[i], me)) { void *retval; int s = pthread_join(threads[i], &retval); if (s != 0) { fprintf(stderr, "Failed to join thread %lu: %s\n", i, strerror(s)); } else if ((unsigned long)retval != 0) { fprintf(stderr, "Error in thread %lu\n", i); ++errors; } } } free(threads); EVP_PKEY_free(eckey); return errors ? 99 : 0; } openssl-ibmca-2.4.1/test/provider/tls.pl000077500000000000000000000033671450276407300202460ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright [2021-2022] 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. # use strict; use warnings; use test; use FindBin; # TLS 1.3 with RSA signatures test::tls(10001, "$FindBin::Bin/server-key-rsa.pem", "$FindBin::Bin/server-cert-rsa.pem", "ALL", "TLS_AES_256_GCM_SHA384", "-tls1_3"); # TLS 1.3 with EC signatures test::tls(10002, "$FindBin::Bin/server-key-ec.pem", "$FindBin::Bin/server-cert-ec.pem", "ALL", "TLS_AES_256_GCM_SHA384", "-tls1_3"); # TLS 1.2 with RSA signatures and ECDH key exchange test::tls(10003, "$FindBin::Bin/server-key-rsa.pem", "$FindBin::Bin/server-cert-rsa.pem", "ECDHE-RSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3"); # TLS 1.2 with ECDSA signatures and ECDH key exchange test::tls(10004, "$FindBin::Bin/server-key-ec.pem", "$FindBin::Bin/server-cert-ec.pem", "ECDHE-ECDSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3"); # TLS 1.2 with RSA signatures and DH key exchange test::tls(10005, "$FindBin::Bin/server-key-rsa.pem", "$FindBin::Bin/server-cert-rsa.pem", "DHE-RSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3"); # TLS 1.2 with RSA signatures and RSA key exchange test::tls(10006, "$FindBin::Bin/server-key-rsa.pem", "$FindBin::Bin/server-cert-rsa.pem", "AES256-GCM-SHA384", "\"\"", "-no_tls1_3");