diff -Nru libica-3.9.0/ChangeLog libica-4.0.0/ChangeLog
--- libica-3.9.0/ChangeLog	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/ChangeLog	2021-12-06 12:01:54.000000000 +0100
@@ -1,3 +1,8 @@
+v4.0.0
+ - [UPDATE] NO_SW_FALLBACKS is now the default for libica.so
+   [UPDATE] Removed deprecated API functions including tests
+   [UPDATE] Introduced 'const' for some API function parameters
+   [FEATURE] icastats: new parm -k to display detailed counters
 v3.9.0
  - [FEATURE] Add support for OpenSSL 3.0
    [FEATURE] icainfo: new parm -c to display available EC curves
diff -Nru libica-3.9.0/configure.ac libica-4.0.0/configure.ac
--- libica-3.9.0/configure.ac	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/configure.ac	2021-12-06 12:01:54.000000000 +0100
@@ -1,4 +1,4 @@
-AC_INIT([libica], [3.9.0], [https://github.com/opencryptoki/libica/issues],, [https://github.com/opencryptoki/libica])
+AC_INIT([libica], [4.0.0], [https://github.com/opencryptoki/libica/issues],, [https://github.com/opencryptoki/libica])
 
 # save cmdline flags
 cmdline_CFLAGS="$CFLAGS"
diff -Nru libica-3.9.0/debian/changelog libica-4.0.0/debian/changelog
--- libica-3.9.0/debian/changelog	2021-12-03 00:42:09.000000000 +0100
+++ libica-4.0.0/debian/changelog	2022-01-31 13:19:06.000000000 +0100
@@ -1,3 +1,37 @@
+libica (4.0.0-0ubuntu1) jammy; urgency=medium
+
+  * New upstream release LP: #1959421
+  * Add cherry-picked patches from upstream:
+    - RSA: limit RSA key length to 4096
+      977fe8ac713f9ff3101ce9882e23d0183fb46ec8.patch
+    - ECC: fix memory leaks in make_eckey()
+      553977ef505b43c7d17056369ed518a971d43d68.patch
+    - ECC: Avoid recursive loop in ec_key_check() with OpenSSL 3.0
+      b41addd200c0938c6c10202da08ad5f7df940e18.patch
+    - RSA: Fix memory leaks in rsa_key_generate_mod_expo()/crt()
+      6031ec80a5ada52609822fed4a6bd2cccafe5563.patch
+    - EC: Handle unsupported EC curve in ica_ec_key_new()
+      b49cf457659a4baf382b3828d89823497bb00f6e.patch
+    - Compute HMAC from installed library
+      7e6e303e6aef019047eb6dfcdedbfe7da2a88526.patch
+    - Fix compile warnings
+      28fa931bed9e6847137829952a3e7cc6091bd071.patch
+    - Fix memory leaks in test programs
+      cc44f18383ec6dc01a05abd6c25a1dec8efe84cb.patch
+    - FIPS: Calculation of library HMAC may fail
+      9c6431f49a9fe0d574722954e018b4cba6ab085b.patch
+    - MAKEFILE: Do not install ec_internal_test
+      5aa9366c236a6d17570403ef81c65e4f5f91a8af.patch
+  * transition from libica3 to libica4
+    - adjusting d/c
+    - migrating d/libica3.* to d/libica4.*
+    - expanding symbols file
+  * adjusting d/copyright
+    - changing tabs to spaces
+    - updating relevant copyright years
+
+ -- Frank Heimes <frank.heimes@canonical.com>  Mon, 31 Jan 2022 13:19:06 +0100
+
 libica (3.9.0-0ubuntu1) jammy; urgency=medium
 
   * New upstream release LP: #1953087
diff -Nru libica-3.9.0/debian/control libica-4.0.0/debian/control
--- libica-3.9.0/debian/control	2019-04-30 12:58:10.000000000 +0200
+++ libica-4.0.0/debian/control	2022-01-31 13:19:06.000000000 +0100
@@ -10,14 +10,14 @@
 Section: libdevel
 Architecture: s390 s390x
 Multi-Arch: same
-Depends: libica3 (= ${binary:Version}), ${misc:Depends}
+Depends: libica4 (= ${binary:Version}), ${misc:Depends}
 Description: hardware cryptography support for IBM System z hardware (dev package)
  libica library provides hardware acceleration for cryptographic
  functions and is part of the openCryptoki project.
  .
  This package contains development headers and library.
 
-Package: libica3
+Package: libica4
 Architecture: s390 s390x
 Multi-Arch: same
 Depends: ${shlibs:Depends}, ${misc:Depends}
diff -Nru libica-3.9.0/debian/copyright libica-4.0.0/debian/copyright
--- libica-3.9.0/debian/copyright	2017-10-04 11:28:19.000000000 +0200
+++ libica-4.0.0/debian/copyright	2022-01-31 13:19:06.000000000 +0100
@@ -3,250 +3,250 @@
 Source: http://sourceforge.net/projects/opencryptoki/files/libica/
 
 Files: *
-Copyright: 2001-2015 IBM Corp.
+Copyright: 1994-1996, 1999-2002, 2004-2019, 2021 IBM Corp.
 License: CPL
  .
-	Common Public License - V1.0
+   Common Public License - V1.0
  .
-	THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON
-	PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-	THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
- .
-	1. DEFINITIONS
- .
-	"Contribution" means:
-		1. in the case of the initial Contributor, the initial code and
-		documentation distributed under this Agreement, and
- .
-		2. in the case of each subsequent Contributor:
-      			1. changes to the Program, and
-      			2. additions to the Program;
- .
-		where such changes and/or additions to the Program originate
-		from and are distributed by that particular Contributor. A
-		Contribution 'originates' from a Contributor if it was added to
-		the Program by such Contributor itself or anyone acting on such
-		Contributor's behalf. Contributions do not include additions to
-		the Program which: (i) are separate modules of software
-		distributed in conjunction with the Program under their own
-		license agreement, and (ii) are not derivative works of the
-		Program.
- .
-	"Contributor" means any person or entity that distributes the Program.
- .
-	"Licensed Patents " mean patent claims licensable by a Contributor
-	which are necessarily infringed by the use or sale of its Contribution
-	alone or when combined with the Program.
- .
-	"Program" means the Contributions distributed in accordance with this
-	Agreement.
- .
-	"Recipient" means anyone who receives the Program under this Agreement,
-	including all Contributors.
- .
- .
-	2. GRANT OF RIGHTS
- .
-		1. Subject to the terms of this Agreement, each Contributor
-		hereby grants Recipient a non-exclusive, worldwide,
-		royalty-free copyright license to reproduce, prepare derivative
-		works of, publicly display, publicly perform, distribute and
-		sublicense the Contribution of such Contributor, if any, and
-		such derivative works, in source code and object code form.
- .
-		2. Subject to the terms of this Agreement, each Contributor
-		hereby grants Recipient a non-exclusive, worldwide,
-		royalty-free patent license under Licensed Patents to make,
-		use, sell, offer to sell, import and otherwise transfer the
-		Contribution of such Contributor, if any, in source code and
-		object code form. This patent license shall apply to the
-		combination of the Contribution and the Program if, at the time
-		the Contribution is added by the Contributor, such addition of
-		the Contribution causes such combination to be covered by the
-		Licensed Patents. The patent license shall not apply to any
-		other combinations which include the Contribution. No hardware
-		per se is licensed hereunder.
- .
-		3. Recipient understands that although each Contributor grants
-		the licenses to its Contributions set forth herein, no
-		assurances are provided by any Contributor that the Program
-		does not infringe the patent or other intellectual property
-		rights of any other entity. Each Contributor disclaims any
-		liability to Recipient for claims brought by any other entity
-		based on infringement of intellectual property rights or
-		otherwise. As a condition to exercising the rights and licenses
-		granted hereunder, each Recipient hereby assumes sole
-		responsibility to secure any other intellectual property rights
-		needed, if any. For example, if a third party patent license is
-		required to allow Recipient to distribute the Program, it is
-		Recipient's responsibility to acquire that license before
-		distributing the Program.
- .
-		4. Each Contributor represents that to its knowledge it has
-		sufficient copyright rights in its Contribution, if any, to
-		grant the copyright license set forth in this Agreement.
- .
- .
-	3. REQUIREMENTS
- .
-	A Contributor may choose to distribute the Program in object code form
-	under its own license agreement, provided that:
- .
-		1. it complies with the terms and conditions of this Agreement;
-		and
- .
-		2. its license agreement:
-			1. effectively disclaims on behalf of all Contributors
-			all warranties and conditions, express and implied,
-			including warranties or conditions of title and
-			non-infringement, and implied warranties or conditions
-			of merchantability and fitness for a particular purpose;
- .
-			2. effectively excludes on behalf of all Contributors
-			all liability for damages, including direct, indirect,
-			special, incidental and consequential damages, such as
-			lost profits;
- .
-			3. states that any provisions which differ from this
-			Agreement are offered by that Contributor alone and not
-			by any other party; and
- .
-			4. states that source code for the Program is available
-			from such Contributor, and informs licensees how to
-			obtain it in a reasonable manner on or through a medium
-			customarily used for software exchange.
- .
-		When the Program is made available in source code form:
-			1. it must be made available under this Agreement; and
-         		2. a copy of this Agreement must be included with each
-			copy of the Program.
- .
-		Contributors may not remove or alter any copyright notices
-		contained within the Program.
- .
-		Each Contributor must identify itself as the originator of its
-		Contribution, if any, in a manner that reasonably allows
-		subsequent Recipients to identify the originator of the
-		Contribution.
- .
- .
-	4. COMMERCIAL DISTRIBUTION
- .
-	Commercial distributors of software may accept certain responsibilities
-	with respect to end users, business partners and the like. While this
-	license is intended to facilitate the commercial use of the Program,
-	the Contributor who includes the Program in a commercial product
-	offering should do so in a manner which does not create potential
-	liability for other Contributors. Therefore, if a Contributor includes
-	the Program in a commercial product offering, such Contributor
-	("Commercial Contributor") hereby agrees to defend and indemnify every
-	other Contributor ("Indemnified Contributor") against any losses,
-	damages and costs (collectively "Losses") arising from claims, lawsuits
-	and other legal actions brought by a third party against the
-	Indemnified Contributor to the extent caused by the acts or omissions
-	of such Commercial Contributor in connection with its distribution of
-	the Program in a commercial product offering. The obligations in this
-	section do not apply to any claims or Losses relating to any actual or
-	alleged intellectual property infringement. In order to qualify, an
-	Indemnified Contributor must: a) promptly notify the Commercial
-	Contributor in writing of such claim, and b) allow the Commercial
-	Contributor to control, and cooperate with the Commercial Contributor
-	in, the defense and any related settlement negotiations. The
-	Indemnified Contributor may participate in any such claim at its own
-	expense.
- .
-	For example, a Contributor might include the Program in a commercial
-	product offering, Product X. That Contributor is then a Commercial
-	Contributor. If that Commercial Contributor then makes performance
-	claims, or offers warranties related to Product X, those performance
-	claims and warranties are such Commercial Contributor's responsibility
-	alone. Under this section, the Commercial Contributor would have to
-	defend claims against the other Contributors related to those
-	performance claims and warranties, and if a court requires any other
-	Contributor to pay any damages as a result, the Commercial Contributor
-	must pay those damages.
- .
- .
-	5. NO WARRANTY
- .
-	EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
-	PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-	KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-	WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
-	FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible
-	for determining the appropriateness of using and distributing the
-	Program and assumes all risks associated with its exercise of rights
-	under this Agreement, including but not limited to the risks and costs
-	of program errors, compliance with applicable laws, damage to or loss
-	of data, programs or equipment, and unavailability or interruption of
-	operations.
- .
- .
-	6. DISCLAIMER OF LIABILITY
- .
-	EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-	ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-	WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-	DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-	HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- .
- .
-	7. GENERAL
- .
-	If any provision of this Agreement is invalid or unenforceable under
-	applicable law, it shall not affect the validity or enforceability of
-	the remainder of the terms of this Agreement, and without further
-	action by the parties hereto, such provision shall be reformed to the
-	minimum extent necessary to make such provision valid and enforceable.
- .
-	If Recipient institutes patent litigation against a Contributor with
-	respect to a patent applicable to software (including a cross-claim or
-	counterclaim in a lawsuit), then any patent licenses granted by that
-	Contributor to such Recipient under this Agreement shall terminate as
-	of the date such litigation is filed. In addition, if Recipient
-	institutes patent litigation against any entity (including a
-	cross-claim or counterclaim in a lawsuit) alleging that the Program
-	itself (excluding combinations of the Program with other software or
-	hardware) infringes such Recipient's patent(s), then such Recipient's
-	rights granted under Section 2(b) shall terminate as of the date such
-	litigation is filed.
- .
-	All Recipient's rights under this Agreement shall terminate if it fails
-	to comply with any of the material terms or conditions of this
-	Agreement and does not cure such failure in a reasonable period of time
-	after becoming aware of such noncompliance. If all Recipient's rights
-	under this Agreement terminate, Recipient agrees to cease use and
-	distribution of the Program as soon as reasonably practicable. However,
-	Recipient's obligations under this Agreement and any licenses granted
-	by Recipient relating to the Program shall continue and survive.
- .
-	Everyone is permitted to copy and distribute copies of this Agreement,
-	but in order to avoid inconsistency the Agreement is copyrighted and
-	may only be modified in the following manner. The Agreement Steward
-	reserves the right to publish new versions (including revisions) of
-	this Agreement from time to time. No one other than the Agreement
-	Steward has the right to modify this Agreement. IBM is the initial
-	Agreement Steward. IBM may assign the responsibility to serve as the
-	Agreement Steward to a suitable separate entity. Each new version of
-	the Agreement will be given a distinguishing version number. The
-	Program (including Contributions) may always be distributed subject to
-	the version of the Agreement under which it was received. In addition,
-	after a new version of the Agreement is published, Contributor may
-	elect to distribute the Program (including its Contributions) under the
-	new version. Except as expressly stated in Sections 2(a) and 2(b)
-	above, Recipient receives no rights or licenses to the intellectual
-	property of any Contributor under this Agreement, whether expressly, by
-	implication, estoppel or otherwise. All rights in the Program not
-	expressly granted under this Agreement are reserved.
- .
-	This Agreement is governed by the laws of the State of New York and the
-	intellectual property laws of the United States of America. No party to
-	this Agreement will bring a legal action under this Agreement more than
-	one year after the cause of action arose. Each party waives its rights
-	to a jury trial in any resulting litigation.
+   THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON
+   PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
+   THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+ .
+   1. DEFINITIONS
+ .
+   "Contribution" means:
+      1. in the case of the initial Contributor, the initial code and
+      documentation distributed under this Agreement, and
+ .
+      2. in the case of each subsequent Contributor:
+               1. changes to the Program, and
+               2. additions to the Program;
+ .
+      where such changes and/or additions to the Program originate
+      from and are distributed by that particular Contributor. A
+      Contribution 'originates' from a Contributor if it was added to
+      the Program by such Contributor itself or anyone acting on such
+      Contributor's behalf. Contributions do not include additions to
+      the Program which: (i) are separate modules of software
+      distributed in conjunction with the Program under their own
+      license agreement, and (ii) are not derivative works of the
+      Program.
+ .
+   "Contributor" means any person or entity that distributes the Program.
+ .
+   "Licensed Patents " mean patent claims licensable by a Contributor
+   which are necessarily infringed by the use or sale of its Contribution
+   alone or when combined with the Program.
+ .
+   "Program" means the Contributions distributed in accordance with this
+   Agreement.
+ .
+   "Recipient" means anyone who receives the Program under this Agreement,
+   including all Contributors.
+ .
+ .
+   2. GRANT OF RIGHTS
+ .
+      1. Subject to the terms of this Agreement, each Contributor
+      hereby grants Recipient a non-exclusive, worldwide,
+      royalty-free copyright license to reproduce, prepare derivative
+      works of, publicly display, publicly perform, distribute and
+      sublicense the Contribution of such Contributor, if any, and
+      such derivative works, in source code and object code form.
+ .
+      2. Subject to the terms of this Agreement, each Contributor
+      hereby grants Recipient a non-exclusive, worldwide,
+      royalty-free patent license under Licensed Patents to make,
+      use, sell, offer to sell, import and otherwise transfer the
+      Contribution of such Contributor, if any, in source code and
+      object code form. This patent license shall apply to the
+      combination of the Contribution and the Program if, at the time
+      the Contribution is added by the Contributor, such addition of
+      the Contribution causes such combination to be covered by the
+      Licensed Patents. The patent license shall not apply to any
+      other combinations which include the Contribution. No hardware
+      per se is licensed hereunder.
+ .
+      3. Recipient understands that although each Contributor grants
+      the licenses to its Contributions set forth herein, no
+      assurances are provided by any Contributor that the Program
+      does not infringe the patent or other intellectual property
+      rights of any other entity. Each Contributor disclaims any
+      liability to Recipient for claims brought by any other entity
+      based on infringement of intellectual property rights or
+      otherwise. As a condition to exercising the rights and licenses
+      granted hereunder, each Recipient hereby assumes sole
+      responsibility to secure any other intellectual property rights
+      needed, if any. For example, if a third party patent license is
+      required to allow Recipient to distribute the Program, it is
+      Recipient's responsibility to acquire that license before
+      distributing the Program.
+ .
+      4. Each Contributor represents that to its knowledge it has
+      sufficient copyright rights in its Contribution, if any, to
+      grant the copyright license set forth in this Agreement.
+ .
+ .
+   3. REQUIREMENTS
+ .
+   A Contributor may choose to distribute the Program in object code form
+   under its own license agreement, provided that:
+ .
+      1. it complies with the terms and conditions of this Agreement;
+      and
+ .
+      2. its license agreement:
+         1. effectively disclaims on behalf of all Contributors
+         all warranties and conditions, express and implied,
+         including warranties or conditions of title and
+         non-infringement, and implied warranties or conditions
+         of merchantability and fitness for a particular purpose;
+ .
+         2. effectively excludes on behalf of all Contributors
+         all liability for damages, including direct, indirect,
+         special, incidental and consequential damages, such as
+         lost profits;
+ .
+         3. states that any provisions which differ from this
+         Agreement are offered by that Contributor alone and not
+         by any other party; and
+ .
+         4. states that source code for the Program is available
+         from such Contributor, and informs licensees how to
+         obtain it in a reasonable manner on or through a medium
+         customarily used for software exchange.
+ .
+      When the Program is made available in source code form:
+         1. it must be made available under this Agreement; and
+               2. a copy of this Agreement must be included with each
+         copy of the Program.
+ .
+      Contributors may not remove or alter any copyright notices
+      contained within the Program.
+ .
+      Each Contributor must identify itself as the originator of its
+      Contribution, if any, in a manner that reasonably allows
+      subsequent Recipients to identify the originator of the
+      Contribution.
+ .
+ .
+   4. COMMERCIAL DISTRIBUTION
+ .
+   Commercial distributors of software may accept certain responsibilities
+   with respect to end users, business partners and the like. While this
+   license is intended to facilitate the commercial use of the Program,
+   the Contributor who includes the Program in a commercial product
+   offering should do so in a manner which does not create potential
+   liability for other Contributors. Therefore, if a Contributor includes
+   the Program in a commercial product offering, such Contributor
+   ("Commercial Contributor") hereby agrees to defend and indemnify every
+   other Contributor ("Indemnified Contributor") against any losses,
+   damages and costs (collectively "Losses") arising from claims, lawsuits
+   and other legal actions brought by a third party against the
+   Indemnified Contributor to the extent caused by the acts or omissions
+   of such Commercial Contributor in connection with its distribution of
+   the Program in a commercial product offering. The obligations in this
+   section do not apply to any claims or Losses relating to any actual or
+   alleged intellectual property infringement. In order to qualify, an
+   Indemnified Contributor must: a) promptly notify the Commercial
+   Contributor in writing of such claim, and b) allow the Commercial
+   Contributor to control, and cooperate with the Commercial Contributor
+   in, the defense and any related settlement negotiations. The
+   Indemnified Contributor may participate in any such claim at its own
+   expense.
+ .
+   For example, a Contributor might include the Program in a commercial
+   product offering, Product X. That Contributor is then a Commercial
+   Contributor. If that Commercial Contributor then makes performance
+   claims, or offers warranties related to Product X, those performance
+   claims and warranties are such Commercial Contributor's responsibility
+   alone. Under this section, the Commercial Contributor would have to
+   defend claims against the other Contributors related to those
+   performance claims and warranties, and if a court requires any other
+   Contributor to pay any damages as a result, the Commercial Contributor
+   must pay those damages.
+ .
+ .
+   5. NO WARRANTY
+ .
+   EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+   PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+   WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+   FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible
+   for determining the appropriateness of using and distributing the
+   Program and assumes all risks associated with its exercise of rights
+   under this Agreement, including but not limited to the risks and costs
+   of program errors, compliance with applicable laws, damage to or loss
+   of data, programs or equipment, and unavailability or interruption of
+   operations.
+ .
+ .
+   6. DISCLAIMER OF LIABILITY
+ .
+   EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+   ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+   WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+   DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ .
+ .
+   7. GENERAL
+ .
+   If any provision of this Agreement is invalid or unenforceable under
+   applicable law, it shall not affect the validity or enforceability of
+   the remainder of the terms of this Agreement, and without further
+   action by the parties hereto, such provision shall be reformed to the
+   minimum extent necessary to make such provision valid and enforceable.
+ .
+   If Recipient institutes patent litigation against a Contributor with
+   respect to a patent applicable to software (including a cross-claim or
+   counterclaim in a lawsuit), then any patent licenses granted by that
+   Contributor to such Recipient under this Agreement shall terminate as
+   of the date such litigation is filed. In addition, if Recipient
+   institutes patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Program
+   itself (excluding combinations of the Program with other software or
+   hardware) infringes such Recipient's patent(s), then such Recipient's
+   rights granted under Section 2(b) shall terminate as of the date such
+   litigation is filed.
+ .
+   All Recipient's rights under this Agreement shall terminate if it fails
+   to comply with any of the material terms or conditions of this
+   Agreement and does not cure such failure in a reasonable period of time
+   after becoming aware of such noncompliance. If all Recipient's rights
+   under this Agreement terminate, Recipient agrees to cease use and
+   distribution of the Program as soon as reasonably practicable. However,
+   Recipient's obligations under this Agreement and any licenses granted
+   by Recipient relating to the Program shall continue and survive.
+ .
+   Everyone is permitted to copy and distribute copies of this Agreement,
+   but in order to avoid inconsistency the Agreement is copyrighted and
+   may only be modified in the following manner. The Agreement Steward
+   reserves the right to publish new versions (including revisions) of
+   this Agreement from time to time. No one other than the Agreement
+   Steward has the right to modify this Agreement. IBM is the initial
+   Agreement Steward. IBM may assign the responsibility to serve as the
+   Agreement Steward to a suitable separate entity. Each new version of
+   the Agreement will be given a distinguishing version number. The
+   Program (including Contributions) may always be distributed subject to
+   the version of the Agreement under which it was received. In addition,
+   after a new version of the Agreement is published, Contributor may
+   elect to distribute the Program (including its Contributions) under the
+   new version. Except as expressly stated in Sections 2(a) and 2(b)
+   above, Recipient receives no rights or licenses to the intellectual
+   property of any Contributor under this Agreement, whether expressly, by
+   implication, estoppel or otherwise. All rights in the Program not
+   expressly granted under this Agreement are reserved.
+ .
+   This Agreement is governed by the laws of the State of New York and the
+   intellectual property laws of the United States of America. No party to
+   this Agreement will bring a legal action under this Agreement more than
+   one year after the cause of action arose. Each party waives its rights
+   to a jury trial in any resulting litigation.
 
 Files: debian/*
 Copyright: 2016 Canonical LTD
@@ -268,4 +268,4 @@
  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+ POSSIBILITY OF SUCH DAMAGE.
diff -Nru libica-3.9.0/debian/libica3.install libica-4.0.0/debian/libica3.install
--- libica-3.9.0/debian/libica3.install	2017-10-04 11:28:19.000000000 +0200
+++ libica-4.0.0/debian/libica3.install	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-usr/lib/*/lib*.so.3
-usr/lib/*/lib*.so.3.*
diff -Nru libica-3.9.0/debian/libica3.symbols libica-4.0.0/debian/libica3.symbols
--- libica-3.9.0/debian/libica3.symbols	2019-08-30 11:47:15.000000000 +0200
+++ libica-4.0.0/debian/libica3.symbols	1970-01-01 01:00:00.000000000 +0100
@@ -1,128 +0,0 @@
-libica.so.3 libica3 #MINVER#
- ICA_DRBG_SHA512@LIBICA_3.0.0 3.2.0
- LIBICA_3.0.0@LIBICA_3.0.0 3.2.0
- LIBICA_3.0.0_FIPS@LIBICA_3.0.0_FIPS 3.2.0
- LIBICA_3.1.0@LIBICA_3.1.0 3.2.0
- LIBICA_3.2.0@LIBICA_3.2.0 3.2.0
- LIBICA_3.3.0@LIBICA_3.3.0 3.3.3
- LIBICA_3.4.0@LIBICA_3.4.0 3.4.0
- LIBICA_3.5.0@LIBICA_3.5.0 3.5.0
- LIBICA_3.6.0@LIBICA_3.6.0 3.6.0
- ica_3des_cbc@LIBICA_3.0.0 3.2.0
- ica_3des_cbc_cs@LIBICA_3.0.0 3.2.0
- ica_3des_cfb@LIBICA_3.0.0 3.2.0
- ica_3des_cmac@LIBICA_3.0.0 3.2.0
- ica_3des_cmac_intermediate@LIBICA_3.0.0 3.2.0
- ica_3des_cmac_last@LIBICA_3.0.0 3.2.0
- ica_3des_ctr@LIBICA_3.0.0 3.2.0
- ica_3des_ctrlist@LIBICA_3.0.0 3.2.0
- ica_3des_decrypt@LIBICA_3.0.0 3.2.0
- ica_3des_ecb@LIBICA_3.0.0 3.2.0
- ica_3des_encrypt@LIBICA_3.0.0 3.2.0
- ica_3des_ofb@LIBICA_3.0.0 3.2.0
- ica_aes_cbc@LIBICA_3.0.0 3.2.0
- ica_aes_cbc_cs@LIBICA_3.0.0 3.2.0
- ica_aes_ccm@LIBICA_3.0.0 3.2.0
- ica_aes_cfb@LIBICA_3.0.0 3.2.0
- ica_aes_cmac@LIBICA_3.0.0 3.2.0
- ica_aes_cmac_intermediate@LIBICA_3.0.0 3.2.0
- ica_aes_cmac_last@LIBICA_3.0.0 3.2.0
- ica_aes_ctr@LIBICA_3.0.0 3.2.0
- ica_aes_ctrlist@LIBICA_3.0.0 3.2.0
- ica_aes_decrypt@LIBICA_3.0.0 3.2.0
- ica_aes_ecb@LIBICA_3.0.0 3.2.0
- ica_aes_encrypt@LIBICA_3.0.0 3.2.0
- ica_aes_gcm@LIBICA_3.0.0 3.2.0
- ica_aes_gcm_initialize@LIBICA_3.0.0 3.2.0
- ica_aes_gcm_intermediate@LIBICA_3.0.0 3.2.0
- ica_aes_gcm_kma_ctx_free@LIBICA_3.2.0 3.2.0
- ica_aes_gcm_kma_ctx_new@LIBICA_3.2.0 3.2.0
- ica_aes_gcm_kma_get_tag@LIBICA_3.2.0 3.2.0
- ica_aes_gcm_kma_init@LIBICA_3.2.0 3.2.0
- ica_aes_gcm_kma_update@LIBICA_3.2.0 3.2.0
- ica_aes_gcm_kma_verify_tag@LIBICA_3.2.0 3.2.0
- ica_aes_gcm_last@LIBICA_3.0.0 3.2.0
- ica_aes_ofb@LIBICA_3.0.0 3.2.0
- ica_aes_xts@LIBICA_3.0.0 3.2.0
- ica_close_adapter@LIBICA_3.0.0 3.2.0
- ica_des_cbc@LIBICA_3.0.0 3.2.0
- ica_des_cbc_cs@LIBICA_3.0.0 3.2.0
- ica_des_cfb@LIBICA_3.0.0 3.2.0
- ica_des_cmac@LIBICA_3.0.0 3.2.0
- ica_des_cmac_intermediate@LIBICA_3.0.0 3.2.0
- ica_des_cmac_last@LIBICA_3.0.0 3.2.0
- ica_des_ctr@LIBICA_3.0.0 3.2.0
- ica_des_ctrlist@LIBICA_3.0.0 3.2.0
- ica_des_decrypt@LIBICA_3.0.0 3.2.0
- ica_des_ecb@LIBICA_3.0.0 3.2.0
- ica_des_encrypt@LIBICA_3.0.0 3.2.0
- ica_des_ofb@LIBICA_3.0.0 3.2.0
- ica_drbg_generate@LIBICA_3.0.0 3.2.0
- ica_drbg_health_test@LIBICA_3.0.0 3.2.0
- ica_drbg_instantiate@LIBICA_3.0.0 3.2.0
- ica_drbg_reseed@LIBICA_3.0.0 3.2.0
- ica_drbg_uninstantiate@LIBICA_3.0.0 3.2.0
- ica_ec_key_free@LIBICA_3.3.0 3.3.3
- ica_ec_key_generate@LIBICA_3.3.0 3.3.3
- ica_ec_key_get_private_key@LIBICA_3.3.0 3.3.3
- ica_ec_key_get_public_key@LIBICA_3.3.0 3.3.3
- ica_ec_key_init@LIBICA_3.3.0 3.3.3
- ica_ec_key_new@LIBICA_3.3.0 3.3.3
- ica_ecdh_derive_secret@LIBICA_3.3.0 3.3.3
- ica_ecdsa_sign@LIBICA_3.3.0 3.3.3
- ica_ecdsa_verify@LIBICA_3.3.0 3.3.3
- ica_ed25519_ctx_del@LIBICA_3.6.0 3.6.0
- ica_ed25519_ctx_new@LIBICA_3.6.0 3.6.0
- ica_ed25519_key_gen@LIBICA_3.6.0 3.6.0
- ica_ed25519_key_get@LIBICA_3.6.0 3.6.0
- ica_ed25519_key_set@LIBICA_3.6.0 3.6.0
- ica_ed25519_sign@LIBICA_3.6.0 3.6.0
- ica_ed25519_verify@LIBICA_3.6.0 3.6.0
- ica_ed448_ctx_del@LIBICA_3.6.0 3.6.0
- ica_ed448_ctx_new@LIBICA_3.6.0 3.6.0
- ica_ed448_key_gen@LIBICA_3.6.0 3.6.0
- ica_ed448_key_get@LIBICA_3.6.0 3.6.0
- ica_ed448_key_set@LIBICA_3.6.0 3.6.0
- ica_ed448_sign@LIBICA_3.6.0 3.6.0
- ica_ed448_verify@LIBICA_3.6.0 3.6.0
- ica_get_functionlist@LIBICA_3.0.0 3.2.0
- ica_get_version@LIBICA_3.0.0 3.2.0
- ica_mp_mul512@LIBICA_3.3.0 3.3.3
- ica_mp_sqr512@LIBICA_3.3.0 3.3.3
- ica_open_adapter@LIBICA_3.0.0 3.2.0
- ica_random_number_generate@LIBICA_3.0.0 3.2.0
- ica_rsa_crt@LIBICA_3.0.0 3.2.0
- ica_rsa_crt_key_check@LIBICA_3.0.0 3.2.0
- ica_rsa_key_generate_crt@LIBICA_3.0.0 3.2.0
- ica_rsa_key_generate_mod_expo@LIBICA_3.0.0 3.2.0
- ica_rsa_mod_expo@LIBICA_3.0.0 3.2.0
- ica_set_fallback_mode@LIBICA_3.3.0 3.3.3
- ica_set_offload_mode@LIBICA_3.5.0 3.5.0
- ica_set_stats_mode@LIBICA_3.5.0 3.5.0
- ica_sha1@LIBICA_3.0.0 3.2.0
- ica_sha224@LIBICA_3.0.0 3.2.0
- ica_sha256@LIBICA_3.0.0 3.2.0
- ica_sha384@LIBICA_3.0.0 3.2.0
- ica_sha3_224@LIBICA_3.1.0 3.2.0
- ica_sha3_256@LIBICA_3.1.0 3.2.0
- ica_sha3_384@LIBICA_3.1.0 3.2.0
- ica_sha3_512@LIBICA_3.1.0 3.2.0
- ica_sha512@LIBICA_3.0.0 3.2.0
- ica_sha512_224@LIBICA_3.4.0 3.4.0
- ica_sha512_256@LIBICA_3.4.0 3.4.0
- ica_shake_128@LIBICA_3.1.0 3.2.0
- ica_shake_256@LIBICA_3.1.0 3.2.0
- ica_x25519_ctx_del@LIBICA_3.6.0 3.6.0
- ica_x25519_ctx_new@LIBICA_3.6.0 3.6.0
- ica_x25519_derive@LIBICA_3.6.0 3.6.0
- ica_x25519_key_gen@LIBICA_3.6.0 3.6.0
- ica_x25519_key_get@LIBICA_3.6.0 3.6.0
- ica_x25519_key_set@LIBICA_3.6.0 3.6.0
- ica_x448_ctx_del@LIBICA_3.6.0 3.6.0
- ica_x448_ctx_new@LIBICA_3.6.0 3.6.0
- ica_x448_derive@LIBICA_3.6.0 3.6.0
- ica_x448_key_gen@LIBICA_3.6.0 3.6.0
- ica_x448_key_get@LIBICA_3.6.0 3.6.0
- ica_x448_key_set@LIBICA_3.6.0 3.6.0
- s390_get_functionlist@LIBICA_3.0.0 3.2.0
- s390_initialize_functionlist@LIBICA_3.0.0 3.2.0
diff -Nru libica-3.9.0/debian/libica4.install libica-4.0.0/debian/libica4.install
--- libica-3.9.0/debian/libica4.install	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/libica4.install	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,2 @@
+usr/lib/*/lib*.so.4
+usr/lib/*/lib*.so.4.*
diff -Nru libica-3.9.0/debian/libica4.symbols libica-4.0.0/debian/libica4.symbols
--- libica-3.9.0/debian/libica4.symbols	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/libica4.symbols	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,242 @@
+libica-cex.so.4 libica4 #MINVER#
+ ICA_DRBG_SHA512@LIBICA_3.0.0 4.0.0
+ LIBICA_3.0.0@LIBICA_3.0.0 4.0.0
+ LIBICA_3.0.0_FIPS@LIBICA_3.0.0_FIPS 4.0.0
+ LIBICA_3.1.0@LIBICA_3.1.0 4.0.0
+ LIBICA_3.2.0@LIBICA_3.2.0 4.0.0
+ LIBICA_3.3.0@LIBICA_3.3.0 4.0.0
+ LIBICA_3.4.0@LIBICA_3.4.0 4.0.0
+ LIBICA_3.5.0@LIBICA_3.5.0 4.0.0
+ LIBICA_3.6.0@LIBICA_3.6.0 4.0.0
+ ica_3des_cbc@LIBICA_3.0.0 4.0.0
+ ica_3des_cbc_cs@LIBICA_3.0.0 4.0.0
+ ica_3des_cfb@LIBICA_3.0.0 4.0.0
+ ica_3des_cmac@LIBICA_3.0.0 4.0.0
+ ica_3des_cmac_intermediate@LIBICA_3.0.0 4.0.0
+ ica_3des_cmac_last@LIBICA_3.0.0 4.0.0
+ ica_3des_ctr@LIBICA_3.0.0 4.0.0
+ ica_3des_ctrlist@LIBICA_3.0.0 4.0.0
+ ica_3des_ecb@LIBICA_3.0.0 4.0.0
+ ica_3des_ofb@LIBICA_3.0.0 4.0.0
+ ica_aes_cbc@LIBICA_3.0.0 4.0.0
+ ica_aes_cbc_cs@LIBICA_3.0.0 4.0.0
+ ica_aes_ccm@LIBICA_3.0.0 4.0.0
+ ica_aes_cfb@LIBICA_3.0.0 4.0.0
+ ica_aes_cmac@LIBICA_3.0.0 4.0.0
+ ica_aes_cmac_intermediate@LIBICA_3.0.0 4.0.0
+ ica_aes_cmac_last@LIBICA_3.0.0 4.0.0
+ ica_aes_ctr@LIBICA_3.0.0 4.0.0
+ ica_aes_ctrlist@LIBICA_3.0.0 4.0.0
+ ica_aes_ecb@LIBICA_3.0.0 4.0.0
+ ica_aes_gcm@LIBICA_3.0.0 4.0.0
+ ica_aes_gcm_initialize@LIBICA_3.0.0 4.0.0
+ ica_aes_gcm_intermediate@LIBICA_3.0.0 4.0.0
+ ica_aes_gcm_kma_ctx_free@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_ctx_new@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_get_tag@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_init@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_update@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_verify_tag@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_last@LIBICA_3.0.0 4.0.0
+ ica_aes_ofb@LIBICA_3.0.0 4.0.0
+ ica_aes_xts@LIBICA_3.0.0 4.0.0
+ ica_close_adapter@LIBICA_3.0.0 4.0.0
+ ica_des_cbc@LIBICA_3.0.0 4.0.0
+ ica_des_cbc_cs@LIBICA_3.0.0 4.0.0
+ ica_des_cfb@LIBICA_3.0.0 4.0.0
+ ica_des_cmac@LIBICA_3.0.0 4.0.0
+ ica_des_cmac_intermediate@LIBICA_3.0.0 4.0.0
+ ica_des_cmac_last@LIBICA_3.0.0 4.0.0
+ ica_des_ctr@LIBICA_3.0.0 4.0.0
+ ica_des_ctrlist@LIBICA_3.0.0 4.0.0
+ ica_des_ecb@LIBICA_3.0.0 4.0.0
+ ica_des_ofb@LIBICA_3.0.0 4.0.0
+ ica_drbg_generate@LIBICA_3.0.0 4.0.0
+ ica_drbg_health_test@LIBICA_3.0.0 4.0.0
+ ica_drbg_instantiate@LIBICA_3.0.0 4.0.0
+ ica_drbg_reseed@LIBICA_3.0.0 4.0.0
+ ica_drbg_uninstantiate@LIBICA_3.0.0 4.0.0
+ ica_ec_key_free@LIBICA_3.3.0 4.0.0
+ ica_ec_key_generate@LIBICA_3.3.0 4.0.0
+ ica_ec_key_get_private_key@LIBICA_3.3.0 4.0.0
+ ica_ec_key_get_public_key@LIBICA_3.3.0 4.0.0
+ ica_ec_key_init@LIBICA_3.3.0 4.0.0
+ ica_ec_key_new@LIBICA_3.3.0 4.0.0
+ ica_ecdh_derive_secret@LIBICA_3.3.0 4.0.0
+ ica_ecdsa_sign@LIBICA_3.3.0 4.0.0
+ ica_ecdsa_verify@LIBICA_3.3.0 4.0.0
+ ica_ed25519_ctx_del@LIBICA_3.6.0 4.0.0
+ ica_ed25519_ctx_new@LIBICA_3.6.0 4.0.0
+ ica_ed25519_key_gen@LIBICA_3.6.0 4.0.0
+ ica_ed25519_key_get@LIBICA_3.6.0 4.0.0
+ ica_ed25519_key_set@LIBICA_3.6.0 4.0.0
+ ica_ed25519_sign@LIBICA_3.6.0 4.0.0
+ ica_ed25519_verify@LIBICA_3.6.0 4.0.0
+ ica_ed448_ctx_del@LIBICA_3.6.0 4.0.0
+ ica_ed448_ctx_new@LIBICA_3.6.0 4.0.0
+ ica_ed448_key_gen@LIBICA_3.6.0 4.0.0
+ ica_ed448_key_get@LIBICA_3.6.0 4.0.0
+ ica_ed448_key_set@LIBICA_3.6.0 4.0.0
+ ica_ed448_sign@LIBICA_3.6.0 4.0.0
+ ica_ed448_verify@LIBICA_3.6.0 4.0.0
+ ica_fips_status@LIBICA_3.0.0_FIPS 4.0.0
+ ica_get_functionlist@LIBICA_3.0.0 4.0.0
+ ica_get_version@LIBICA_3.0.0 4.0.0
+ ica_mp_mul512@LIBICA_3.3.0 4.0.0
+ ica_mp_sqr512@LIBICA_3.3.0 4.0.0
+ ica_open_adapter@LIBICA_3.0.0 4.0.0
+ ica_random_number_generate@LIBICA_3.0.0 4.0.0
+ ica_rsa_crt@LIBICA_3.0.0 4.0.0
+ ica_rsa_crt_key_check@LIBICA_3.0.0 4.0.0
+ ica_rsa_key_generate_crt@LIBICA_3.0.0 4.0.0
+ ica_rsa_key_generate_mod_expo@LIBICA_3.0.0 4.0.0
+ ica_rsa_mod_expo@LIBICA_3.0.0 4.0.0
+ ica_set_fallback_mode@LIBICA_3.3.0 4.0.0
+ ica_set_offload_mode@LIBICA_3.5.0 4.0.0
+ ica_set_stats_mode@LIBICA_3.5.0 4.0.0
+ ica_sha1@LIBICA_3.0.0 4.0.0
+ ica_sha224@LIBICA_3.0.0 4.0.0
+ ica_sha256@LIBICA_3.0.0 4.0.0
+ ica_sha384@LIBICA_3.0.0 4.0.0
+ ica_sha3_224@LIBICA_3.1.0 4.0.0
+ ica_sha3_256@LIBICA_3.1.0 4.0.0
+ ica_sha3_384@LIBICA_3.1.0 4.0.0
+ ica_sha3_512@LIBICA_3.1.0 4.0.0
+ ica_sha512@LIBICA_3.0.0 4.0.0
+ ica_sha512_224@LIBICA_3.4.0 4.0.0
+ ica_sha512_256@LIBICA_3.4.0 4.0.0
+ ica_shake_128@LIBICA_3.1.0 4.0.0
+ ica_shake_256@LIBICA_3.1.0 4.0.0
+ ica_x25519_ctx_del@LIBICA_3.6.0 4.0.0
+ ica_x25519_ctx_new@LIBICA_3.6.0 4.0.0
+ ica_x25519_derive@LIBICA_3.6.0 4.0.0
+ ica_x25519_key_gen@LIBICA_3.6.0 4.0.0
+ ica_x25519_key_get@LIBICA_3.6.0 4.0.0
+ ica_x25519_key_set@LIBICA_3.6.0 4.0.0
+ ica_x448_ctx_del@LIBICA_3.6.0 4.0.0
+ ica_x448_ctx_new@LIBICA_3.6.0 4.0.0
+ ica_x448_derive@LIBICA_3.6.0 4.0.0
+ ica_x448_key_gen@LIBICA_3.6.0 4.0.0
+ ica_x448_key_get@LIBICA_3.6.0 4.0.0
+ ica_x448_key_set@LIBICA_3.6.0 4.0.0
+libica.so.4 libica4 #MINVER#
+ ICA_DRBG_SHA512@LIBICA_3.0.0 4.0.0
+ LIBICA_3.0.0@LIBICA_3.0.0 4.0.0
+ LIBICA_3.0.0_FIPS@LIBICA_3.0.0_FIPS 4.0.0
+ LIBICA_3.1.0@LIBICA_3.1.0 4.0.0
+ LIBICA_3.2.0@LIBICA_3.2.0 4.0.0
+ LIBICA_3.3.0@LIBICA_3.3.0 4.0.0
+ LIBICA_3.4.0@LIBICA_3.4.0 4.0.0
+ LIBICA_3.5.0@LIBICA_3.5.0 4.0.0
+ LIBICA_3.6.0@LIBICA_3.6.0 4.0.0
+ ica_3des_cbc@LIBICA_3.0.0 4.0.0
+ ica_3des_cbc_cs@LIBICA_3.0.0 4.0.0
+ ica_3des_cfb@LIBICA_3.0.0 4.0.0
+ ica_3des_cmac@LIBICA_3.0.0 4.0.0
+ ica_3des_cmac_intermediate@LIBICA_3.0.0 4.0.0
+ ica_3des_cmac_last@LIBICA_3.0.0 4.0.0
+ ica_3des_ctr@LIBICA_3.0.0 4.0.0
+ ica_3des_ctrlist@LIBICA_3.0.0 4.0.0
+ ica_3des_ecb@LIBICA_3.0.0 4.0.0
+ ica_3des_ofb@LIBICA_3.0.0 4.0.0
+ ica_aes_cbc@LIBICA_3.0.0 4.0.0
+ ica_aes_cbc_cs@LIBICA_3.0.0 4.0.0
+ ica_aes_ccm@LIBICA_3.0.0 4.0.0
+ ica_aes_cfb@LIBICA_3.0.0 4.0.0
+ ica_aes_cmac@LIBICA_3.0.0 4.0.0
+ ica_aes_cmac_intermediate@LIBICA_3.0.0 4.0.0
+ ica_aes_cmac_last@LIBICA_3.0.0 4.0.0
+ ica_aes_ctr@LIBICA_3.0.0 4.0.0
+ ica_aes_ctrlist@LIBICA_3.0.0 4.0.0
+ ica_aes_ecb@LIBICA_3.0.0 4.0.0
+ ica_aes_gcm@LIBICA_3.0.0 4.0.0
+ ica_aes_gcm_initialize@LIBICA_3.0.0 4.0.0
+ ica_aes_gcm_intermediate@LIBICA_3.0.0 4.0.0
+ ica_aes_gcm_kma_ctx_free@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_ctx_new@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_get_tag@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_init@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_update@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_kma_verify_tag@LIBICA_3.2.0 4.0.0
+ ica_aes_gcm_last@LIBICA_3.0.0 4.0.0
+ ica_aes_ofb@LIBICA_3.0.0 4.0.0
+ ica_aes_xts@LIBICA_3.0.0 4.0.0
+ ica_close_adapter@LIBICA_3.0.0 4.0.0
+ ica_des_cbc@LIBICA_3.0.0 4.0.0
+ ica_des_cbc_cs@LIBICA_3.0.0 4.0.0
+ ica_des_cfb@LIBICA_3.0.0 4.0.0
+ ica_des_cmac@LIBICA_3.0.0 4.0.0
+ ica_des_cmac_intermediate@LIBICA_3.0.0 4.0.0
+ ica_des_cmac_last@LIBICA_3.0.0 4.0.0
+ ica_des_ctr@LIBICA_3.0.0 4.0.0
+ ica_des_ctrlist@LIBICA_3.0.0 4.0.0
+ ica_des_ecb@LIBICA_3.0.0 4.0.0
+ ica_des_ofb@LIBICA_3.0.0 4.0.0
+ ica_drbg_generate@LIBICA_3.0.0 4.0.0
+ ica_drbg_health_test@LIBICA_3.0.0 4.0.0
+ ica_drbg_instantiate@LIBICA_3.0.0 4.0.0
+ ica_drbg_reseed@LIBICA_3.0.0 4.0.0
+ ica_drbg_uninstantiate@LIBICA_3.0.0 4.0.0
+ ica_ec_key_free@LIBICA_3.3.0 4.0.0
+ ica_ec_key_generate@LIBICA_3.3.0 4.0.0
+ ica_ec_key_get_private_key@LIBICA_3.3.0 4.0.0
+ ica_ec_key_get_public_key@LIBICA_3.3.0 4.0.0
+ ica_ec_key_init@LIBICA_3.3.0 4.0.0
+ ica_ec_key_new@LIBICA_3.3.0 4.0.0
+ ica_ecdh_derive_secret@LIBICA_3.3.0 4.0.0
+ ica_ecdsa_sign@LIBICA_3.3.0 4.0.0
+ ica_ecdsa_verify@LIBICA_3.3.0 4.0.0
+ ica_ed25519_ctx_del@LIBICA_3.6.0 4.0.0
+ ica_ed25519_ctx_new@LIBICA_3.6.0 4.0.0
+ ica_ed25519_key_gen@LIBICA_3.6.0 4.0.0
+ ica_ed25519_key_get@LIBICA_3.6.0 4.0.0
+ ica_ed25519_key_set@LIBICA_3.6.0 4.0.0
+ ica_ed25519_sign@LIBICA_3.6.0 4.0.0
+ ica_ed25519_verify@LIBICA_3.6.0 4.0.0
+ ica_ed448_ctx_del@LIBICA_3.6.0 4.0.0
+ ica_ed448_ctx_new@LIBICA_3.6.0 4.0.0
+ ica_ed448_key_gen@LIBICA_3.6.0 4.0.0
+ ica_ed448_key_get@LIBICA_3.6.0 4.0.0
+ ica_ed448_key_set@LIBICA_3.6.0 4.0.0
+ ica_ed448_sign@LIBICA_3.6.0 4.0.0
+ ica_ed448_verify@LIBICA_3.6.0 4.0.0
+ ica_fips_status@LIBICA_3.0.0_FIPS 4.0.0
+ ica_get_functionlist@LIBICA_3.0.0 4.0.0
+ ica_get_version@LIBICA_3.0.0 4.0.0
+ ica_mp_mul512@LIBICA_3.3.0 4.0.0
+ ica_mp_sqr512@LIBICA_3.3.0 4.0.0
+ ica_open_adapter@LIBICA_3.0.0 4.0.0
+ ica_random_number_generate@LIBICA_3.0.0 4.0.0
+ ica_rsa_crt@LIBICA_3.0.0 4.0.0
+ ica_rsa_crt_key_check@LIBICA_3.0.0 4.0.0
+ ica_rsa_key_generate_crt@LIBICA_3.0.0 4.0.0
+ ica_rsa_key_generate_mod_expo@LIBICA_3.0.0 4.0.0
+ ica_rsa_mod_expo@LIBICA_3.0.0 4.0.0
+ ica_set_fallback_mode@LIBICA_3.3.0 4.0.0
+ ica_set_offload_mode@LIBICA_3.5.0 4.0.0
+ ica_set_stats_mode@LIBICA_3.5.0 4.0.0
+ ica_sha1@LIBICA_3.0.0 4.0.0
+ ica_sha224@LIBICA_3.0.0 4.0.0
+ ica_sha256@LIBICA_3.0.0 4.0.0
+ ica_sha384@LIBICA_3.0.0 4.0.0
+ ica_sha3_224@LIBICA_3.1.0 4.0.0
+ ica_sha3_256@LIBICA_3.1.0 4.0.0
+ ica_sha3_384@LIBICA_3.1.0 4.0.0
+ ica_sha3_512@LIBICA_3.1.0 4.0.0
+ ica_sha512@LIBICA_3.0.0 4.0.0
+ ica_sha512_224@LIBICA_3.4.0 4.0.0
+ ica_sha512_256@LIBICA_3.4.0 4.0.0
+ ica_shake_128@LIBICA_3.1.0 4.0.0
+ ica_shake_256@LIBICA_3.1.0 4.0.0
+ ica_x25519_ctx_del@LIBICA_3.6.0 4.0.0
+ ica_x25519_ctx_new@LIBICA_3.6.0 4.0.0
+ ica_x25519_derive@LIBICA_3.6.0 4.0.0
+ ica_x25519_key_gen@LIBICA_3.6.0 4.0.0
+ ica_x25519_key_get@LIBICA_3.6.0 4.0.0
+ ica_x25519_key_set@LIBICA_3.6.0 4.0.0
+ ica_x448_ctx_del@LIBICA_3.6.0 4.0.0
+ ica_x448_ctx_new@LIBICA_3.6.0 4.0.0
+ ica_x448_derive@LIBICA_3.6.0 4.0.0
+ ica_x448_key_gen@LIBICA_3.6.0 4.0.0
+ ica_x448_key_get@LIBICA_3.6.0 4.0.0
+ ica_x448_key_set@LIBICA_3.6.0 4.0.0
diff -Nru libica-3.9.0/debian/patches/28fa931bed9e6847137829952a3e7cc6091bd071.patch libica-4.0.0/debian/patches/28fa931bed9e6847137829952a3e7cc6091bd071.patch
--- libica-3.9.0/debian/patches/28fa931bed9e6847137829952a3e7cc6091bd071.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/28fa931bed9e6847137829952a3e7cc6091bd071.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,60 @@
+From 28fa931bed9e6847137829952a3e7cc6091bd071 Mon Sep 17 00:00:00 2001
+From: Ingo Franzki <ifranzki@linux.ibm.com>
+Date: Mon, 24 Jan 2022 10:24:44 +0100
+Subject: [PATCH 07/10] Fix compile warnings
+
+... like potentially uninitialized variables or unused functions.
+
+Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
+---
+--- a/src/fips.c
++++ b/src/fips.c
+@@ -1304,8 +1304,8 @@
+ 	ica_adapter_handle_t ah;
+ 	const struct rsa_tv *tv;
+ 	size_t i, keylen, crtparamlen;
+-	unsigned char *out;
+-	libica_func_list_element* libica_func_list;
++	unsigned char *out = NULL;
++	libica_func_list_element* libica_func_list = NULL;
+ 	unsigned int count;
+ 
+ 	if (ica_open_adapter(&ah))
+--- a/src/ica_api.c
++++ b/src/ica_api.c
+@@ -90,6 +90,7 @@
+ 	ica_stats_enabled = stats_mode ? 1 : 0;
+ }
+ 
++#ifndef NO_CPACF
+ #ifdef ICA_FIPS
+ static unsigned int fips_check_3des_key(const ica_des_key_triple_t *key) {
+ 	if (!CRYPTO_memcmp(key->key1, key->key2, DES_KEY_LEN64)
+@@ -101,7 +102,6 @@
+ }
+ #endif
+ 
+-#ifndef NO_CPACF
+ static unsigned int check_des_parms(unsigned int mode,
+ 				    unsigned long data_length,
+ 				    const unsigned char *in_data,
+--- a/src/s390_ecc.c
++++ b/src/s390_ecc.c
+@@ -147,7 +147,7 @@
+ 	EC_POINT *point = NULL;
+ 	BIGNUM *bn_priv = NULL;
+ #if !OPENSSL_VERSION_PREREQ(3, 0)
+-	EC_KEY *ec_key;
++	EC_KEY *ec_key = NULL;
+ #else
+ 	unsigned char *pub_key = NULL;
+ 	unsigned int pub_key_len;
+@@ -262,7 +262,7 @@
+ {
+ 	int ok = 0;
+ #if !OPENSSL_VERSION_PREREQ(3, 0)
+-	EC_KEY *ec_key;
++	EC_KEY *ec_key = NULL;
+ #else
+ 	OSSL_PARAM_BLD *tmpl = NULL;
+ 	int rc;
diff -Nru libica-3.9.0/debian/patches/553977ef505b43c7d17056369ed518a971d43d68.patch libica-4.0.0/debian/patches/553977ef505b43c7d17056369ed518a971d43d68.patch
--- libica-3.9.0/debian/patches/553977ef505b43c7d17056369ed518a971d43d68.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/553977ef505b43c7d17056369ed518a971d43d68.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,66 @@
+From 553977ef505b43c7d17056369ed518a971d43d68 Mon Sep 17 00:00:00 2001
+From: Ingo Franzki <ifranzki@linux.ibm.com>
+Date: Wed, 5 Jan 2022 09:07:51 +0100
+Subject: [PATCH 02/10] ECC: fix memory leaks in make_eckey()
+
+Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
+---
+--- a/src/s390_ecc.c
++++ b/src/s390_ecc.c
+@@ -146,12 +146,12 @@
+ 	EC_GROUP *group = NULL;
+ 	EC_POINT *point = NULL;
+ 	BIGNUM *bn_priv = NULL;
+-	unsigned char *pub_key = NULL;
+-	unsigned int pub_key_len;
+-	point_conversion_form_t form;
+ #if !OPENSSL_VERSION_PREREQ(3, 0)
+ 	EC_KEY *ec_key;
+ #else
++	unsigned char *pub_key = NULL;
++	unsigned int pub_key_len;
++	point_conversion_form_t form;
+ 	OSSL_PARAM_BLD *tmpl = NULL;
+ 	int rc;
+ #endif
+@@ -175,18 +175,13 @@
+ 		goto err;
+ 	}
+ 
+-	form = EC_GROUP_get_point_conversion_form(group);
+-	pub_key_len = EC_POINT_point2buf(group, point, form, &pub_key, NULL);
+-	if (pub_key_len == 0) {
+-		goto err;
+-	}
+-
+ #if !OPENSSL_VERSION_PREREQ(3, 0)
+ 	ec_key = EC_KEY_new_by_curve_name(nid);
+ 	if (ec_key == NULL) {
+ 		goto err;
+ 	}
+ 
++	EC_POINT_free(point);
+ 	point = EC_POINT_new(EC_KEY_get0_group(ec_key));
+ 	if (point == NULL) {
+ 		goto err;
+@@ -209,6 +204,11 @@
+ 	}
+ 
+ #else
++	form = EC_GROUP_get_point_conversion_form(group);
++	pub_key_len = EC_POINT_point2buf(group, point, form, &pub_key, NULL);
++	if (pub_key_len == 0) {
++		goto err;
++	}
+ 
+ 	tmpl = OSSL_PARAM_BLD_new();
+ 	if (tmpl == NULL) {
+@@ -243,6 +243,8 @@
+ #else
+ 	if (tmpl)
+ 		OSSL_PARAM_BLD_free(tmpl);
++	if (pub_key)
++		OPENSSL_free(pub_key);
+ #endif
+ 
+ 	if (ok)
diff -Nru libica-3.9.0/debian/patches/5aa9366c236a6d17570403ef81c65e4f5f91a8af.patch libica-4.0.0/debian/patches/5aa9366c236a6d17570403ef81c65e4f5f91a8af.patch
--- libica-3.9.0/debian/patches/5aa9366c236a6d17570403ef81c65e4f5f91a8af.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/5aa9366c236a6d17570403ef81c65e4f5f91a8af.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,18 @@
+From 5aa9366c236a6d17570403ef81c65e4f5f91a8af Mon Sep 17 00:00:00 2001
+From: Ingo Franzki <ifranzki@linux.ibm.com>
+Date: Wed, 26 Jan 2022 09:29:27 +0100
+Subject: [PATCH 10/10] MAKEFILE: Do not install ec_internal_test
+
+Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
+---
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -90,7 +90,7 @@
+ # internal tests
+ 
+ if ICA_INTERNAL_TESTS
+-bin_PROGRAMS += internal_tests/ec_internal_test
++noinst_PROGRAMS = internal_tests/ec_internal_test
+ 
+ internal_tests_ec_internal_test_CFLAGS = ${AM_CFLAGS} -I${srcdir}/include \
+ 					 -I${srcdir}/../include	\
diff -Nru libica-3.9.0/debian/patches/6031ec80a5ada52609822fed4a6bd2cccafe5563.patch libica-4.0.0/debian/patches/6031ec80a5ada52609822fed4a6bd2cccafe5563.patch
--- libica-3.9.0/debian/patches/6031ec80a5ada52609822fed4a6bd2cccafe5563.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/6031ec80a5ada52609822fed4a6bd2cccafe5563.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,44 @@
+From 6031ec80a5ada52609822fed4a6bd2cccafe5563 Mon Sep 17 00:00:00 2001
+From: Ingo Franzki <ifranzki@linux.ibm.com>
+Date: Wed, 5 Jan 2022 09:26:26 +0100
+Subject: [PATCH 04/10] RSA: Fix memory leaks in
+ rsa_key_generate_mod_expo()/crt()
+
+Also fix a compiler warning in rsa_key_generate().
+
+Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
+---
+--- a/src/s390_rsa.c
++++ b/src/s390_rsa.c
+@@ -128,7 +128,8 @@
+ 		} while (*public_exponent <= 2 || !(*public_exponent % 2));
+ 	}
+ 
+-	e = BN_bin2bn(public_exponent, sizeof(unsigned long), NULL);
++	e = BN_bin2bn((const unsigned char *)public_exponent,
++		      sizeof(unsigned long), NULL);
+ 	if (e == NULL) {
+ 		goto done;
+ 	}
+@@ -259,6 +260,8 @@
+ #if !OPENSSL_VERSION_PREREQ(3, 0)
+ 	RSA_free(rsa);
+ #else
++	BN_free(n);
++	BN_free(d);
+ 	EVP_PKEY_free(pkey);
+ #endif
+ 
+@@ -410,6 +413,12 @@
+ #if !OPENSSL_VERSION_PREREQ(3, 0)
+ 	RSA_free(rsa);
+ #else
++	BN_free(n);
++	BN_free(p);
++	BN_free(q);
++	BN_free(dmp1);
++	BN_free(dmq1);
++	BN_free(iqmp);
+ 	EVP_PKEY_free(pkey);
+ #endif
+ 
diff -Nru libica-3.9.0/debian/patches/7e6e303e6aef019047eb6dfcdedbfe7da2a88526.patch libica-4.0.0/debian/patches/7e6e303e6aef019047eb6dfcdedbfe7da2a88526.patch
--- libica-3.9.0/debian/patches/7e6e303e6aef019047eb6dfcdedbfe7da2a88526.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/7e6e303e6aef019047eb6dfcdedbfe7da2a88526.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,57 @@
+From 7e6e303e6aef019047eb6dfcdedbfe7da2a88526 Mon Sep 17 00:00:00 2001
+From: Joerg Schmidbauer <jschmidb@de.ibm.com>
+Date: Tue, 11 Jan 2022 16:04:15 +0100
+Subject: [PATCH 06/10] Compute HMAC from installed library
+
+The HMAC hash was computed from the libica in the build tree, but
+the runtime check is run against the installed libica and those 2
+files may be different. E.g. if the runtime one has debuginfo stripped
+(and placed into a separate file), the hashes are different.
+This commit introduces a new make target: fipsinstall, which creates
+the HMAC files in the install directory.
+
+Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
+---
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -17,11 +17,8 @@
+ 	cd ${top_builddir}/src && gcov .libs/*.gcda
+ 
+ if ICA_FIPS
+-install-data-hook:
+-	$(INSTALL) -m 0444 ${top_builddir}/src/.libs/.libica.so.$(VERSION).hmac $(DESTDIR)$(libdir)
+-	cd $(DESTDIR)$(libdir) && ln -sf .libica.so.$(VERSION).hmac .libica.so.$(MAJOR).hmac
+-	$(INSTALL) -m 0444 ${top_builddir}/src/.libs/.libica-cex.so.$(VERSION).hmac $(DESTDIR)$(libdir)
+-	cd $(DESTDIR)$(libdir) && ln -sf .libica-cex.so.$(VERSION).hmac .libica-cex.so.$(MAJOR).hmac
++fipsinstall:
++	 $(AM_V_GEN)$(MAKE) -C src fipsinstall
+ if ICA_OPENSSL3
+ 	test -f $(DESTDIR)$(sysconfdir)/libica || $(MKDIR_P) $(DESTDIR)$(sysconfdir)/libica
+ 	test -f $(DESTDIR)$(sysconfdir)/libica/openssl3-fips.cnf || $(INSTALL) -m 644 ${top_builddir}/src/openssl3-fips.cnf $(DESTDIR)$(sysconfdir)/libica/openssl3-fips.cnf || true
+@@ -38,3 +35,5 @@
+ endif
+ endif
+ 
++.PHONY: fipsinstall
++
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -47,6 +47,12 @@
+ 	./mp.pl mp.S
+ 
+ if ICA_FIPS
++fipsinstall:
++	$(AM_V_GEN) openssl dgst -sha256 -mac hmac -macopt hexkey:00000000 $(DESTDIR)$(libdir)/libica.so.$(VERSION1) | sed -e 's/^.* //' > $(DESTDIR)$(libdir)/.libica.so.$(VERSION1).hmac
++	$(AM_V_GEN) cd $(DESTDIR)$(libdir) && ln -s .libica.so.$(VERSION1).hmac .libica.so.$(MAJOR).hmac
++	$(AM_V_GEN) openssl dgst -sha256 -mac hmac -macopt hexkey:00000000 $(DESTDIR)$(libdir)/libica-cex.so.$(VERSION1) | sed -e 's/^.* //' > $(DESTDIR)$(libdir)/.libica-cex.so.$(VERSION1).hmac
++	$(AM_V_GEN) cd $(DESTDIR)$(libdir) && ln -s .libica-cex.so.$(VERSION1).hmac .libica-cex.so.$(MAJOR).hmac
++
+ hmac-file-lnk: hmac-file
+ 	$(AM_V_GEN) cd ${top_builddir}/src/.libs && ln -sf .libica.so.$(VERSION1).hmac .libica.so.$(MAJOR).hmac
+ 	$(AM_V_GEN) cd ${top_builddir}/src/.libs && ln -sf .libica-cex.so.$(VERSION1).hmac .libica-cex.so.$(MAJOR).hmac
+@@ -110,4 +116,4 @@
+ 		    include/rng.h ../test/testcase.h
+ endif
+ 
+-.PHONY: hmac-file hmac-file-lnk
++.PHONY: hmac-file hmac-file-lnk fipsinstall
diff -Nru libica-3.9.0/debian/patches/977fe8ac713f9ff3101ce9882e23d0183fb46ec8.patch libica-4.0.0/debian/patches/977fe8ac713f9ff3101ce9882e23d0183fb46ec8.patch
--- libica-3.9.0/debian/patches/977fe8ac713f9ff3101ce9882e23d0183fb46ec8.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/977fe8ac713f9ff3101ce9882e23d0183fb46ec8.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,99 @@
+From 977fe8ac713f9ff3101ce9882e23d0183fb46ec8 Mon Sep 17 00:00:00 2001
+From: Joerg Schmidbauer <jschmidb@de.ibm.com>
+Date: Wed, 15 Dec 2021 16:29:57 +0100
+Subject: [PATCH 01/10] RSA: limit RSA key length to 4096
+
+CEX adapters support RSA up to 4096 bits. Although RSA key generation
+in libica is done via openssl, and therefore even greater key lengths
+would be supported, such keys could not be processed on CEX adapters
+afterwards. With the removal of sw fallbacks this is now a hard
+restriction.
+
+Signed-off-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
+---
+--- a/include/ica_api.h
++++ b/include/ica_api.h
+@@ -1291,6 +1291,7 @@
+  *
+  * @return 0 if successful.
+  * EINVAL if at least one invalid parameter is given.
++ * EPERM if modulus bit length is greater than 4096 (CEX adapter restriction).
+  * EFAULT if OpenSSL key generation should fail.
+  */
+ ICA_EXPORT
+@@ -1319,6 +1320,7 @@
+  *
+  * @return 0 if successful.
+  * EINVAL if at least one invalid parameter is given.
++ * EPERM if modulus bit length is greater than 4096 (CEX adapter restriction).
+  * EFAULT if OpenSSL key generation should fail.
+  */
+ ICA_EXPORT
+@@ -1346,6 +1348,7 @@
+  *
+  * @return 0 if successful.
+  * EINVAL if at least one invalid parameter is given.
++ * EPERM if key bit length is greater than 4096 (CEX adapter restriction).
+  * ENOMEM if memory allocation fails.
+  * EIO if the operation fails. This should never happen.
+  */
+@@ -1375,6 +1378,7 @@
+  *
+  * @return 0 if successful.
+  * EINVAL if at least one invalid parameter is given.
++ * EPERM if key bit length is greater than 4096 (CEX adapter restriction).
+  * ENOMEM if memory allocation fails.
+  * EIO if the operation fails. This should never happen.
+  */
+--- a/src/ica_api.c
++++ b/src/ica_api.c
+@@ -52,6 +52,8 @@
+ 
+ #define MAX_VERSION_LENGTH 16
+ 
++#define MAX_RSA_KEY_BITS		4096
++
+ #ifndef NO_SW_FALLBACKS
+ int ica_fallbacks_enabled = 1;
+ #else
+@@ -1071,9 +1073,12 @@
+ 	/* Keys should comply with modulus_bit_length */
+ 	if ((modulus_bit_length + 7) / 8 != public_key->key_length)
+ 		return EINVAL;
+-	/* Minimum length for public exponent is sizeof(unsigned long) */
++	/* Minimum key length is sizeof(unsigned long) */
+ 	if (public_key->key_length < sizeof(unsigned long))
+ 		return EINVAL;
++	/* Max key bit length is 4096 because of CEX adapter restriction */
++	if (modulus_bit_length > MAX_RSA_KEY_BITS)
++		return EPERM;
+ 
+ 	/* OpenSSL takes only exponents of type unsigned long, so we have to
+ 	 * be sure that we give a value of the right size to OpenSSL.
+@@ -1111,6 +1116,8 @@
+ 		return EINVAL;
+ 	if (public_key->key_length < sizeof(unsigned long))
+ 		return EINVAL;
++	if (modulus_bit_length > MAX_RSA_KEY_BITS)
++		return EPERM;
+ 
+ 	num_ignored_bytes = public_key->key_length - sizeof(unsigned long);
+ 	public_exponent = public_key->exponent;
+@@ -1145,6 +1152,8 @@
+ 
+ 	if (rsa_key->key_length < sizeof(unsigned long))
+ 		return EINVAL;
++	if (rsa_key->key_length * 8 > MAX_RSA_KEY_BITS)
++		return EPERM;
+ 
+ 	/* fill driver structure */
+ 	rb.inputdata = (unsigned char *)input_data;
+@@ -1264,6 +1273,8 @@
+ 
+ 	if (rsa_key->key_length < sizeof(unsigned long))
+ 		return EINVAL;
++	if (rsa_key->key_length * 8 > MAX_RSA_KEY_BITS)
++		return EPERM;
+ 
+ 	/* fill driver structure */
+ 	rb.inputdata = (unsigned char *)input_data;
diff -Nru libica-3.9.0/debian/patches/9c6431f49a9fe0d574722954e018b4cba6ab085b.patch libica-4.0.0/debian/patches/9c6431f49a9fe0d574722954e018b4cba6ab085b.patch
--- libica-3.9.0/debian/patches/9c6431f49a9fe0d574722954e018b4cba6ab085b.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/9c6431f49a9fe0d574722954e018b4cba6ab085b.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,20 @@
+From 9c6431f49a9fe0d574722954e018b4cba6ab085b Mon Sep 17 00:00:00 2001
+From: Ingo Franzki <ifranzki@linux.ibm.com>
+Date: Mon, 24 Jan 2022 14:33:57 +0100
+Subject: [PATCH 09/10] FIPS: Calculation of library HMAC may fail
+
+Initialize length variable before calling EVP_DigestSignFinal().
+If hlen is uninitialized it may cause EVP_DigestSignFinal() to fail.
+
+Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
+---
+--- a/src/fips.c
++++ b/src/fips.c
+@@ -333,6 +333,7 @@
+ 		}
+ 	}
+ 
++	hlen = sizeof(rbuf);
+ 	if (EVP_DigestSignFinal(mdctx, rbuf, &hlen) <= 0)
+ 		goto end;
+ 
diff -Nru libica-3.9.0/debian/patches/b41addd200c0938c6c10202da08ad5f7df940e18.patch libica-4.0.0/debian/patches/b41addd200c0938c6c10202da08ad5f7df940e18.patch
--- libica-3.9.0/debian/patches/b41addd200c0938c6c10202da08ad5f7df940e18.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/b41addd200c0938c6c10202da08ad5f7df940e18.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,32 @@
+From b41addd200c0938c6c10202da08ad5f7df940e18 Mon Sep 17 00:00:00 2001
+From: Ingo Franzki <ifranzki@linux.ibm.com>
+Date: Wed, 5 Jan 2022 09:15:58 +0100
+Subject: [PATCH 03/10] ECC: Avoid recursive loop in ec_key_check() with
+ OpenSSL 3.0
+
+Use libica's OpenSSL library context in ec_key_check(), otherwise
+calling EVP_PKEY_fromdata() in build_pkey_from_params() may cause
+a recursive loop, when a provider is used that calls ica_ec_key_init()
+(and thus ec_key_check()) within its key import function.
+
+Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
+---
+--- a/src/s390_ecc.c
++++ b/src/s390_ecc.c
+@@ -2458,6 +2458,8 @@
+ 	BIGNUM *d = NULL, *x = NULL, *y = NULL;
+ 	int privlen, rc = EINVAL;
+ 
++	BEGIN_OPENSSL_LIBCTX(openssl_libctx, rc);
++
+ 	if (!ica_key)
+ 		goto done;
+ 
+@@ -2489,6 +2491,7 @@
+ 	if (privkey)
+ 		EVP_PKEY_free(privkey);
+ 
++	END_OPENSSL_LIBCTX(rc);
+ 	return rc;
+ }
+ 
diff -Nru libica-3.9.0/debian/patches/b49cf457659a4baf382b3828d89823497bb00f6e.patch libica-4.0.0/debian/patches/b49cf457659a4baf382b3828d89823497bb00f6e.patch
--- libica-3.9.0/debian/patches/b49cf457659a4baf382b3828d89823497bb00f6e.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/b49cf457659a4baf382b3828d89823497bb00f6e.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,32 @@
+From b49cf457659a4baf382b3828d89823497bb00f6e Mon Sep 17 00:00:00 2001
+From: Ingo Franzki <ifranzki@linux.ibm.com>
+Date: Thu, 13 Jan 2022 10:42:02 +0100
+Subject: [PATCH 05/10] EC: Handle unsupported EC curve in ica_ec_key_new()
+
+In case of an unsupported curve nid, privlen_from_nid() returns -1.
+The subsequent calloc() will fail with a size of -3 (0xfffffffffffffffd).
+
+Also free the already allocated key in case of an error to avoid a
+memory leak.
+
+Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
+---
+--- a/src/ica_api.c
++++ b/src/ica_api.c
+@@ -1336,9 +1336,15 @@
+ 
+ 	/* allocate clear memory for the 3 key parts */
+ 	len = privlen_from_nid(nid);
++	if (len <= 0) {
++		free(key);
++		return NULL;
++	}
+ 	key->X = calloc(1, 3*len);
+-	if (!key->X)
++	if (!key->X) {
++		free(key);
+ 		return NULL;
++	}
+ 
+ 	key->nid = nid;
+ 	key->Y = key->X + len;
diff -Nru libica-3.9.0/debian/patches/cc44f18383ec6dc01a05abd6c25a1dec8efe84cb.patch libica-4.0.0/debian/patches/cc44f18383ec6dc01a05abd6c25a1dec8efe84cb.patch
--- libica-3.9.0/debian/patches/cc44f18383ec6dc01a05abd6c25a1dec8efe84cb.patch	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/cc44f18383ec6dc01a05abd6c25a1dec8efe84cb.patch	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,107 @@
+From cc44f18383ec6dc01a05abd6c25a1dec8efe84cb Mon Sep 17 00:00:00 2001
+From: Ingo Franzki <ifranzki@linux.ibm.com>
+Date: Mon, 24 Jan 2022 10:32:47 +0100
+Subject: [PATCH 08/10] Fix memory leaks in test programs
+
+When configured with --enable-sanitizer some tests fail because
+the address sanitizer reports memory leaks.
+
+Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
+---
+--- a/test/ecdh_test.c
++++ b/test/ecdh_test.c
+@@ -339,6 +339,8 @@
+ 
+ 		rc = ica_ec_key_init(ecdh_kats[i].xa, ecdh_kats[i].ya, ecdh_kats[i].da, eckey_A);
+ 		if (rc != 0) {
++			ica_ec_key_free(eckey_A);
++			eckey_A = NULL;
+ 			if (rc == EPERM) {
+ 				V_(printf("Curve %d not supported on this system, skipping ...\n", ecdh_kats[i].nid));
+ 				continue;
+@@ -350,11 +352,18 @@
+ 		}
+ 
+ 		eckey_B = ica_ec_key_new(ecdh_kats[i].nid, &privlen);
+-		if (!eckey_B)
++		if (!eckey_B) {
++			ica_ec_key_free(eckey_A);
++			eckey_A = NULL;
+ 			continue;
++		}
+ 
+ 		rc = ica_ec_key_init(ecdh_kats[i].xb, ecdh_kats[i].yb, ecdh_kats[i].db, eckey_B);
+ 		if (rc != 0) {
++			ica_ec_key_free(eckey_B);
++			eckey_B = NULL;
++			ica_ec_key_free(eckey_A);
++			eckey_A = NULL;
+ 			if (rc == EPERM) {
+ 				V_(printf("Curve %d not supported on this system, skipping ...\n", ecdh_kats[i].nid));
+ 				continue;
+@@ -415,7 +424,9 @@
+ 			errors++;
+ 
+ 		ica_ec_key_free(eckey_A);
++		eckey_A = NULL;
+ 		ica_ec_key_free(eckey_B);
++		eckey_B = NULL;
+ 		unset_env_icapath();
+ 	}
+ 
+--- a/test/ecdsa_test.c
++++ b/test/ecdsa_test.c
+@@ -225,6 +225,8 @@
+ 
+ 		rc = ica_ec_key_init(ecdsa_kats[i].x, ecdsa_kats[i].y, ecdsa_kats[i].d, eckey);
+ 		if (rc != 0) {
++			ica_ec_key_free(eckey);
++			eckey = NULL;
+ 			if (rc == EPERM) {
+ 				V_(printf("Curve %d not supported on this system, skipping ...\n", ecdsa_kats[i].nid));
+ 				continue;
+@@ -274,6 +276,7 @@
+ 			errors++;
+ 
+ 		ica_ec_key_free(eckey);
++		eckey = NULL;
+ 		unset_env_icapath();
+ 	}
+ 
+--- a/test/ec_keygen_test.c
++++ b/test/ec_keygen_test.c
+@@ -115,6 +115,8 @@
+ 
+ 			rc = ica_ec_key_generate(adapter_handle, eckey);
+ 			if (rc) {
++				ica_ec_key_free(eckey);
++				eckey = NULL;
+ 				if (rc == EPERM) {
+ 					V_(printf("Curve %d not supported on this system, skipping ...\n", eckeygen_tests[i].nid));
+ 					continue;
+@@ -156,12 +158,14 @@
+ 					}
+ 				}
+ 			}
++
++			ica_ec_key_free(eckey);
++			eckey = NULL;
+ 		}
+ 
+ 		if (test_failed)
+ 			errors++;
+ 
+-		ica_ec_key_free(eckey);
+ 		unset_env_icapath();
+ 	}
+ 
+--- a/test/icastats_test.c.in
++++ b/test/icastats_test.c.in
+@@ -186,6 +186,7 @@
+ 			}
+ 			if((c = fgetc(file)) == '1'){
+ 				fclose(file);
++				closedir(sysDir);
+ 				return 1;
+ 			}
+ 			fclose(file);
diff -Nru libica-3.9.0/debian/patches/series libica-4.0.0/debian/patches/series
--- libica-3.9.0/debian/patches/series	1970-01-01 01:00:00.000000000 +0100
+++ libica-4.0.0/debian/patches/series	2022-01-31 13:19:06.000000000 +0100
@@ -0,0 +1,10 @@
+977fe8ac713f9ff3101ce9882e23d0183fb46ec8.patch
+553977ef505b43c7d17056369ed518a971d43d68.patch
+b41addd200c0938c6c10202da08ad5f7df940e18.patch
+6031ec80a5ada52609822fed4a6bd2cccafe5563.patch
+b49cf457659a4baf382b3828d89823497bb00f6e.patch
+7e6e303e6aef019047eb6dfcdedbfe7da2a88526.patch
+28fa931bed9e6847137829952a3e7cc6091bd071.patch
+cc44f18383ec6dc01a05abd6c25a1dec8efe84cb.patch
+9c6431f49a9fe0d574722954e018b4cba6ab085b.patch
+5aa9366c236a6d17570403ef81c65e4f5f91a8af.patch
diff -Nru libica-3.9.0/doc/icastats.1 libica-4.0.0/doc/icastats.1
--- libica-3.9.0/doc/icastats.1	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/doc/icastats.1	2021-12-06 12:01:54.000000000 +0100
@@ -12,8 +12,8 @@
 .SH SYNOPSIS
 .B icastats
 [-v | --version] [-h | --help] [--reset-all | -R] [--reset | -r]
-[--delete-all |-D] [--delete | -d] [--all | -A] [--summary | -S] [[-U |
---user] <username>]
+[--delete-all |-D] [--delete | -d] [--all | -A] [--summary | -S] [-U |
+--user <username>] [--key-sizes | -k] [--json | -j]
 .SH DESCRIPTION
 .B icastats
 displays statistic data about the usage of cryptographic functions provided by
@@ -50,10 +50,16 @@
       AES GCM |       0             0 |       0            0
 .fi
 .P
+In addition to the default output format, a machine readable JSON output format
+can be selected using the --json | -j option.
+.P
 For each cryptographic function the table shows the number of invocations
 where hardware support was involved or the libica fall back implementation
 in software was used. For the ciphering methods the invocation counter is
 further divided into encrypt and decrypt operation counter values.
+For some cryptographic functions (AES, RSA, ECC) counters exist per key size.
+Use the --key-sizes | -k option to display those counters as well. For the JSON
+output format, only the per key size counters are reported.
 .P
 All the counter values are stored and maintained in one shared memory page
 for each user. This memory area is created automatically with the first run
@@ -103,6 +109,10 @@
 values (only root user)
 .IP "-U <username> or --user <username>"
 show statistic values from the given user (only root user)
+.IP "-k or --key-sizes"
+show libica statistic data per key size
+.IP "-j or --json"
+output the statistics in JSON format
 .SH FILES
 .nf
 /shm/dev/icastats_<userid>
diff -Nru libica-3.9.0/include/ica_api.h libica-4.0.0/include/ica_api.h
--- libica-3.9.0/include/ica_api.h	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/include/ica_api.h	2021-12-06 12:01:54.000000000 +0100
@@ -597,7 +597,7 @@
 ICA_EXPORT
 unsigned int ica_sha1(unsigned int message_part,
 		      unsigned int input_length,
-		      unsigned char *input_data,
+		      const unsigned char *input_data,
 		      sha_context_t *sha_context,
 		      unsigned char *output_data);
 
@@ -643,7 +643,7 @@
 ICA_EXPORT
 unsigned int ica_sha224(unsigned int message_part,
 			unsigned int input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha256_context_t *sha256_context,
 			unsigned char *output_data);
 
@@ -687,7 +687,7 @@
 ICA_EXPORT
 unsigned int ica_sha256(unsigned int message_part,
 			unsigned int input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha256_context_t *sha256_context,
 			unsigned char *output_data);
 
@@ -733,7 +733,7 @@
 ICA_EXPORT
 unsigned int ica_sha384(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha512_context_t *sha512_context,
 			unsigned char *output_data);
 
@@ -777,7 +777,7 @@
 ICA_EXPORT
 unsigned int ica_sha512(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha512_context_t *sha512_context,
 			unsigned char *output_data);
 
@@ -821,7 +821,7 @@
 ICA_EXPORT
 unsigned int ica_sha512_224(unsigned int message_part,
 			    uint64_t input_length,
-			    unsigned char *input_data,
+			    const unsigned char *input_data,
 			    sha512_context_t *sha512_context,
 			    unsigned char *output_data);
 
@@ -864,42 +864,42 @@
  */ICA_EXPORT
 unsigned int ica_sha512_256(unsigned int message_part,
 			    uint64_t input_length,
-			    unsigned char *input_data,
+			    const unsigned char *input_data,
 			    sha512_context_t *sha512_context,
 			    unsigned char *output_data);
 
 ICA_EXPORT
 unsigned int ica_sha3_224(unsigned int message_part,
 			unsigned int input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha3_224_context_t *sha3_224_context,
 			unsigned char *output_data);
 
 ICA_EXPORT
 unsigned int ica_sha3_256(unsigned int message_part,
 			unsigned int input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha3_256_context_t *sha3_256_context,
 			unsigned char *output_data);
 
 ICA_EXPORT
 unsigned int ica_sha3_384(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha3_384_context_t *sha3_384_context,
 			unsigned char *output_data);
 
 ICA_EXPORT
 unsigned int ica_sha3_512(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha3_512_context_t *sha3_512_context,
 			unsigned char *output_data);
 
 ICA_EXPORT
 unsigned int ica_shake_128(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			shake_128_context_t *shake_128_context,
 			unsigned char *output_data,
 			unsigned int output_length);
@@ -907,7 +907,7 @@
 ICA_EXPORT
 unsigned int ica_shake_256(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			shake_256_context_t *shake_256_context,
 			unsigned char *output_data,
 			unsigned int output_length);
@@ -1184,8 +1184,8 @@
 int ica_ed25519_key_set(ICA_ED25519_CTX *ctx, const unsigned char priv[32],
 			const unsigned char pub[32]);
 ICA_EXPORT
-int ica_ed448_key_set(ICA_ED448_CTX *ctx, const unsigned char priv[56],
-		      const unsigned char pub[56]);
+int ica_ed448_key_set(ICA_ED448_CTX *ctx, const unsigned char priv[57],
+		      const unsigned char pub[57]);
 
 /*
  * Copy the private and public key from the context. MSA9 required.
@@ -1351,7 +1351,7 @@
  */
 ICA_EXPORT
 unsigned int ica_rsa_mod_expo(ica_adapter_handle_t adapter_handle,
-			      unsigned char *input_data,
+			      const unsigned char *input_data,
 			      ica_rsa_key_mod_expo_t *rsa_key,
 			      unsigned char *output_data);
 
@@ -1380,7 +1380,7 @@
  */
 ICA_EXPORT
 unsigned int ica_rsa_crt(ica_adapter_handle_t adapter_handle,
-			 unsigned char *input_data,
+			 const unsigned char *input_data,
 			 ica_rsa_key_crt_t *rsa_key,
 			 unsigned char *output_data);
 
@@ -1400,227 +1400,6 @@
 unsigned int ica_rsa_crt_key_check(ica_rsa_key_crt_t *rsa_key);
 
 /**
- * @deprecated, use ica_des_ecb() or ica_des_cbc() instead.
- *
- * Encrypt data using a single length DES key.
- * @param mode Specifies the operational mode and must be:
- *	       MODE_ECB - Use Electronic Code Book mode
- *	       MODE_CBC - Use Cipher Block Chaining mode
- * @param data_length
- * Specifies the byte length of the input data. It has to be a multiple of the
- * cipher block which has a size of 8 byte.
- * @param input_data
- * Pointer to the input data data to be encrypted. Must be a multiple of the
- * cipher to use hw acceleration.
- * @param iv
- * Pointer to a valid 8 byte initialization vector when using CBC mode.
- * @param des_key
- * Pointer to a single length DES key.
- * @param output_data
- * Pointer to the buffer to contain the resulting encrypted data. Must be a
- * multiple of the cipher block and at least as big as the buffer for
- * input_data.
- *
- * @return 0 if successful.
- * EINVAL if at least one invalid parameter is given.
- * EIO if the operation fails. This should never happen.
- */
-/* XXX next major: remove */
-ICA_EXPORT ICA_DEPRECATED
-unsigned int ica_des_encrypt(unsigned int mode,
-			     unsigned int data_length,
-			     unsigned char *input_data,
-			     ica_des_vector_t *iv,
-			     ica_des_key_single_t *des_key,
-			     unsigned char *output_data);
-
-/**
- * @deprecated, use ica_des_ecb() or ica_des_cbc() instead.
- *
- * Decrypt data using a single length DES key.
- * @param mode
- * Specifies the operational mode and must be:
- * 	MODE_ECB - Use Electronic Code Book mode
- *	MODE_CBC - Use Cipher Block Chaining mode
- * @param data_length
- * Specifies the byte length of the input data. It has to be a multiple of the
- * cipher block which has a size of 8 byte.
- * @param input_data
- * Pointer to the input data data to be decrypted. Must be a multiple of the
- * cipher to use hw acceleration.
- * @param iv
- * Pointer to a valid 8 byte initialization vector when using CBC mode.
- * @param des_key
- * Pointer to a single length DES key.
- * @param output_data
- * Pointer to the buffer to contain the resulting decrypted data. Must be a
- * multiple of the cipher block and at least as big as the buffer for
- * input_data.
- *
- * @return 0 if successful.
- * EINVAL if at least one invalid parameter is given.
- * EIO if the operation fails. This should never happen.
- */
-/* XXX next major: remove */
-ICA_EXPORT ICA_DEPRECATED
-unsigned int ica_des_decrypt(unsigned int mode,
-			     unsigned int data_length,
-			     unsigned char *input_data,
-			     ica_des_vector_t *iv,
-			     ica_des_key_single_t *des_key,
-			     unsigned char *output_data);
-
-/**
- * @deprecated, use ica_3des_ecb() or ica_3des_cbc() instead.
- *
- * Encrypt data using a triple length DES key.
- * @param mode
- * Specifies the operational mode and must be:
- * 	MODE_ECB - Use Electronic Code Book mode
- *	MODE_CBC - Use Cipher Block Chaining mode
- * @param data_length
- * Specifies the byte length of the input data. It has to be a multiple of the
- * cipher block which has a size of 8 byte.
- * @param input_data
- * Pointer to the input data data to be encrypted. Must be a multiple of the
- * cipher block to use hw acceleration.
- * @param iv
- * Pointer to a valid 8 byte initialization vector when using CBC mode.
- * @param des_key
- * Pointer to a triple length DES key.
- * @param output_data
- * Pointer to the buffer to contain the resulting encrypted data. Must be a
- * multiple of the cipher block and at least as big as the buffer for
- * input_data.
- *
- * @return 0 if successful.
- * EINVAL if at least one invalid parameter is given.
- * EIO if the operation fails. This should never happen.
- */
-/* XXX next major: remove */
-ICA_EXPORT ICA_DEPRECATED
-unsigned int ica_3des_encrypt(unsigned int mode,
-			      unsigned int data_length,
-			      unsigned char *input_data,
-			      ica_des_vector_t *iv,
-			      ica_des_key_triple_t *des_key,
-			      unsigned char *output_data);
-
-/**
- * @deprecated, use ica_3des_ecb() or ica_3des_cbc() instead.
- *
- * Decrypt data using a triple length DES key.
- * @param mode
- * Specifies the operational mode and must be:
- * 	MODE_ECB - Use Electronic Code Book mode
- *	MODE_CBC - Use Cipher Block Chaining mode
- * @param data_length
- * Specifies the byte length of the input data. It has to be a multiple of the
- * cipher block which has a size of 8 byte.
- * @param input_data
- * Pointer to the input data data to be decrypted. Must be a multiple of the
- * cipher block to use hw acceleration.
- * @param iv
- * Pointer to a valid 8 byte initialization vector when using CBC mode.
- * @param des_key
- * Pointer to a triple length DES key.
- * @param output_data
- * Pointer to the buffer to contain the resulting decrypted data. Must be a
- * multiple of the cipher block and at least as big as the buffer for
- * input_data.
- *
- * @return 0 if successful.
- * EINVAL if at least one invalid parameter is given.
- * EIO if the operation fails. This should never happen.
- */
-/* XXX next major: remove */
-ICA_EXPORT ICA_DEPRECATED
-unsigned int ica_3des_decrypt(unsigned int mode,
-			      unsigned int data_length,
-			      unsigned char *input_data,
-			      ica_des_vector_t *iv,
-			      ica_des_key_triple_t *des_key,
-			      unsigned char *output_data);
-
-/**
- * @deprecated, use ica_aes_ecb() or ica_aes_cbc() instead.
- *
- * Encrypt data using AES (key_length is 16, 24, or 32)
- * @param mode
- * Specifies the operational mode and must be:
- * 	MODE_ECB - Use Electronic Code Book mode
- *	MODE_CBC - Use Cipher Block Chaining mode
- * @param data_length
- * Specifies the byte length of the input data. Input data length has to be
- * a multiple of the AES block length, which is 16 bytes.
- * @param input_data
- * Pointer to the input data data to be encrypted. Must be a multiple of the
- * cipher block to use hw acceleration.
- * @param iv
- * Pointer to a valid 16 byte initialization vector when using CBC mode.
- * @param key_length
- * Length of the AES key being used.
- * @param aes_key
- * Pointer to an AES key.
- * @param output_data
- * Pointer to the buffer to contain the resulting encrypted data. Must be a
- * multiple of the cipher block and at least as big as the buffer for
- * input_data.
- *
- * @return 0 if successful.
- * EINVAL if at least one invalid parameter is given.
- * EIO if the operation fails. This should never happen.
- */
-/* XXX next major: remove */
-ICA_EXPORT ICA_DEPRECATED
-unsigned int ica_aes_encrypt(unsigned int mode,
-			     unsigned int data_length,
-			     unsigned char *input_data,
-			     ica_aes_vector_t *iv,
-			     unsigned int key_length,
-			     unsigned char *aes_key,
-			     unsigned char *output_data);
-
-/**
- * @deprecated, use ica_aes_ecb() or ica_aes_cbc() instead.
- *
- * Decrypt data using AES (key_length is 16, 24, or 32)
- * @param mode
- * Specifies the operational mode and must be:
- * 	MODE_ECB - Use Electronic Code Book mode
- *	MODE_CBC - Use Cipher Block Chaining mode
- * @param data_length
- * Specifies the byte length of the input data. Input data length has to be
- * a multiple of the AES block length, which is 16 bytes.
- * @param input_data
- * Pointer to the input data to be decrypted. Must be a multiple of the
- * cipher block to use hw acceleration.
- * @param iv
- * Pointer to a valid 16 byte initialization vector when using CBC mode.
- * @param key_length
- * Length of the AES key being used.
- * @param aes_key
- * Pointer to an AES key.
- * @param output_data
- * Pointer to the buffer to contain the resulting decrypted data. Must be a
- * multiple of the cipher block and at least as big as the buffer for
- * input_data.
- *
- * @return 0 if successful.
- * EINVAL if at least one invalid parameter is given.
- * EIO if the operation fails. This should never happen.
- */
-/* XXX next major: remove */
-ICA_EXPORT ICA_DEPRECATED
-unsigned int ica_aes_decrypt(unsigned int mode,
-			     unsigned int data_length,
-			     unsigned char *input_data,
-			     ica_aes_vector_t *iv,
-			     unsigned int key_length,
-			     unsigned char *aes_key,
-			     unsigned char *output_data);
-
-/**
  * Encrypt or decrypt data with an DES key using Electronic Cook Book (ECB)
  * mode as described in NIST Special Publication 800-38A Chapter 6.1.
  *
@@ -3596,15 +3375,6 @@
 ICA_EXPORT
 unsigned int ica_get_version(libica_version_info *version_info);
 
-/* XXX next major: dont export, move to s390_crypto.h */
-ICA_EXPORT ICA_DEPRECATED
-int s390_initialize_functionlist(void);
-
-/* XXX next major: dont export, move to s390_crypto.h */
-ICA_EXPORT ICA_DEPRECATED
-int s390_get_functionlist(libica_func_list_element *pmech_list,
-			  unsigned int *pmech_list_len);
-
 /**
  * Function that returns a list of crypto mechanisms supported by libica.
  * @param pmech_list
@@ -3868,11 +3638,6 @@
 ICA_EXPORT
 int ica_mp_sqr512(uint64_t r[16], const uint64_t a[8]);
 
-#ifdef ICA_FIPS
-/*
- * Additional FIPS interfaces are available for built-in FIPS mode.
- */
-
 /*
  * FIPS status output interface.
  *
@@ -3882,6 +3647,11 @@
 ICA_EXPORT
 int ica_fips_status(void);
 
+#ifdef ICA_FIPS
+/*
+ * Additional FIPS interfaces are available for built-in FIPS mode.
+ */
+
 /*
  * FIPS powerups tests.
  *
diff -Nru libica-3.9.0/libica.map libica-4.0.0/libica.map
--- libica-3.9.0/libica.map	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/libica.map	2021-12-06 12:01:54.000000000 +0100
@@ -3,15 +3,11 @@
 	_fini;
 	_init;
 
-	s390_initialize_functionlist;
-	s390_get_functionlist;
 	ica_get_functionlist;
 	ica_get_version;
 
 	ica_random_number_generate;
 
-	ica_des_encrypt;
-	ica_des_decrypt;
 	ica_des_ecb;
 	ica_des_cbc;
 	ica_des_cbc_cs;
@@ -23,8 +19,6 @@
 	ica_des_cmac_intermediate;
 	ica_des_cmac_last;
 
-	ica_3des_encrypt;
-	ica_3des_decrypt;
 	ica_3des_ecb;
 	ica_3des_cbc;
 	ica_3des_cbc_cs;
@@ -36,8 +30,6 @@
 	ica_3des_cmac_intermediate;
 	ica_3des_cmac_last;
 
-	ica_aes_encrypt;
-	ica_aes_decrypt;
 	ica_aes_ecb;
 	ica_aes_cbc;
 	ica_aes_cbc_cs;
diff -Nru libica-3.9.0/libica.spec libica-4.0.0/libica.spec
--- libica-3.9.0/libica.spec	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/libica.spec	2021-12-06 12:01:54.000000000 +0100
@@ -1,5 +1,5 @@
 Name:          libica
-Version:       3.9.0
+Version:       4.0.0
 Release:       1%{?dist}
 Summary:       Interface library to the ICA device driver
 
diff -Nru libica-3.9.0/src/fips.c libica-4.0.0/src/fips.c
--- libica-3.9.0/src/fips.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/fips.c	2021-12-06 12:01:54.000000000 +0100
@@ -59,6 +59,7 @@
 #define HMAC_SUFFIX ".hmac"
 #define READ_BUFFER_LENGTH 16384
 
+#ifndef ICA_INTERNAL_TEST
 /*
  * The hard-coded HMAC key to be optionally provided for the library
  * integrity test. The recommended key size for HMAC-SHA256 is 64 bytes.
@@ -69,6 +70,8 @@
 	"0000000000000000000000000000000000000000000000000000000000000000"
 	"0000000000000000000000000000000000000000000000000000000000000000";
 
+#endif /* ICA_INTERNAL_TEST */
+
 int fips;
 
 #define LIBICA_FIPS_CONFIG		LIBICA_CONFDIR "/libica/openssl3-fips.cnf"
@@ -254,9 +257,22 @@
 
 		fips |= ICA_FIPS_MODE;
 #endif
+	} else {
+		/* kernel fips flag == 0, load default provider in case we are
+		 * running with openssl 3.0 */
+#if OPENSSL_VERSION_PREREQ(3, 0)
+		openssl_provider = OSSL_PROVIDER_load(openssl_libctx, "default");
+		if (openssl_provider == NULL) {
+			syslog(LOG_ERR, "Libica: failed to load default provider\n");
+			fips |= ICA_FIPS_INTEGRITY;
+			return;
+		}
+#endif
 	}
 }
 
+#ifndef ICA_INTERNAL_TEST
+
 static char *make_hmac_path(const char *origpath)
 {
 	char *path;
@@ -469,6 +485,7 @@
 
 	syslog(LOG_INFO, msg3);
 }
+#endif /* ICA_INTERNAL_TEST */
 
 void
 fips_powerup_tests(void)
@@ -1288,10 +1305,33 @@
 	const struct rsa_tv *tv;
 	size_t i, keylen, crtparamlen;
 	unsigned char *out;
+	libica_func_list_element* libica_func_list;
+	unsigned int count;
 
 	if (ica_open_adapter(&ah))
 		return 1;
 
+	if (ica_get_functionlist(NULL, &count) != 0)
+		goto _err_;
+
+	libica_func_list = malloc(sizeof(libica_func_list_element) * count);
+	if (!libica_func_list)
+		goto _err_;
+
+	if (ica_get_functionlist(libica_func_list, &count) != 0)
+		goto _err_;
+
+	for (i = 0; i < count; i++) {
+		if (libica_func_list[i].mech_mode_id == RSA_CRT &&
+			libica_func_list[i].flags == 0) {
+			/* RSA_CRT, and probably also RSA_ME, not available, skip test.
+			 * Looks like we don't have cards nor sw fallbacks. */
+			free(libica_func_list);
+			ica_close_adapter(ah);
+			return 0;
+		}
+	}
+
 	for (i = 0; i < RSA_TV_LEN; i++) {
 		tv = &RSA_TV[i];
 
@@ -1340,10 +1380,12 @@
 		free(privkey.dq);
 		free(privkey.qInverse);
 	}
+	free(libica_func_list);
 	ica_close_adapter(ah);
 	return 0;
 
 _err_:
+	free(libica_func_list);
 	ica_close_adapter(ah);
 	free(out);
 	free(pubkey.exponent);
diff -Nru libica-3.9.0/src/ica_api.c libica-4.0.0/src/ica_api.c
--- libica-3.9.0/src/ica_api.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/ica_api.c	2021-12-06 12:01:54.000000000 +0100
@@ -394,7 +394,7 @@
 
 unsigned int ica_sha1(unsigned int message_part,
 		      unsigned int input_length,
-		      unsigned char *input_data,
+		      const unsigned char *input_data,
 		      sha_context_t *sha_context,
 		      unsigned char *output_data)
 {
@@ -449,7 +449,7 @@
 
 unsigned int ica_sha224(unsigned int message_part,
 			unsigned int input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha256_context_t *sha256_context,
 			unsigned char *output_data)
 {
@@ -496,7 +496,7 @@
 
 unsigned int ica_sha256(unsigned int message_part,
 			unsigned int input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha256_context_t *sha256_context,
 			unsigned char *output_data)
 {
@@ -543,7 +543,7 @@
 
 unsigned int ica_sha384(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha512_context_t *sha512_context,
 			unsigned char *output_data)
 {
@@ -591,7 +591,7 @@
 
 unsigned int ica_sha512(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha512_context_t *sha512_context,
 			unsigned char *output_data)
 {
@@ -639,7 +639,7 @@
 
 unsigned int ica_sha512_224(unsigned int message_part,
 			    uint64_t input_length,
-			    unsigned char *input_data,
+			    const unsigned char *input_data,
 			    sha512_context_t *sha512_context,
 			    unsigned char *output_data)
 {
@@ -687,7 +687,7 @@
 
 unsigned int ica_sha512_256(unsigned int message_part,
 			    uint64_t input_length,
-			    unsigned char *input_data,
+			    const unsigned char *input_data,
 			    sha512_context_t *sha512_context,
 			    unsigned char *output_data)
 {
@@ -735,7 +735,7 @@
 
 unsigned int ica_sha3_224(unsigned int message_part,
 			unsigned int input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha3_224_context_t *sha3_224_context,
 			unsigned char *output_data)
 {
@@ -782,7 +782,7 @@
 
 unsigned int ica_sha3_256(unsigned int message_part,
 			unsigned int input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha3_256_context_t *sha3_256_context,
 			unsigned char *output_data)
 {
@@ -829,7 +829,7 @@
 
 unsigned int ica_sha3_384(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha3_384_context_t *sha3_384_context,
 			unsigned char *output_data)
 {
@@ -877,7 +877,7 @@
 
 unsigned int ica_sha3_512(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			sha3_512_context_t *sha3_512_context,
 			unsigned char *output_data)
 {
@@ -925,7 +925,7 @@
 
 unsigned int ica_shake_128(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			shake_128_context_t *shake_128_context,
 			unsigned char *output_data, unsigned int output_length)
 {
@@ -980,7 +980,7 @@
 
 unsigned int ica_shake_256(unsigned int message_part,
 			uint64_t input_length,
-			unsigned char *input_data,
+			const unsigned char *input_data,
 			shake_256_context_t *shake_256_context,
 			unsigned char *output_data, unsigned int output_length)
 {
@@ -1127,7 +1127,7 @@
 }
 
 unsigned int ica_rsa_mod_expo(ica_adapter_handle_t adapter_handle,
-			      unsigned char *input_data,
+			      const unsigned char *input_data,
 			      ica_rsa_key_mod_expo_t *rsa_key,
 			      unsigned char *output_data)
 {
@@ -1147,12 +1147,12 @@
 		return EINVAL;
 
 	/* fill driver structure */
-	rb.inputdata = (char *)input_data;
+	rb.inputdata = (unsigned char *)input_data;
 	rb.inputdatalength = rsa_key->key_length;
-	rb.outputdata = (char *)output_data;
+	rb.outputdata = output_data;
 	rb.outputdatalength = rsa_key->key_length;
-	rb.b_key = (char *)rsa_key->exponent;
-	rb.n_modulus = (char *)rsa_key->modulus;
+	rb.b_key = rsa_key->exponent;
+	rb.n_modulus = rsa_key->modulus;
 
 	hardware = ALGO_SW;
 	if (adapter_handle == DRIVER_NOT_LOADED)
@@ -1171,7 +1171,9 @@
 				rsa_mod_expo_sw(&rb) : ENODEV;
 	}
 	if (rc == 0)
-		stats_increment(ICA_STATS_RSA_ME, hardware, ENCRYPT);
+		stats_increment(ICA_STATS_RSA_ME_512 +
+				rsa_keysize_stats_ofs(rsa_key->key_length),
+				hardware, ENCRYPT);
 
 	OPENSSL_cleanse(&rb, sizeof(rb));
 
@@ -1224,8 +1226,11 @@
 		/* qInv = (1/q) mod p */
 		BN_mod_inverse(bn_invq, bn_q, bn_p, ctx);
 		memset(tmp_buf, 0, rsa_key->key_length/2);
-		BN_bn2bin(bn_invq, tmp_buf);
-
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+		BN_bn2bin(bn_invq, tmp_buf + rsa_key->key_length/2 - BN_num_bytes(bn_invq));
+#else
+		BN_bn2binpad(bn_invq, tmp_buf, rsa_key->key_length/2);
+#endif
 		memcpy(rsa_key->qInverse + 8, tmp_buf, rsa_key->key_length/2);
 
 		free(tmp_buf);
@@ -1241,7 +1246,7 @@
 }
 
 unsigned int ica_rsa_crt(ica_adapter_handle_t adapter_handle,
-			 unsigned char *input_data,
+			 const unsigned char *input_data,
 			 ica_rsa_key_crt_t *rsa_key,
 			 unsigned char *output_data)
 {
@@ -1261,18 +1266,18 @@
 		return EINVAL;
 
 	/* fill driver structure */
-	rb.inputdata = (char *)input_data;
+	rb.inputdata = (unsigned char *)input_data;
 	rb.inputdatalength = rsa_key->key_length;
-	rb.outputdata = (char *)output_data;
+	rb.outputdata = output_data;
 	rb.outputdatalength = rsa_key->key_length;
 
 	ica_rsa_crt_key_check(rsa_key);
 
-	rb.np_prime = (char *)rsa_key->p;
-	rb.nq_prime = (char *)rsa_key->q;
-	rb.bp_key = (char *)rsa_key->dp;
-	rb.bq_key = (char *)rsa_key->dq;
-	rb.u_mult_inv = (char *)rsa_key->qInverse;
+	rb.np_prime = rsa_key->p;
+	rb.nq_prime = rsa_key->q;
+	rb.bp_key = rsa_key->dp;
+	rb.bq_key = rsa_key->dq;
+	rb.u_mult_inv = rsa_key->qInverse;
 
 	hardware = ALGO_SW;
 	if (adapter_handle == DRIVER_NOT_LOADED)
@@ -1291,7 +1296,9 @@
 				rsa_crt_sw(&rb) : ENODEV;
 	}
 	if (rc == 0)
-		stats_increment(ICA_STATS_RSA_CRT, hardware, ENCRYPT);
+		stats_increment(ICA_STATS_RSA_CRT_512 +
+				rsa_keysize_stats_ofs(rsa_key->key_length),
+				hardware, ENCRYPT);
 
 	OPENSSL_cleanse(&rb, sizeof(rb));
 
@@ -1422,7 +1429,9 @@
 	}
 
 	if (rc == 0)
-		stats_increment(ICA_STATS_ECKGEN, hardware, ENCRYPT);
+		stats_increment(ICA_STATS_ECKGEN_160 +
+				ecc_keysize_stats_ofs(key->nid),
+				hardware, ENCRYPT);
 
 	return rc;
 }
@@ -1483,7 +1492,9 @@
 	}
 
 	if (rc == 0)
-		stats_increment(ICA_STATS_ECDH, hardware, ENCRYPT);
+		stats_increment(ICA_STATS_ECDH_160 +
+				ecc_keysize_stats_ofs(privkey_A->nid),
+				hardware, ENCRYPT);
 
 	return rc;
 }
@@ -1538,7 +1549,9 @@
 	}
 
 	if (rc == 0)
-		stats_increment(ICA_STATS_ECDSA_SIGN, hardware, ENCRYPT);
+		stats_increment(ICA_STATS_ECDSA_SIGN_160 +
+				ecc_keysize_stats_ofs(privkey->nid),
+				hardware, ENCRYPT);
 
 	return rc;
 }
@@ -1595,7 +1608,9 @@
 	}
 
 	if (rc == 0)
-		stats_increment(ICA_STATS_ECDSA_VERIFY, hardware, ENCRYPT);
+		stats_increment(ICA_STATS_ECDSA_VERIFY_160 +
+				ecc_keysize_stats_ofs(pubkey->nid),
+				hardware, ENCRYPT);
 
 	return rc;
 }
@@ -2346,264 +2361,6 @@
  *
  ******************************************************************************/
 
-unsigned int ica_des_encrypt(unsigned int mode,
-			     unsigned int data_length,
-			     unsigned char *input_data,
-			     ica_des_vector_t *iv,
-			     ica_des_key_single_t *des_key,
-			     unsigned char *output_data)
-{
-#ifdef NO_CPACF
-	UNUSED(mode);
-	UNUSED(data_length);
-	UNUSED(input_data);
-	UNUSED(iv);
-	UNUSED(des_key);
-	UNUSED(output_data);
-	return EPERM;
-#else
-#ifdef ICA_FIPS
-	if (fips)
-		return EACCES;
-#endif /* ICA_FIPS */
-
-	if (check_des_parms(mode, data_length, input_data,
-			    (unsigned char *) iv, (unsigned char *) des_key,
-			     output_data))
-		return EINVAL;
-
-	if (mode == MODE_ECB) {
-		return s390_des_ecb(DEA_ENCRYPT, data_length,
-				    input_data, (unsigned char *) des_key,
-				    output_data);
-	} else if (mode == MODE_CBC) {
-		return s390_des_cbc(DEA_ENCRYPT, data_length,
-				    input_data, (unsigned char *) iv,
-				    (unsigned char *) des_key, output_data);
-	}
-	return EINVAL;
-#endif /* NO_CPACF */
-}
-
-unsigned int ica_des_decrypt(unsigned int mode,
-			     unsigned int data_length,
-			     unsigned char *input_data,
-			     ica_des_vector_t *iv,
-			     ica_des_key_single_t *des_key,
-			     unsigned char *output_data)
-{
-#ifdef NO_CPACF
-	UNUSED(mode);
-	UNUSED(data_length);
-	UNUSED(input_data);
-	UNUSED(iv);
-	UNUSED(des_key);
-	UNUSED(output_data);
-	return EPERM;
-#else
-#ifdef ICA_FIPS
-	if (fips)
-		return EACCES;
-#endif /* ICA_FIPS */
-
-	if (check_des_parms(mode, data_length, input_data,
-			    (unsigned char *) iv, (unsigned char *) des_key,
-			     output_data))
-		return EINVAL;
-
-	if (mode == MODE_ECB) {
-		return s390_des_ecb(DEA_DECRYPT, data_length,
-				    input_data, (unsigned char *) des_key,
-				    output_data);
-	} else if (mode == MODE_CBC) {
-		return s390_des_cbc(DEA_DECRYPT, data_length,
-				    input_data, (unsigned char *) iv,
-				    (unsigned char *) des_key, output_data);
-	}
-	return EINVAL;
-#endif /* NO_CPACF */
-}
-
-unsigned int ica_3des_encrypt(unsigned int mode,
-			      unsigned int data_length,
-			      unsigned char *input_data,
-			      ica_des_vector_t *iv,
-			      ica_des_key_triple_t *des_key,
-			      unsigned char *output_data)
-{
-#ifdef NO_CPACF
-	UNUSED(mode);
-	UNUSED(data_length);
-	UNUSED(input_data);
-	UNUSED(iv);
-	UNUSED(des_key);
-	UNUSED(output_data);
-	return EPERM;
-#else
-#ifdef ICA_FIPS
-	if (fips >> 1)
-		return EACCES;
-	if (fips_check_3des_key(des_key))
-		return EINVAL;
-#endif /* ICA_FIPS */
-
-	if (check_des_parms(mode, data_length, input_data,
-			    (unsigned char *) iv, (unsigned char *) des_key,
-			     output_data))
-		return EINVAL;
-
-	if (mode == MODE_ECB) {
-		return s390_des_ecb(TDEA_192_ENCRYPT, data_length,
-				    input_data,(unsigned char *) des_key,
-				    output_data);
-	} else if (mode == MODE_CBC) {
-		return s390_des_cbc(TDEA_192_ENCRYPT, data_length,
-				    input_data, (unsigned char *) iv,
-				    (unsigned char *) des_key, output_data);
-	}
-	return EINVAL;
-#endif /* NO_CPACF */
-}
-
-unsigned int ica_3des_decrypt(unsigned int mode,
-			      unsigned int data_length,
-			      unsigned char *input_data,
-			      ica_des_vector_t *iv,
-			      ica_des_key_triple_t *des_key,
-			      unsigned char *output_data)
-{
-#ifdef NO_CPACF
-	UNUSED(mode);
-	UNUSED(data_length);
-	UNUSED(input_data);
-	UNUSED(iv);
-	UNUSED(des_key);
-	UNUSED(output_data);
-	return EPERM;
-#else
-#ifdef ICA_FIPS
-	if (fips >> 1)
-		return EACCES;
-	if (fips_check_3des_key(des_key))
-		return EINVAL;
-#endif /* ICA_FIPS */
-
-	if (check_des_parms(mode, data_length, input_data,
-			    (unsigned char *) iv, (unsigned char *) des_key,
-			     output_data))
-		return EINVAL;
-
-	if (mode == MODE_ECB) {
-		return s390_des_ecb(TDEA_192_DECRYPT, data_length,
-				    input_data, (unsigned char *) des_key,
-				    output_data);
-	} else if (mode == MODE_CBC) {
-		return s390_des_cbc(TDEA_192_DECRYPT, data_length,
-				    input_data, (unsigned char *) iv,
-				    (unsigned char *) des_key, output_data);
-	}
-	return EINVAL;
-#endif /* NO_CPACF */
-}
-
-unsigned int ica_aes_encrypt(unsigned int mode,
-			     unsigned int data_length,
-			     unsigned char *input_data,
-			     ica_aes_vector_t *iv,
-			     unsigned int key_length,
-			     unsigned char *aes_key,
-			     unsigned char *output_data)
-{
-#ifdef NO_CPACF
-	UNUSED(mode);
-	UNUSED(data_length);
-	UNUSED(input_data);
-	UNUSED(iv);
-	UNUSED(key_length);
-	UNUSED(aes_key);
-	UNUSED(output_data);
-	return EPERM;
-#else
-	unsigned int function_code;
-
-#ifdef ICA_FIPS
-	if (fips >> 1)
-		return EACCES;
-#endif /* ICA_FIPS */
-
-	/* check for obvious errors in parms */
-	if (check_aes_parms(mode, data_length, input_data,
-			    (unsigned char *) iv, key_length, aes_key,
-			    output_data))
-		return EINVAL;
-
-	function_code = aes_directed_fc(key_length, ICA_ENCRYPT);
-
-	switch (mode) {
-	case MODE_CBC:
-		return s390_aes_cbc(function_code, data_length, input_data,
-				    (unsigned char *) iv, aes_key,
-				    output_data);
-	case MODE_ECB:
-		return s390_aes_ecb(function_code, data_length, input_data,
-				    aes_key, output_data);
-	default:
-		return EINVAL;
-	}
-
-	return EINVAL;
-#endif /* NO_CPACF */
-}
-
-unsigned int ica_aes_decrypt(unsigned int mode,
-			     unsigned int data_length,
-			     unsigned char *input_data,
-			     ica_aes_vector_t *iv,
-			     unsigned int key_length,
-			     unsigned char *aes_key,
-			     unsigned char *output_data)
-{
-#ifdef NO_CPACF
-	UNUSED(mode);
-	UNUSED(data_length);
-	UNUSED(input_data);
-	UNUSED(iv);
-	UNUSED(key_length);
-	UNUSED(aes_key);
-	UNUSED(output_data);
-	return EPERM;
-#else
-	unsigned int function_code;
-
-#ifdef ICA_FIPS
-	if (fips >> 1)
-		return EACCES;
-#endif /* ICA_FIPS */
-
-	/* check for obvious errors in parms */
-	if (check_aes_parms(mode, data_length, input_data,
-			    (unsigned char *) iv, key_length, aes_key,
-			    output_data))
-		return EINVAL;
-
-	function_code = aes_directed_fc(key_length, ICA_DECRYPT);
-
-	switch (mode) {
-	case MODE_CBC:
-		return s390_aes_cbc(function_code, data_length, input_data,
-				    (unsigned char *) iv, aes_key,
-				    output_data);
-	case MODE_ECB:
-		return s390_aes_ecb(function_code, data_length, input_data,
-				    aes_key, output_data);
-	default:
-		return EINVAL;
-	}
-
-	return EINVAL;
-#endif /* NO_CPACF */
-}
-
 unsigned int ica_des_ecb(const unsigned char *in_data, unsigned char *out_data,
 			 unsigned long data_length, unsigned char *key,
 			 unsigned int direction)
@@ -3639,7 +3396,9 @@
 		       iv);
 
 	if (!rc)
-		stats_increment(ICA_STATS_AES_CMAC, ALGO_HW, ICA_DECRYPT);
+		stats_increment(ICA_STATS_AES_CMAC_128 +
+				aes_directed_fc_stats_ofs(function_code),
+				ALGO_HW, ICA_DECRYPT);
 	return rc;
 #endif /* NO_CPACF */
 }
@@ -3684,8 +3443,10 @@
 			       key_length, key, mac_length, mac, iv);
 		if (rc)
 			return rc;
-		else
-			stats_increment(ICA_STATS_AES_CMAC, ALGO_HW, direction);
+
+		stats_increment(ICA_STATS_AES_CMAC_128 +
+				aes_directed_fc_stats_ofs(function_code),
+				ALGO_HW, direction);
 	} else {
 		/* verify */
 		rc = s390_cmac(function_code, message, message_length,
@@ -3694,8 +3455,10 @@
 			return rc;
 		if (CRYPTO_memcmp(tmp_mac, mac, mac_length))
 			return EFAULT;
-		else
-			stats_increment(ICA_STATS_AES_CMAC, ALGO_HW, direction);
+
+		stats_increment(ICA_STATS_AES_CMAC_128 +
+				aes_directed_fc_stats_ofs(function_code),
+				ALGO_HW, direction);
 	}
 
 	return 0;
@@ -4483,14 +4246,18 @@
 #endif /* NO_CPACF */
 }
 
-#ifdef ICA_FIPS
-
 int
 ica_fips_status(void)
 {
+#ifdef ICA_FIPS
 	return fips;
+#else
+	return 0;
+#endif
 }
 
+#ifdef ICA_FIPS
+
 void
 ica_fips_powerup_tests(void)
 {
diff -Nru libica-3.9.0/src/icainfo.c libica-4.0.0/src/icainfo.c
--- libica-3.9.0/src/icainfo.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/icainfo.c	2021-12-06 12:01:54.000000000 +0100
@@ -333,6 +333,8 @@
 	{"X25519 Derive", X25519_DERIVE},
 	{"X448 Keygen", X448_KEYGEN},
 	{"X448 Derive", X448_DERIVE},
+	{"RSA Keygen ME", RSA_KEY_GEN_ME},
+	{"RSA Keygen CRT", RSA_KEY_GEN_CRT},
 	{"RSA ME", RSA_ME},
 	{"RSA CRT", RSA_CRT},
 	{"DES ECB", DES_ECB},
@@ -462,7 +464,7 @@
 #endif /* ICA_FIPS */
 
 #ifdef NO_SW_FALLBACKS
-	printf("Software fallbacks are disabled in libica-cex.\n");
+	printf("Software fallbacks are disabled.\n");
 #endif
 #ifdef NO_CPACF
 	printf("CPACF support (including fallbacks) is disabled in libica-cex.\n");
diff -Nru libica-3.9.0/src/icastats.c libica-4.0.0/src/icastats.c
--- libica-3.9.0/src/icastats.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/icastats.c	2021-12-06 12:01:54.000000000 +0100
@@ -21,10 +21,13 @@
 #include <getopt.h>
 #include <pwd.h>
 #include <libgen.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/utsname.h>
 #include "icastats.h"
 
 #define CMD_NAME "icastats"
-#define COPYRIGHT "Copyright IBM Corp. 2009-2019"
+#define COPYRIGHT "Copyright IBM Corp. 2009-2021"
 
 void print_version(void)
 {
@@ -43,13 +46,15 @@
 	       " -d, --delete        delete your own statistics.\n"
 	       " -D, --delete-all    delete the statistics from all users. (root user only)\n"
 	       " -U, --user <userid> show the statistics from one user. (root user only)\n"
-	       " -S, --summary       show the accumulated statistics from alle users. (root user only)\n"
+	       " -S, --summary       show the accumulated statistics from all users. (root user only)\n"
 	       " -A, --all	     show the statistic tables from all users. (root user only)\n"
+	       " -k, --key-sizes     show statistics per key size.\n"
+	       " -j, --json          output the statistics in JSON format.\n"
 	       " -v, --version       output version information\n"
 	       " -h, --help          display help information\n");
 }
 
-#define getopt_string "rRdDU:SAvh"
+#define getopt_string "rRdDU:SAkjvh"
 static struct option getopt_long_options[] = {
 	{"reset", 0, 0, 'r'},
 	{"reset-all", 0, 0, 'R'},
@@ -58,6 +63,8 @@
 	{"user", required_argument, 0, 'U'},
 	{"summary", 0, 0, 'S'},
 	{"all", 0, 0, 'A'},
+	{"key-sizes", 0, 0, 'k'},
+	{"json", 0, 0, 'j'},
 	{"version", 0, 0, 'v'},
 	{"help", 0, 0, 'h'},
 	{0, 0, 0, 0}
@@ -70,22 +77,25 @@
 
 
 #define CELL_SIZE 12
-void print_stats(stats_entry_t *stats)
+void print_stats(stats_entry_t *stats, int key_sizes)
 {
 	printf(" function       |             hardware         |              software\n");
 	printf("----------------+------------------------------+-----------------------------\n");
 	printf("                |        ENC    CRYPT     DEC  |        ENC     CRYPT    DEC \n");
 	printf("----------------+------------------------------+-----------------------------\n");
 	unsigned int i;
-	for (i = 0; i < ICA_NUM_STATS; ++i){
-		if(i<=ICA_STATS_RSA_CRT){
+	for (i = 0; i < ICA_NUM_STATS; ++i) {
+		if (!key_sizes && strncmp(STATS_DESC[i], "- ", 2) == 0)
+			continue;
+
+		if(i <= ICA_STATS_RSA_CRT_4096) {
 			printf(" %14s |        %*lu          |         %*lu\n",
 			       STATS_DESC[i],
 			       CELL_SIZE,
 			       stats[i].enc.hw,
 			       CELL_SIZE,
 			       stats[i].enc.sw);
-		} else{
+		} else {
 			printf(" %14s |%*lu     %*lu |%*lu    %*lu\n",
 			       STATS_DESC[i],
 			       CELL_SIZE,
@@ -101,8 +111,96 @@
 	}
 }
 
+static int first_usr;
+
+void print_json_header()
+{
+	char timestamp[200];
+	struct utsname un;
+	struct tm *tm;
+	time_t t;
+
+	time(&t);
+	tm = gmtime(&t);
+	/* ISO 8601 format: e.g. 2021-11-17T08:01:23Z (always UTC) */
+	strftime(timestamp, sizeof(timestamp), "%FT%TZ", tm);
+
+	if (uname(&un) != 0) {
+		fprintf(stderr, "Failed to obtain system information, uname: %s",
+		       strerror(errno));
+		return;
+	}
+
+	printf("{\n\t\"host\": {\n");
+	printf("\t\t\"nodename\": \"%s\",\n", un.nodename);
+	printf("\t\t\"sysname\": \"%s\",\n", un.sysname);
+	printf("\t\t\"release\": \"%s\",\n", un.release);
+	printf("\t\t\"machine\": \"%s\",\n", un.machine);
+	printf("\t\t\"date\": \"%s\"\n", timestamp);
+	printf("\t},\n\t\"users\": [");
+
+	first_usr = 1;
+}
+
+void print_stats_json(stats_entry_t *stats, const char *usr)
+{
+	unsigned int i;
+	const char *last_func = NULL;
+
+	if (!first_usr)
+		printf(",");
+	printf("\n\t\t{\n\t\t\t\"user\": \"%s\",\n", usr);
+	printf("\t\t\t\"functions\": [");
+
+	for (i = 0; i < ICA_NUM_STATS; ++i) {
+		if (i < ICA_NUM_STATS - 1 &&
+		    strncmp(STATS_DESC[i + 1], "- ", 2) == 0 &&
+		    strncmp(STATS_DESC[i], "- ", 2) != 0) {
+			last_func = STATS_DESC[i];
+			continue;
+		}
+
+		if (i != 0)
+			printf(",");
+		printf("\n\t\t\t\t{\n");
+
+		if (strncmp(STATS_DESC[i], "- ", 2) == 0 && last_func != NULL) {
+			printf("\t\t\t\t\t\"function\": \"%s %s\",\n",
+			       last_func, STATS_DESC[i]);
+		} else {
+			printf("\t\t\t\t\t\"function\": \"%s\",\n",
+			       STATS_DESC[i]);
+			last_func = NULL;
+		}
+
+		if (i <= ICA_STATS_RSA_CRT_4096) {
+			printf("\t\t\t\t\t\"hw-crypt\": %lu,\n",
+			       stats[i].enc.hw);
+			printf("\t\t\t\t\t\"sw-crypt\": %lu\n",
+			       stats[i].enc.sw);
+		} else {
+			printf("\t\t\t\t\t\"hw-enc\": %lu,\n",
+			       stats[i].enc.hw);
+			printf("\t\t\t\t\t\"sw-enc\": %lu,\n",
+			       stats[i].enc.sw);
+			printf("\t\t\t\t\t\"hw-dec\": %lu,\n",
+			       stats[i].dec.hw);
+			printf("\t\t\t\t\t\"sw-dec\": %lu\n",
+			       stats[i].dec.sw);
+		}
+
+		printf("\t\t\t\t}");
+	}
 
+	printf("\n\t\t\t]\n\t\t}");
 
+	first_usr = 0;
+}
+
+void print_json_footer()
+{
+	printf("\n\t]\n}\n");
+}
 
 int main(int argc, char *argv[])
 {
@@ -113,6 +211,8 @@
 	int sum = 0;
 	int user = -1;
 	int all = 0;
+	int key_sizes = 0;
+	int json = 0;
 	struct passwd *pswd;
 
 	while ((rc = getopt_long(argc, argv, getopt_string,
@@ -155,6 +255,12 @@
 		case 'A':
 			all = 1;
 			break;
+		case 'k':
+			key_sizes = 1;
+			break;
+		case 'j':
+			json = 1;
+			break;
 		case 'v':
 			print_version();
 			exit(0);
@@ -191,16 +297,24 @@
 	if(all){
 		char *usr;
 		stats_entry_t *entries;
+		if (json)
+			print_json_header();
 		while((usr = get_next_usr()) != NULL){
 			if((entries = malloc(sizeof(stats_entry_t)*ICA_NUM_STATS)) == NULL){
 				perror("malloc: ");
 				return EXIT_FAILURE;
 			}
-			get_stats_data(entries);;
-			printf("user: %s\n", usr);
-			print_stats(entries);
+			get_stats_data(entries);
+			if (json) {
+				print_stats_json(entries, usr);
+			} else {
+				printf("user: %s\n", usr);
+				print_stats(entries, key_sizes);
+			}
 			free(entries);
 		}
+		if (json)
+			print_json_footer();
 		return EXIT_SUCCESS;
 	}
 
@@ -215,10 +329,14 @@
 			perror("get_stats_sum: ");
 			return EXIT_FAILURE;
 		}
-		print_stats(entries);
+		if (json) {
+			print_json_header();
+			print_stats_json(entries, "all users");
+			print_json_footer();
+		} else {
+			print_stats(entries, key_sizes);
+		}
 		return EXIT_SUCCESS;
-
-
 	}
 
 	if(reset == 2){
@@ -243,7 +361,18 @@
 			return EXIT_FAILURE;
 		}
 		get_stats_data(stats);
-		print_stats(stats);
+		if (json) {
+			pswd = getpwuid(user == -1 ? geteuid() : (uid_t)user);
+			if (pswd == NULL) {
+				fprintf(stderr, "Failed to get user name");
+				return EXIT_FAILURE;
+			}
+			print_json_header();
+			print_stats_json(stats, pswd->pw_name);
+			print_json_footer();
+		} else {
+			print_stats(stats, key_sizes);
+		}
 
 	}
 	return EXIT_SUCCESS;
diff -Nru libica-3.9.0/src/icastats_shared.c libica-4.0.0/src/icastats_shared.c
--- libica-3.9.0/src/icastats_shared.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/icastats_shared.c	2021-12-06 12:01:54.000000000 +0100
@@ -33,22 +33,6 @@
 static stats_entry_t *stats = NULL;
 volatile int stats_shm_handle = NOT_INITIALIZED;
 
-
-static inline void atomic_add(uint64_t *x, uint64_t i)
-{
-    uint64_t old;
-    uint64_t new;
-    asm volatile ("   lg      %0,%2\n"
-                  "0: lgr     %1,%0\n"
-                  "   agr     %1,%3\n"
-                  "   csg     %0,%1,%2\n"
-                  "   jl      0b"
-                 :"=&d" (old), "=&d"(new), "=Q"(*x)
-                 :"d"(i), "Q"(*x)
-                 :"cc", "memory");
-}
-
-
 /* open shared memory segment
  * Arguments:
  * @user: if user is -1 stats_mmap will open the shared memory segent of the same
@@ -63,24 +47,36 @@
 int stats_mmap(int user)
 {
 	char shm_id[NAME_LENGHT];
+	struct stat stat_buf;
 
 	if (stats == NULL) {
 		sprintf(shm_id, "icastats_%d",
 			user == -1 ? geteuid() : (uid_t)user);
 
-		stats_shm_handle = shm_open(shm_id, O_CREAT | O_RDWR,
+		stats_shm_handle = shm_open(shm_id, O_RDWR,  S_IRUSR | S_IWUSR);
+		if (stats_shm_handle == NOT_INITIALIZED)
+			stats_shm_handle = shm_open(shm_id, O_CREAT | O_RDWR,
 						    S_IRUSR | S_IWUSR);
 
 		if (stats_shm_handle == NOT_INITIALIZED)
 			return -1;
 
 		if (user > 0 && geteuid() == 0) {
-			if (fchown(stats_shm_handle, user, user) == -1)
+			if (fchown(stats_shm_handle, user, user) == -1) {
+				close(stats_shm_handle);
 				return -1;
+			}
+		}
+
+		if (fstat(stats_shm_handle, &stat_buf)) {
+			close(stats_shm_handle);
+			return -1;
 		}
 
-		if (ftruncate(stats_shm_handle, STATS_SHM_SIZE) == -1)
+		if (ftruncate(stats_shm_handle, STATS_SHM_SIZE) == -1) {
+			close(stats_shm_handle);
 			return -1;
+		}
 
 		stats = (stats_entry_t *) mmap(NULL, STATS_SHM_SIZE, PROT_READ |
 						 PROT_WRITE, MAP_SHARED,
@@ -90,6 +86,9 @@
 			stats = NULL;
 			return -1;
 		}
+
+		if (stat_buf.st_size != STATS_SHM_SIZE)
+			memset(stats, 0, STATS_SHM_SIZE);
 	}
 	return 0;
 }
@@ -142,18 +141,87 @@
 			return stats[field].dec.sw;
 }
 
+static uint64_t calc_summary(stats_fields_t start, unsigned int num,
+		             int hardware, int direction)
+{
+	unsigned int i;
+	uint64_t sum = 0;
+
+	for (i = 0; i < num; i++)
+		sum += stats_query(start + i, hardware, direction);
+
+	return sum;
+}
+
 /* Returns the statistic data in a stats_entry_t array
  * @entries - Needs to be a array of size ICA_NUM_STATS.
  */
-
 void get_stats_data(stats_entry_t *entries)
 {
 	unsigned int i;
-	for(i = 0;i<ICA_NUM_STATS; i++){
-		entries[i].enc.hw = stats_query(i, ALGO_HW, ENCRYPT);
-		entries[i].enc.sw = stats_query(i, ALGO_SW, ENCRYPT);
-		entries[i].dec.hw = stats_query(i, ALGO_HW, DECRYPT);
-		entries[i].dec.sw = stats_query(i, ALGO_SW, DECRYPT);
+	for(i = 0; i < ICA_NUM_STATS; i++) {
+		switch (i) {
+		case ICA_STATS_AES_ECB:
+		case ICA_STATS_AES_CBC:
+		case ICA_STATS_AES_OFB:
+		case ICA_STATS_AES_CFB:
+		case ICA_STATS_AES_CTR:
+		case ICA_STATS_AES_CMAC:
+		case ICA_STATS_AES_GCM:
+			entries[i].enc.hw = calc_summary(i + 1, 3,
+					                 ALGO_HW, ENCRYPT);
+			entries[i].enc.sw = calc_summary(i + 1, 3,
+					                 ALGO_SW, ENCRYPT);
+			entries[i].dec.hw = calc_summary(i + 1, 3,
+					                 ALGO_HW, DECRYPT);
+			entries[i].dec.sw = calc_summary(i + 1, 3,
+					                 ALGO_SW, DECRYPT);
+			break;
+
+		case ICA_STATS_AES_XTS:
+			entries[i].enc.hw = calc_summary(i + 1, 2,
+					                 ALGO_HW, ENCRYPT);
+			entries[i].enc.sw = calc_summary(i + 1, 2,
+					                 ALGO_SW, ENCRYPT);
+			entries[i].dec.hw = calc_summary(i + 1, 2,
+					                 ALGO_HW, DECRYPT);
+			entries[i].dec.sw = calc_summary(i + 1, 2,
+					                 ALGO_SW, DECRYPT);
+			break;
+
+		case ICA_STATS_RSA_ME:
+		case ICA_STATS_RSA_CRT:
+			entries[i].enc.hw = calc_summary(i + 1, 4,
+					                 ALGO_HW, ENCRYPT);
+			entries[i].enc.sw = calc_summary(i + 1, 4,
+					                 ALGO_SW, ENCRYPT);
+			entries[i].dec.hw = calc_summary(i + 1, 4,
+					                 ALGO_HW, DECRYPT);
+			entries[i].dec.sw = calc_summary(i + 1, 4,
+					                 ALGO_SW, DECRYPT);
+			break;
+
+		case ICA_STATS_ECDH:
+		case ICA_STATS_ECDSA_SIGN:
+		case ICA_STATS_ECDSA_VERIFY:
+		case ICA_STATS_ECKGEN:
+			entries[i].enc.hw = calc_summary(i + 1, 8,
+					                 ALGO_HW, ENCRYPT);
+			entries[i].enc.sw = calc_summary(i + 1, 8,
+					                 ALGO_SW, ENCRYPT);
+			entries[i].dec.hw = calc_summary(i + 1, 8,
+					                 ALGO_HW, DECRYPT);
+			entries[i].dec.sw = calc_summary(i + 1, 8,
+					                 ALGO_SW, DECRYPT);
+			break;
+
+		default:
+			entries[i].enc.hw = stats_query(i, ALGO_HW, ENCRYPT);
+			entries[i].enc.sw = stats_query(i, ALGO_SW, ENCRYPT);
+			entries[i].dec.hw = stats_query(i, ALGO_HW, DECRYPT);
+			entries[i].dec.sw = stats_query(i, ALGO_SW, DECRYPT);
+			break;
+		}
 	}
 }
 
@@ -277,14 +345,14 @@
 
 	if(direction == ENCRYPT)
 		if (hardware == ALGO_HW)
-			atomic_add(&stats[field].enc.hw, 1);
+			__sync_add_and_fetch(&stats[field].enc.hw, 1);
 		else
-			atomic_add(&stats[field].enc.sw, 1);
+			__sync_add_and_fetch(&stats[field].enc.sw, 1);
 	else
 		if (hardware == ALGO_HW)
-			atomic_add(&stats[field].dec.hw, 1);
+			__sync_add_and_fetch(&stats[field].dec.hw, 1);
 		else
-			atomic_add(&stats[field].dec.sw, 1);
+			__sync_add_and_fetch(&stats[field].dec.sw, 1);
 }
 #endif
 
diff -Nru libica-3.9.0/src/include/icastats.h libica-4.0.0/src/include/icastats.h
--- libica-3.9.0/src/include/icastats.h	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/include/icastats.h	2021-12-06 12:01:54.000000000 +0100
@@ -16,6 +16,9 @@
 
 #include <stdint.h>
 
+#include <openssl/obj_mac.h>
+
+#include "ica_api.h"
 
 typedef struct crypt_opts{
 	uint64_t hw;
@@ -47,9 +50,41 @@
 	ICA_STATS_PRNG,
 	ICA_STATS_DRBGSHA512,
 	ICA_STATS_ECDH,
+	ICA_STATS_ECDH_160,
+	ICA_STATS_ECDH_192,
+	ICA_STATS_ECDH_224,
+	ICA_STATS_ECDH_256,
+	ICA_STATS_ECDH_320,
+	ICA_STATS_ECDH_384,
+	ICA_STATS_ECDH_512,
+	ICA_STATS_ECDH_521,
 	ICA_STATS_ECDSA_SIGN,
+	ICA_STATS_ECDSA_SIGN_160,
+	ICA_STATS_ECDSA_SIGN_192,
+	ICA_STATS_ECDSA_SIGN_224,
+	ICA_STATS_ECDSA_SIGN_256,
+	ICA_STATS_ECDSA_SIGN_320,
+	ICA_STATS_ECDSA_SIGN_384,
+	ICA_STATS_ECDSA_SIGN_512,
+	ICA_STATS_ECDSA_SIGN_521,
 	ICA_STATS_ECDSA_VERIFY,
+	ICA_STATS_ECDSA_VERIFY_160,
+	ICA_STATS_ECDSA_VERIFY_192,
+	ICA_STATS_ECDSA_VERIFY_224,
+	ICA_STATS_ECDSA_VERIFY_256,
+	ICA_STATS_ECDSA_VERIFY_320,
+	ICA_STATS_ECDSA_VERIFY_384,
+	ICA_STATS_ECDSA_VERIFY_512,
+	ICA_STATS_ECDSA_VERIFY_521,
 	ICA_STATS_ECKGEN,
+	ICA_STATS_ECKGEN_160,
+	ICA_STATS_ECKGEN_192,
+	ICA_STATS_ECKGEN_224,
+	ICA_STATS_ECKGEN_256,
+	ICA_STATS_ECKGEN_320,
+	ICA_STATS_ECKGEN_384,
+	ICA_STATS_ECKGEN_512,
+	ICA_STATS_ECKGEN_521,
 	ICA_STATS_ED25519_KEYGEN,
 	ICA_STATS_ED25519_SIGN,
 	ICA_STATS_ED25519_VERIFY,
@@ -61,7 +96,15 @@
 	ICA_STATS_X448_KEYGEN,
 	ICA_STATS_X448_DERIVE,
 	ICA_STATS_RSA_ME,
-	ICA_STATS_RSA_CRT, /* add new crypt counters above RSA_CRT
+	ICA_STATS_RSA_ME_512,
+	ICA_STATS_RSA_ME_1024,
+	ICA_STATS_RSA_ME_2048,
+	ICA_STATS_RSA_ME_4096,
+	ICA_STATS_RSA_CRT,
+	ICA_STATS_RSA_CRT_512,
+	ICA_STATS_RSA_CRT_1024,
+	ICA_STATS_RSA_CRT_2048,
+	ICA_STATS_RSA_CRT_4096, /* add new crypt counters above RSA_CRT_4096
 			      (see print_stats function) */
 
 	/* enc and dec counter  */
@@ -78,13 +121,36 @@
 	ICA_STATS_3DES_CTR,
 	ICA_STATS_3DES_CMAC,
 	ICA_STATS_AES_ECB,
+	ICA_STATS_AES_ECB_128,
+	ICA_STATS_AES_ECB_192,
+	ICA_STATS_AES_ECB_256,
 	ICA_STATS_AES_CBC,
+	ICA_STATS_AES_CBC_128,
+	ICA_STATS_AES_CBC_192,
+	ICA_STATS_AES_CBC_256,
 	ICA_STATS_AES_OFB,
+	ICA_STATS_AES_OFB_128,
+	ICA_STATS_AES_OFB_192,
+	ICA_STATS_AES_OFB_256,
 	ICA_STATS_AES_CFB,
+	ICA_STATS_AES_CFB_128,
+	ICA_STATS_AES_CFB_192,
+	ICA_STATS_AES_CFB_256,
 	ICA_STATS_AES_CTR,
+	ICA_STATS_AES_CTR_128,
+	ICA_STATS_AES_CTR_192,
+	ICA_STATS_AES_CTR_256,
 	ICA_STATS_AES_CMAC,
+	ICA_STATS_AES_CMAC_128,
+	ICA_STATS_AES_CMAC_192,
+	ICA_STATS_AES_CMAC_256,
 	ICA_STATS_AES_XTS,
+	ICA_STATS_AES_XTS_128,
+	ICA_STATS_AES_XTS_256,
 	ICA_STATS_AES_GCM,
+	ICA_STATS_AES_GCM_128,
+	ICA_STATS_AES_GCM_192,
+	ICA_STATS_AES_GCM_256,
 
 	/* number of counters */
 	ICA_NUM_STATS
@@ -107,10 +173,42 @@
 	"GHASH",      	\
 	"P_RNG",      	\
 	"DRBG-SHA-512",	\
-	"ECDH",         \
-	"ECDSA Sign",   \
-	"ECDSA Verify", \
-	"EC Keygen",    \
+	"ECDH",		\
+	"- 160",	\
+	"- 192",	\
+	"- 224",	\
+	"- 256",	\
+	"- 320",	\
+	"- 384",	\
+	"- 512",	\
+	"- 521",	\
+	"ECDSA Sign",	\
+	"- 160",	\
+	"- 192",	\
+	"- 224",	\
+	"- 256",	\
+	"- 320",	\
+	"- 384",	\
+	"- 512",	\
+	"- 521",	\
+	"ECDSA Verify",	\
+	"- 160",	\
+	"- 192",	\
+	"- 224",	\
+	"- 256",	\
+	"- 320",	\
+	"- 384",	\
+	"- 512",	\
+	"- 521",	\
+	"EC Keygen",	\
+	"- 160",	\
+	"- 192",	\
+	"- 224",	\
+	"- 256",	\
+	"- 320",	\
+	"- 384",	\
+	"- 512",	\
+	"- 521",	\
 	"Ed25519 Keygen",\
 	"Ed25519 Sign", \
 	"Ed25519 Verify",\
@@ -121,8 +219,16 @@
 	"X25519 Derive",\
 	"X448 Keygen",  \
 	"X448 Derive",  \
-	"RSA-ME",     	\
-	"RSA-CRT",    	\
+	"RSA-ME",	\
+	"- 512",	\
+	"- 1024",	\
+	"- 2048",	\
+	"- 4096",	\
+	"RSA-CRT",	\
+	"- 512",	\
+	"- 1024",	\
+	"- 2048",	\
+	"- 4096",	\
 	"DES ECB",    	\
 	"DES CBC",    	\
 	"DES OFB",    	\
@@ -136,15 +242,36 @@
 	"3DES CTR",   	\
 	"3DES CMAC",	\
 	"AES ECB",	\
+	"- 128",	\
+	"- 192",	\
+	"- 256",	\
 	"AES CBC",	\
+	"- 128",	\
+	"- 192",	\
+	"- 256",	\
 	"AES OFB",	\
+	"- 128",	\
+	"- 192",	\
+	"- 256",	\
 	"AES CFB",	\
+	"- 128",	\
+	"- 192",	\
+	"- 256",	\
 	"AES CTR",	\
+	"- 128",	\
+	"- 192",	\
+	"- 256",	\
 	"AES CMAC",	\
-	"AES XTS",  \
-	"AES GCM"
-
-
+	"- 128",	\
+	"- 192",	\
+	"- 256",	\
+	"AES XTS",	\
+	"- 128",	\
+	"- 256",	\
+	"AES GCM",	\
+	"- 128",	\
+	"- 192",	\
+	"- 256"
 
 #define STATS_SHM_SIZE (sizeof(stats_entry_t) * ICA_NUM_STATS)
 #define ENCRYPT 1
@@ -167,5 +294,64 @@
 void stats_reset();
 int delete_all();
 
+static inline int aes_directed_fc_stats_ofs(unsigned int fc)
+{
+	switch (fc) {
+	case AES_128_DECRYPT:
+	case AES_128_ENCRYPT:
+		return 0;
+	case AES_192_DECRYPT:
+	case AES_192_ENCRYPT:
+		return 1;
+	case AES_256_DECRYPT:
+	case AES_256_ENCRYPT:
+		return 2;
+	case AES_128_XTS_ENCRYPT:
+	case AES_128_XTS_DECRYPT:
+		return 0;
+	case AES_256_XTS_ENCRYPT:
+	case AES_256_XTS_DECRYPT:
+		return 1;
+	}
+	return 0;
+}
+
+static inline int rsa_keysize_stats_ofs(unsigned int key_length)
+{
+	if (key_length >= 4096 / 8)
+		return 3;
+	if (key_length >= 2048 / 8)
+		return 2;
+	if (key_length >= 1024 / 8)
+		return 1;
+	return 0;
+}
+
+static inline int ecc_keysize_stats_ofs(int nid)
+{
+	switch (nid) {
+	case NID_brainpoolP160r1:
+		return 0;
+	case NID_X9_62_prime192v1:
+	case NID_brainpoolP192r1:
+		return 1;
+	case NID_secp224r1:
+	case NID_brainpoolP224r1:
+		return 2;
+	case NID_X9_62_prime256v1:
+	case NID_brainpoolP256r1:
+		return 3;
+	case NID_brainpoolP320r1:
+		return 4;
+	case NID_secp384r1:
+	case NID_brainpoolP384r1:
+		return 5;
+	case NID_brainpoolP512r1:
+		return 6;
+	case NID_secp521r1:
+		return 7;
+	}
+	return 0;
+}
 
 #endif
diff -Nru libica-3.9.0/src/include/s390_aes.h libica-4.0.0/src/include/s390_aes.h
--- libica-3.9.0/src/include/s390_aes.h	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/include/s390_aes.h	2021-12-06 12:01:54.000000000 +0100
@@ -140,7 +140,7 @@
 	if (rc)
 		return rc;
 
-	stats_increment(ICA_STATS_AES_GCM,
+	stats_increment(ICA_STATS_AES_GCM_128 + aes_directed_fc_stats_ofs(fc),
 			ALGO_HW,
 			(s390_kma_functions[fc].hw_fc &
 			S390_CRYPTO_DIRECTION_MASK) == 0 ?
@@ -164,7 +164,8 @@
 	if (rc)
 		return rc;
 
-	stats_increment(ICA_STATS_AES_CTR, ALGO_HW,
+	stats_increment(ICA_STATS_AES_CTR_128 + aes_directed_fc_stats_ofs(fc),
+			ALGO_HW,
 			 (s390_msa4_functions[fc].hw_fc &
 			 S390_CRYPTO_DIRECTION_MASK) ==
 			 0 ?ENCRYPT:DECRYPT);
@@ -426,7 +427,8 @@
 				     out_data);
 		hardware = ALGO_SW;
 	}
-	stats_increment(ICA_STATS_AES_ECB,
+
+	stats_increment(ICA_STATS_AES_ECB_128 + aes_directed_fc_stats_ofs(fc),
 			hardware,
 			(s390_kmc_functions[fc].hw_fc &
 			S390_CRYPTO_DIRECTION_MASK) == 0 ?
@@ -453,7 +455,8 @@
 				     out_data);
 		hardware = ALGO_SW;
 	}
-	stats_increment(ICA_STATS_AES_CBC,
+
+	stats_increment(ICA_STATS_AES_CBC_128 + aes_directed_fc_stats_ofs(fc),
 			hardware, (s390_kmc_functions[fc].hw_fc &
 			S390_CRYPTO_DIRECTION_MASK) == 0 ?
 			ENCRYPT:DECRYPT);
@@ -506,7 +509,8 @@
 	if (rc)
 		return rc;
 
-	stats_increment(ICA_STATS_AES_CFB, ALGO_HW,
+	stats_increment(ICA_STATS_AES_CFB_128 + aes_directed_fc_stats_ofs(fc),
+			ALGO_HW,
 			(s390_kmc_functions[fc].hw_fc &
 			S390_CRYPTO_DIRECTION_MASK) == 0 ?
 			ENCRYPT:DECRYPT);
@@ -599,7 +603,8 @@
 	if (rc)
 		return rc;
 
-	stats_increment(ICA_STATS_AES_OFB, ALGO_HW,
+	stats_increment(ICA_STATS_AES_OFB_128 + aes_directed_fc_stats_ofs(fc),
+			ALGO_HW,
 			(s390_kmc_functions[fc].hw_fc &
 			S390_CRYPTO_DIRECTION_MASK) == 0 ?
 			ENCRYPT:DECRYPT);
@@ -844,7 +849,8 @@
 	if (rc)
 		return rc;
 
-	stats_increment(ICA_STATS_AES_XTS, ALGO_HW,
+	stats_increment(ICA_STATS_AES_XTS_128 + aes_directed_fc_stats_ofs(fc),
+			ALGO_HW,
 			(s390_kmc_functions[fc].hw_fc &
 			S390_CRYPTO_DIRECTION_MASK) == 0 ?
 			ENCRYPT:DECRYPT);
diff -Nru libica-3.9.0/src/include/s390_cmac.h libica-4.0.0/src/include/s390_cmac.h
--- libica-3.9.0/src/include/s390_cmac.h	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/include/s390_cmac.h	2021-12-06 12:01:54.000000000 +0100
@@ -90,7 +90,9 @@
 		case 26:
 		case 27:
 		case 28:
-			stats_increment(ICA_STATS_AES_CMAC, hw, direction);
+			stats_increment(ICA_STATS_AES_CMAC_128 +
+					aes_directed_fc_stats_ofs(fc),
+					hw, direction);
 			break;
 		default:
 			break;
diff -Nru libica-3.9.0/src/include/s390_crypto.h libica-4.0.0/src/include/s390_crypto.h
--- libica-3.9.0/src/include/s390_crypto.h	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/include/s390_crypto.h	2021-12-06 12:01:54.000000000 +0100
@@ -25,6 +25,11 @@
 
 #include <openssl/opensslv.h>
 
+/* major 4.0: no more exported, now internal */
+int s390_initialize_functionlist(void);
+int s390_get_functionlist(libica_func_list_element *pmech_list,
+			  unsigned int *pmech_list_len);
+
 #ifndef OPENSSL_VERSION_PREREQ
     #if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR)
         #define OPENSSL_VERSION_PREREQ(maj, min)        \
diff -Nru libica-3.9.0/src/include/s390_gcm.h libica-4.0.0/src/include/s390_gcm.h
--- libica-3.9.0/src/include/s390_gcm.h	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/include/s390_gcm.h	2021-12-06 12:01:54.000000000 +0100
@@ -745,9 +745,13 @@
 	if (rc >= 0) {
 		ctx->subkey_provided = 1;
 		if (ctx->direction)
-			stats_increment(ICA_STATS_AES_GCM, ALGO_HW, ENCRYPT);
+			stats_increment(ICA_STATS_AES_GCM_128 +
+					aes_directed_fc_stats_ofs(function_code),
+					ALGO_HW, ENCRYPT);
 		else
-			stats_increment(ICA_STATS_AES_GCM, ALGO_HW, DECRYPT);
+			stats_increment(ICA_STATS_AES_GCM_128 +
+					aes_directed_fc_stats_ofs(function_code),
+					ALGO_HW, DECRYPT);
 		return 0;
 	} else
 		return EIO;
diff -Nru libica-3.9.0/src/include/s390_sha.h libica-4.0.0/src/include/s390_sha.h
--- libica-3.9.0/src/include/s390_sha.h	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/include/s390_sha.h	2021-12-06 12:01:54.000000000 +0100
@@ -104,67 +104,67 @@
 	{S390_CRYPTO_SHA_512, 32, 64, 128, SHA_512_256_DEFAULT_IV},
 };
 
-int s390_sha1(unsigned char *iv, unsigned char *input_data,
+int s390_sha1(unsigned char *iv, const unsigned char *input_data,
 	      unsigned int input_length, unsigned char *output_data,
 	      unsigned int message_part, uint64_t *running_length);
 
-int s390_sha224(unsigned char *iv, unsigned char *input_data,
+int s390_sha224(unsigned char *iv, const unsigned char *input_data,
 		unsigned int input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length);
 
-int s390_sha256(unsigned char *iv, unsigned char *input_data,
+int s390_sha256(unsigned char *iv, const unsigned char *input_data,
 		unsigned int input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length);
 
-int s390_sha384(unsigned char *iv, unsigned char *input_data,
+int s390_sha384(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi);
 
-int s390_sha512(unsigned char *iv, unsigned char *input_data,
+int s390_sha512(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi);
 
-int s390_sha512_224(unsigned char *iv, unsigned char *input_data,
+int s390_sha512_224(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi);
 
-int s390_sha512_256(unsigned char *iv, unsigned char *input_data,
+int s390_sha512_256(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi);
 
-int s390_sha3_224(unsigned char *iv, unsigned char *input_data,
+int s390_sha3_224(unsigned char *iv, const unsigned char *input_data,
 		unsigned int input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length);
 
-int s390_sha3_256(unsigned char *iv, unsigned char *input_data,
+int s390_sha3_256(unsigned char *iv, const unsigned char *input_data,
 		unsigned int input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length);
 
-int s390_sha3_384(unsigned char *iv, unsigned char *input_data,
+int s390_sha3_384(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi);
 
-int s390_sha3_512(unsigned char *iv, unsigned char *input_data,
+int s390_sha3_512(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi);
 
-int s390_shake_128(unsigned char *iv, unsigned char *input_data,
+int s390_shake_128(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data, unsigned int output_length,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi);
 
-int s390_shake_256(unsigned char *iv, unsigned char *input_data,
+int s390_shake_256(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data, unsigned int output_length,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi);
 
-int s390_shake_hw(unsigned char *iv, unsigned char *input_data,
+int s390_shake_hw(unsigned char *iv, const unsigned char *input_data,
 		       uint64_t input_length, unsigned char *output_data, unsigned int output_length,
 		       unsigned int message_part, uint64_t *running_length_lo,
 		       uint64_t *running_length_hi, kimd_functions_t sha_function);
@@ -179,7 +179,7 @@
 	return (n >= SHA_3_224 && n <= SHA_3_512 ? 1 : 0);
 }
 
-static inline int s390_sha_hw(unsigned char *iv, unsigned char *input_data,
+static inline int s390_sha_hw(unsigned char *iv, const unsigned char *input_data,
 		       uint64_t input_length, unsigned char *output_data, unsigned int output_length,
 		       unsigned int message_part, uint64_t *running_length_lo,
 		       uint64_t *running_length_hi, kimd_functions_t sha_function)
diff -Nru libica-3.9.0/src/Makefile.am libica-4.0.0/src/Makefile.am
--- libica-3.9.0/src/Makefile.am	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/Makefile.am	2021-12-06 12:01:54.000000000 +0100
@@ -1,4 +1,4 @@
-VERSION = 3:9:0
+VERSION = 4:0:0
 
 AM_CFLAGS = @FLAGS@
 MAJOR := `echo $(VERSION) | cut -d: -f1`
@@ -10,7 +10,7 @@
 
 lib_LTLIBRARIES = libica.la libica-cex.la
 
-CFLAGS_common = ${AM_CFLAGS} -I${srcdir}/include -I${srcdir}/../include \
+CFLAGS_common = ${AM_CFLAGS} -DNO_SW_FALLBACKS -I${srcdir}/include -I${srcdir}/../include \
 		   -DLIBICA_CONFDIR=\"${sysconfdir}\" \
 		   -fvisibility=hidden -pthread
 LIBS_common = @LIBS@ -lrt -lcrypto -ldl
@@ -36,7 +36,7 @@
 libica_la_LDFLAGS = ${LDFLAGS_common}
 libica_la_SOURCES = ${SOURCES_common}
 
-libica_cex_la_CFLAGS = ${CFLAGS_common} -DNO_CPACF -DNO_SW_FALLBACKS -DLIBNAME=\"libica-cex\"
+libica_cex_la_CFLAGS = ${CFLAGS_common} -DNO_CPACF -DLIBNAME=\"libica-cex\"
 libica_cex_la_CCASFLAGS = ${AM_CFLAGS}
 libica_cex_la_LIBADD = ${LIBS_common}
 libica_cex_la_LDFLAGS = ${LDFLAGS_common}
@@ -64,7 +64,7 @@
 
 bin_PROGRAMS = icainfo icastats icainfo-cex
 
-icainfo_CFLAGS_COMMON = ${AM_CFLAGS} -I${srcdir}/include -I${srcdir}/../include
+icainfo_CFLAGS_COMMON = ${AM_CFLAGS} -DNO_SW_FALLBACKS -I${srcdir}/include -I${srcdir}/../include
 icainfo_LDADD_COMMON = @LIBS@ -lcrypto
 icainfo_SOURCES_COMMON = icainfo.c include/fips.h include/s390_crypto.h \
 		  ../include/ica_api.h
@@ -73,11 +73,11 @@
 icainfo_LDADD = ${icainfo_LDADD_COMMON} libica.la
 icainfo_SOURCES = ${icainfo_SOURCES_COMMON}
 
-icainfo_cex_CFLAGS = ${icainfo_CFLAGS_COMMON} -DNO_CPACF -DNO_SW_FALLBACKS
+icainfo_cex_CFLAGS = ${icainfo_CFLAGS_COMMON} -DNO_CPACF
 icainfo_cex_LDADD = ${icainfo_LDADD_COMMON} libica-cex.la
 icainfo_cex_SOURCES = ${icainfo_SOURCES_COMMON}
 
-icastats_CFLAGS = ${AM_CFLAGS} -I${srcdir}/include -DICASTATS
+icastats_CFLAGS = ${AM_CFLAGS} -I${srcdir}/include -I${srcdir}/../include -DICASTATS
 icastats_LDADD = @LIBS@ -lrt
 icastats_SOURCES = icastats.c icastats_shared.c include/icastats.h
 
diff -Nru libica-3.9.0/src/s390_crypto.c libica-4.0.0/src/s390_crypto.c
--- libica-3.9.0/src/s390_crypto.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/s390_crypto.c	2021-12-06 12:01:54.000000000 +0100
@@ -680,14 +680,20 @@
 #ifdef NO_CPACF
 	pmech_list[x].flags &= ~ICA_FLAG_SHW;
 	/* NO_CPACF also removes sw fallbacks for CPACF based functions, but not
-	 * for card-based functions. */
-	if (pmech_list[x].flags & ICA_FLAG_SW && !(pmech_list[x].flags & ICA_FLAG_DHW)) {
+	 * for card-based functions and RSA keygen, which is only available in sw. */
+	if (pmech_list[x].flags & ICA_FLAG_SW && !(pmech_list[x].flags & ICA_FLAG_DHW) &&
+		pmech_list[x].mech_mode_id != RSA_KEY_GEN_ME &&
+		pmech_list[x].mech_mode_id != RSA_KEY_GEN_CRT) {
 		pmech_list[x].flags &= ~ICA_FLAG_SW;
 	}
 #endif /* NO_CPACF */
 
 #ifdef NO_SW_FALLBACKS
-	pmech_list[x].flags &= ~ICA_FLAG_SW;
+	/* Set SW flag to 0 if we don't have sw fallbacks, except for RSA keygen,
+	 * because there is no hw path for RSA keygen. */
+	if (pmech_list[x].mech_mode_id != RSA_KEY_GEN_ME &&
+		pmech_list[x].mech_mode_id != RSA_KEY_GEN_CRT)
+		pmech_list[x].flags &= ~ICA_FLAG_SW;
 #endif
   }
   return 0;
diff -Nru libica-3.9.0/src/s390_rsa.c libica-4.0.0/src/s390_rsa.c
--- libica-3.9.0/src/s390_rsa.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/s390_rsa.c	2021-12-06 12:01:54.000000000 +0100
@@ -42,24 +42,24 @@
 #endif
 
 #ifndef NO_SW_FALLBACKS
-static unsigned int mod_expo_sw(int arg_length, char *arg, int exp_length,
-				char *exp, int mod_length, char *mod,
-				int *res_length, char *res, BN_CTX *ctx);
-static unsigned int mod_mul_sw(int fc_1_length, char *fc1, int fc_2_length,
-			      char *fc2, int mod_length, char *mod,
-			      int *res_length, char *res, BN_CTX *ctx);
-static unsigned int mod_sw(int arg_length, char *arg, int mod_length,
-			   char *mod, int *res_length, char *res, BN_CTX *ctx);
-static unsigned int add_sw(int aug_length, char *aug, int add_length,
-			   char *add, int *res_length, char *res, BN_CTX *ctx);
-static unsigned int mod_sub_sw(int min_length, char *minu, int sub_length,
-			       char *sub, int mod_length, char *mod,
-			       int *res_length, char *res, BN_CTX * ctx);
-static unsigned int mul_sw(int fc_1_length, char *fc1, int fc_2_length,
-			   char *fc2, int *res_length, char *res, BN_CTX *ctx);
-static unsigned int mod_expo_sw(int arg_length, char *arg, int exp_length,
-				char *exp, int mod_length, char *mod,
-				int *res_length, char *res, BN_CTX *ctx);
+static unsigned int mod_expo_sw(int arg_length, unsigned char *arg, int exp_length,
+				unsigned char *exp, int mod_length, unsigned char *mod,
+				int *res_length, unsigned char *res, BN_CTX *ctx);
+static unsigned int mod_mul_sw(int fc_1_length, unsigned char *fc1, int fc_2_length,
+			      unsigned char *fc2, int mod_length, unsigned char *mod,
+			      int *res_length, unsigned char *res, BN_CTX *ctx);
+static unsigned int mod_sw(int arg_length, unsigned char *arg, int mod_length,
+			   unsigned char *mod, int *res_length, unsigned char *res, BN_CTX *ctx);
+static unsigned int add_sw(int aug_length, unsigned char *aug, int add_length,
+			   unsigned char *add, int *res_length, unsigned char *res, BN_CTX *ctx);
+static unsigned int mod_sub_sw(int min_length, unsigned char *minu, int sub_length,
+			       unsigned char *sub, int mod_length, unsigned char *mod,
+			       int *res_length, unsigned char *res, BN_CTX * ctx);
+static unsigned int mul_sw(int fc_1_length, unsigned char *fc1, int fc_2_length,
+			   unsigned char *fc2, int *res_length, unsigned char *res, BN_CTX *ctx);
+static unsigned int mod_expo_sw(int arg_length, unsigned char *arg, int exp_length,
+				unsigned char *exp, int mod_length, unsigned char *mod,
+				int *res_length, unsigned char *res, BN_CTX *ctx);
 #endif /* NO_SW_FALLBACKS */
 
 #if !OPENSSL_VERSION_PREREQ(3, 0)
@@ -450,9 +450,9 @@
  * Perform a multiprecision modular multiplication using a multiplicand,
  * multiplier and modulus.
  */
-static unsigned int mod_mul_sw(int fc_1_length, char *fc1, int fc_2_length,
-			      char *fc2, int mod_length, char *mod,
-			      int *res_length, char *res, BN_CTX *ctx)
+static unsigned int mod_mul_sw(int fc_1_length, unsigned char *fc1, int fc_2_length,
+			      unsigned char *fc2, int mod_length, unsigned char *mod,
+			      int *res_length, unsigned char *res, BN_CTX *ctx)
 {
 	int rc = 0;
 	int ln = 0;
@@ -587,9 +587,9 @@
  *
  * Returns 0 if successful BN error code if unsuccessful.
  */
-static unsigned int mod_expo_sw(int arg_length, char *arg, int exp_length,
-				char *exp, int mod_length, char *mod,
-				int *res_length, char *res, BN_CTX *ctx)
+static unsigned int mod_expo_sw(int arg_length, unsigned char *arg, int exp_length,
+				unsigned char *exp, int mod_length, unsigned char *mod,
+				int *res_length, unsigned char *res, BN_CTX *ctx)
 {
 	int rc = 0;
 	int ln = 0;
@@ -700,11 +700,11 @@
 	size for ir buffers. Thus the software fallback should be able to
 	handle keys of bigger size, too.
 */
-	char ir1[long_length];
+	unsigned char ir1[long_length];
 	int ir_1_length = sizeof(ir1);
-	char ir2[long_length];
+	unsigned char ir2[long_length];
 	int ir_2_length = sizeof(ir2);
-	char temp[long_length];
+	unsigned char temp[long_length];
 	int temp_length = sizeof(temp);
 
 	if ((ctx = BN_CTX_new()) == NULL) {
@@ -825,8 +825,8 @@
  *
  * Returns 0 if successful, BN error code if unsuccessful
  */
-static unsigned int mod_sw(int arg_length, char *arg, int mod_length,
-			   char *mod, int *res_length, char *res, BN_CTX *ctx)
+static unsigned int mod_sw(int arg_length, unsigned char *arg, int mod_length,
+			   unsigned char *mod, int *res_length, unsigned char *res, BN_CTX *ctx)
 {
 	int rc = 0;
 	int ln = 0;
@@ -906,9 +906,9 @@
  * 5) Convert the result from a BN to a string using BN_bn2bin
  * 6) Call BN_free for the minuend, subtrahend and result BN's
  */
-static unsigned int mod_sub_sw(int min_length, char *minu, int sub_length,
-			       char *sub, int mod_length, char *mod,
-			       int *res_length, char *res, BN_CTX * ctx)
+static unsigned int mod_sub_sw(int min_length, unsigned char *minu, int sub_length,
+			       unsigned char *sub, int mod_length, unsigned char *mod,
+			       int *res_length, unsigned char *res, BN_CTX * ctx)
 {
 	int rc = 0;
 	int ln = 0;
@@ -1010,8 +1010,8 @@
  * 4) Convert the result from a BN to a string using BN_bn2bin
  * 5) Call BN_free for the augend, addend and result BN's
 */
-static unsigned int add_sw(int aug_length, char *aug, int add_length,
-			   char *add, int *res_length, char *res, BN_CTX *ctx)
+static unsigned int add_sw(int aug_length, unsigned char *aug, int add_length,
+			   unsigned char *add, int *res_length, unsigned char *res, BN_CTX *ctx)
 {
 	int rc = 0;
 	int ln = 0;
@@ -1079,8 +1079,8 @@
  *
  * Returns 0 if successful, BN error code if unsuccessful
  */
-static unsigned int mul_sw(int fc_1_length, char *fc1, int fc_2_length,
-			   char *fc2, int *res_length, char *res, BN_CTX *ctx)
+static unsigned int mul_sw(int fc_1_length, unsigned char *fc1, int fc_2_length,
+			   unsigned char *fc2, int *res_length, unsigned char *res, BN_CTX *ctx)
 {
 	int rc = 0;
 	int ln = 0;
diff -Nru libica-3.9.0/src/s390_sha.c libica-4.0.0/src/s390_sha.c
--- libica-3.9.0/src/s390_sha.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/src/s390_sha.c	2021-12-06 12:01:54.000000000 +0100
@@ -28,7 +28,7 @@
 #include "init.h"
 #include "icastats.h"
 
-int s390_sha1(unsigned char *iv, unsigned char *input_data,
+int s390_sha1(unsigned char *iv, const unsigned char *input_data,
 	      unsigned int input_length, unsigned char *output_data,
 	      unsigned int message_part, uint64_t *running_length)
 {
@@ -44,7 +44,7 @@
 	return rc;
 }
 
-int s390_sha224(unsigned char *iv, unsigned char *input_data,
+int s390_sha224(unsigned char *iv, const unsigned char *input_data,
 		unsigned int input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length)
 {
@@ -60,7 +60,7 @@
 	return rc;
 }
 
-int s390_sha256(unsigned char *iv, unsigned char *input_data,
+int s390_sha256(unsigned char *iv, const unsigned char *input_data,
 		unsigned int input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length)
 {
@@ -75,7 +75,7 @@
 
 	return rc;
 }
-int s390_sha384(unsigned char *iv, unsigned char *input_data,
+int s390_sha384(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi)
@@ -93,7 +93,7 @@
 	return rc;
 }
 
-int s390_sha512(unsigned char *iv, unsigned char *input_data,
+int s390_sha512(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi)
@@ -111,7 +111,7 @@
 	return rc;
 }
 
-int s390_sha512_224(unsigned char *iv, unsigned char *input_data,
+int s390_sha512_224(unsigned char *iv, const unsigned char *input_data,
 		    uint64_t input_length, unsigned char *output_data,
 		    unsigned int message_part, uint64_t *running_length_lo,
 		    uint64_t *running_length_hi)
@@ -129,7 +129,7 @@
 	return rc;
 }
 
-int s390_sha512_256(unsigned char *iv, unsigned char *input_data,
+int s390_sha512_256(unsigned char *iv, const unsigned char *input_data,
 		    uint64_t input_length, unsigned char *output_data,
 		    unsigned int message_part, uint64_t *running_length_lo,
 		    uint64_t *running_length_hi)
@@ -147,7 +147,7 @@
 	return rc;
 }
 
-int s390_sha3_224(unsigned char *iv, unsigned char *input_data,
+int s390_sha3_224(unsigned char *iv, const unsigned char *input_data,
 		unsigned int input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length)
 {
@@ -163,7 +163,7 @@
 	return rc;
 }
 
-int s390_sha3_256(unsigned char *iv, unsigned char *input_data,
+int s390_sha3_256(unsigned char *iv, const unsigned char *input_data,
 		unsigned int input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length)
 {
@@ -179,7 +179,7 @@
 	return rc;
 }
 
-int s390_sha3_384(unsigned char *iv, unsigned char *input_data,
+int s390_sha3_384(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi)
@@ -197,7 +197,7 @@
 	return rc;
 }
 
-int s390_sha3_512(unsigned char *iv, unsigned char *input_data,
+int s390_sha3_512(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi)
@@ -215,7 +215,7 @@
 	return rc;
 }
 
-int s390_shake_128(unsigned char *iv, unsigned char *input_data,
+int s390_shake_128(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data, unsigned int output_length,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi)
@@ -232,7 +232,7 @@
 	return rc;
 }
 
-int s390_shake_256(unsigned char *iv, unsigned char *input_data,
+int s390_shake_256(unsigned char *iv, const unsigned char *input_data,
 		uint64_t input_length, unsigned char *output_data, unsigned int output_length,
 		unsigned int message_part, uint64_t *running_length_lo,
 		uint64_t *running_length_hi)
diff -Nru libica-3.9.0/test/aes_128_test.c libica-4.0.0/test/aes_128_test.c
--- libica-3.9.0/test/aes_128_test.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/test/aes_128_test.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,284 +0,0 @@
-/* This program is released under the Common Public License V1.0
- *
- * You should have received a copy of Common Public License V1.0 along with
- * with this program.
- */
-
-/* Copyright IBM Corp. 2005, 2009, 2011 */
-#include <fcntl.h>
-#include <sys/errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-#include "ica_api.h"
-#include <stdlib.h>
-#include <openssl/aes.h>
-#include "testcase.h"
-
-unsigned char NIST_KEY1[] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-};
-
-unsigned char NIST_TEST_DATA[] = {
-	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
-};
-
-unsigned char NIST_TEST_RESULT[] = {
-	0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
-	0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a,
-};
-
-int test_aes128_new_api(int mode)
-{
-	ica_aes_vector_t iv;
-	unsigned char key[AES_KEY_LEN128];
-	int rc = 0;
-	unsigned char dec_text[sizeof(NIST_TEST_DATA)],
-		      enc_text[sizeof(NIST_TEST_DATA)];
-
-	bzero(dec_text, sizeof(dec_text));
-	bzero(enc_text, sizeof(enc_text));
-	bzero(iv, sizeof(iv));
-	bcopy(NIST_KEY1, key, sizeof(NIST_KEY1));
-
-	rc = ica_aes_encrypt(mode, sizeof(NIST_TEST_DATA), NIST_TEST_DATA, &iv,
-			     AES_KEY_LEN128, key, enc_text);
-	if (rc) {
-		VV_(printf("key \n"));
-		dump_array((unsigned char *) key, sizeof(NIST_KEY1));
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("test iv\n"));
-		dump_array((unsigned char *) &iv, sizeof(ica_aes_vector_t));
-		VV_(printf("key\n"));
-		dump_array((unsigned char *) key, AES_KEY_LEN128);
-		VV_(printf("ica_aes_encrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	if (memcmp(enc_text, NIST_TEST_RESULT, sizeof(NIST_TEST_RESULT)) != 0) {
-		VV_(printf("key \n"));
-		dump_array((unsigned char *) key, sizeof(NIST_KEY1));
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("test iv\n"));
-		dump_array((unsigned char *) &iv, sizeof(ica_aes_vector_t));
-		VV_(printf("key\n"));
-		dump_array((unsigned char *) key, AES_KEY_LEN128);
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) enc_text, sizeof(enc_text));
-		VV_(printf("This does NOT match the known result.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Yep, it's what it should be.\n"));
-	}
-
-	bzero(iv, sizeof(iv));
-	rc = ica_aes_decrypt(mode, sizeof(enc_text), enc_text, &iv,
-			     AES_KEY_LEN128, key, dec_text);
-	if (rc) {
-		VV_(printf("key \n"));
-		dump_array((unsigned char *) key, sizeof(NIST_KEY1));
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("test iv\n"));
-		dump_array((unsigned char *) &iv, sizeof(ica_aes_vector_t));
-		VV_(printf("key\n"));
-		dump_array((unsigned char *) key, AES_KEY_LEN128);
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) enc_text, sizeof(enc_text));
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array((unsigned char *) dec_text, sizeof(dec_text));
-		VV_(printf("ica_aes_decrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	if (memcmp(dec_text, NIST_TEST_DATA, sizeof(NIST_TEST_DATA)) != 0) {
-		VV_(printf("This does NOT match the original data.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Successful!\n"));
-		VV_(printf("key \n"));
-		dump_array((unsigned char *) key, sizeof(NIST_KEY1));
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("test iv\n"));
-		dump_array((unsigned char *) &iv, sizeof(ica_aes_vector_t));
-		VV_(printf("key\n"));
-		dump_array((unsigned char *) key, AES_KEY_LEN128);
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) enc_text, sizeof(enc_text));
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array((unsigned char *) dec_text, sizeof(dec_text));
-	}
-
-// Test 2
-
-	rc = 0;
-	bzero(dec_text, sizeof(dec_text));
-	bzero(enc_text, sizeof(enc_text));
-	bzero(iv, sizeof(iv));
-	bzero(key, sizeof(key));
-
-	unsigned int length = 64;
-	unsigned char *decrypt = malloc(length);
-	unsigned char *encrypt = malloc(length);
-	unsigned char *original = malloc(length);
-	ica_aes_key_len_128_t key2;
-
-	rc = ica_random_number_generate(length, original);
-	if (rc) {
-		VV_(printf("ica_random_number_generate returned rc = %i\n", rc));
-		return TEST_FAIL;
-	}
-
-	rc = ica_random_number_generate(AES_KEY_LEN128, (unsigned char *) &key2);
-	if (rc) {
-		VV_(printf("ica_random_number_generate returned rc = %i\n", rc));
-		return TEST_FAIL;
-	}
-
-	rc = ica_aes_encrypt(mode, length, original, &iv, AES_KEY_LEN128, (unsigned char *) &key2,
-			     (unsigned char *) encrypt);
-	if (rc) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) original, length);
-		VV_(printf("KEY: \n"));
-		dump_array((unsigned char *) &key2, AES_KEY_LEN128);
-		VV_(printf("ica_aes_encrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	if (memcmp(encrypt, original, length) == 0) {
-		VV_(printf("Encrypt and original are the same.\n"));
-		return TEST_FAIL;
-	}
-
-	bzero(iv, sizeof(iv));
-	rc = ica_aes_decrypt(mode, length, encrypt, &iv, AES_KEY_LEN128,
-			     (unsigned char *) &key2, decrypt);
-	if (rc) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) original, length);
-		VV_(printf("KEY: \n"));
-		dump_array((unsigned char *) &key2, AES_KEY_LEN128);
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) encrypt, length);
-		VV_(printf("ica_aes_decrypt failed with errno %d (0x%x).\n", rc, rc));
-		goto free;
-	}
-
-	if (memcmp(decrypt, original, length) != 0) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) original, length);
-		VV_(printf("KEY: \n"));
-		dump_array((unsigned char *) &key2, AES_KEY_LEN128);
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) encrypt, length);
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array((unsigned char *) decrypt, length);
-		VV_(printf("This does NOT match the original data.\n"));
-		rc = -1;
-		goto free;
-	}
-
-	if(memcmp(decrypt, encrypt, length) == 0) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) original, length);
-		VV_(printf("KEY: \n"));
-		dump_array((unsigned char *) &key2, AES_KEY_LEN128);
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) encrypt, length);
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array((unsigned char *) decrypt, length);
-		VV_(printf("decrypt and encrypt are the same\n"));
-		rc = -1;
-		goto free;
-
-	} else {
-		VV_(printf("Successful!\n"));
-	}
-free:
-	free(original);
-	free(encrypt);
-	free(decrypt);
-
-	if (rc)
-		return TEST_FAIL;
-
-	return TEST_SUCC;
-}
-
-/*
- * Performs ECB and CBC tests.
- */
-int main(int argc, char **argv)
-{
-#ifdef NO_CPACF
-	UNUSED(argc);
-	UNUSED(argv);
-	printf("Skipping AES-128 test, because CPACF support disabled via config option.\n");
-	return TEST_SKIP;
-#else
-	unsigned int mode = 0;
-	int rc = 0;
-	int error_count = 0;
-
-	if (argc > 1) {
-		if (strstr(argv[1], "ecb"))
-			mode = MODE_ECB;
-		if (strstr(argv[1], "cbc"))
-			mode = MODE_CBC;
-	}
-
-	if (argc > 2) {
-		if (strstr(argv[2], "ecb"))
-			mode = MODE_ECB;
-		if (strstr(argv[2], "cbc"))
-			mode = MODE_CBC;
-	}
-
-	set_verbosity(argc, argv);
-
-	if (mode != 0 && mode != MODE_ECB && mode != MODE_CBC) {
-		printf("Usage: %s [ ecb | cbc ]\n", argv[0]);
-		return TEST_ERR;
-	}
-
-	if (!mode) {
-	/* This is the standard loop that will perform all testcases */
-		mode = 2;
-		while (mode) {
-			rc = test_aes128_new_api(mode);
-			if (rc) {
-				error_count++;
-				V_(printf ("test_aes_new_api mode = %i failed \n", mode));
-			}
-			else {
-				V_(printf ("test_aes_new_api mode = %i finished.\n", mode));
-			}
-			mode--;
-		}
-		if (error_count)
-			printf("%i AES-128-ECB/CBC tests failed.\n", error_count);
-		else
-			printf("All AES-128-ECB/CBC tests passed.\n");
-	} else {
-	/* Perform only either in ECB or CBC mode */
-		rc = test_aes128_new_api(mode);
-		if (rc)
-			printf ("test_aes_new_api mode = %i failed \n", mode);
-		else {
-			printf ("test_aes_new_api mode = %i finished.\n", mode);
-		}
-	}
-
-	if (rc)
-		return TEST_FAIL;
-
-	return TEST_SUCC;
-#endif /* NO_CPACF */
-}
diff -Nru libica-3.9.0/test/aes_192_test.c libica-4.0.0/test/aes_192_test.c
--- libica-3.9.0/test/aes_192_test.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/test/aes_192_test.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,163 +0,0 @@
-/* This program is released under the Common Public License V1.0
- *
- * You should have received a copy of Common Public License V1.0 along with
- * with this program.
- */
-
-/* Copyright IBM Corp. 2005, 2009, 2011 */
-#include <fcntl.h>
-#include <sys/errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include "ica_api.h"
-#include "testcase.h"
-
-unsigned char NIST_KEY2[] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-};
-
-unsigned char NIST_TEST_DATA[] = {
-	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
-};
-
-unsigned char NIST_TEST_RESULT[] = {
-	0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
-	0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91,
-};
-
-int test_aes192_new_api(int mode)
-{
-	ica_aes_vector_t iv;
-	ica_aes_key_len_192_t key;
-	int rc = 0;
-	unsigned char dec_text[sizeof(NIST_TEST_DATA)],
-		      enc_text[sizeof(NIST_TEST_DATA)];
-
-	bzero(dec_text, sizeof(dec_text));
-	bzero(enc_text, sizeof(enc_text));
-	bzero(iv, sizeof(iv));
-	bcopy(NIST_KEY2, key, sizeof(NIST_KEY2));
-
-	rc = ica_aes_encrypt(mode, sizeof(NIST_TEST_DATA), NIST_TEST_DATA, &iv,
-			     AES_KEY_LEN192, (unsigned char *) &key, enc_text);
-	if (rc) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char*)NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("ica_aes_encrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	if (memcmp(enc_text, NIST_TEST_RESULT, sizeof(NIST_TEST_RESULT)) != 0) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char*)NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char*)enc_text, sizeof(enc_text));
-		VV_(printf("This does NOT match the known result.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Yep, it's what it should be.\n"));
-	}
-
-	bzero(iv, sizeof(iv));
-	rc = ica_aes_decrypt(mode, sizeof(enc_text), enc_text, &iv,
-			     AES_KEY_LEN192, (unsigned char *) &key, dec_text);
-	if (rc != 0) {
-		VV_(printf("ica_aes_decrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	if (memcmp(dec_text, NIST_TEST_DATA, sizeof(NIST_TEST_DATA)) != 0) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char*)NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char*)enc_text, sizeof(enc_text));
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array((unsigned char*)dec_text, sizeof(dec_text));
-		VV_(printf("This does NOT match the original data.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Successful!\n"));
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char*)NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char*)enc_text, sizeof(enc_text));
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array((unsigned char*)dec_text, sizeof(dec_text));
-	}
-
-	return TEST_SUCC;
-}
-
-/*
- * Performs ECB and CBC tests.
- */
-int main(int argc, char **argv)
-{
-#ifdef NO_CPACF
-	UNUSED(argc);
-	UNUSED(argv);
-	printf("Skipping AES-192 test, because CPACF support disabled via config option.\n");
-	return TEST_SKIP;
-#else
-	unsigned int mode = 0;
-	int rc = 0;
-	int error_count = 0;
-
-	if (argc > 1) {
-		if (strstr(argv[1], "ecb"))
-			mode = MODE_ECB;
-		if (strstr(argv[1], "cbc"))
-			mode = MODE_CBC;
-	}
-	if (argc > 2) {
-		if (strstr(argv[2], "ecb"))
-			mode = MODE_ECB;
-		if (strstr(argv[2], "cbc"))
-			mode = MODE_CBC;
-	}
-
-	set_verbosity(argc, argv);
-
-	if (mode != 0 && mode != MODE_ECB && mode != MODE_CBC) {
-		printf("Usage: %s [ ecb | cbc ]\n", argv[0]);
-		return TEST_ERR;
-	}
-
-	if (!mode) {
-	/* This is the standard loop that will perform all testcases */
-		mode = 2;
-		while (mode) {
-			rc = test_aes192_new_api(mode);
-			if (rc) {
-				error_count++;
-				V_(printf ("test_aes_new_api mode = %i failed \n", mode));
-			} else {
-				V_(printf ("test_aes_new_api mode = %i finished.\n", mode));
-			}
-			mode--;
-		}
-		if (error_count)
-			printf("%i AES-192-ECB/CBC tests failed.\n", error_count);
-		else
-			printf("All AES-192-ECB/CBC tests passed.\n");
-	} else {
-	/* Perform only either in ECB or CBC mode */
-		rc = test_aes192_new_api(mode);
-		if (rc)
-			printf ("test_aes_new_api mode = %i failed \n", mode);
-		else {
-			printf ("test_aes_new_api mode = %i finished.\n", mode);
-		}
-	}
-
-	if (rc)
-		return TEST_FAIL;
-
-	return TEST_SUCC;
-#endif /* NO_CPACF */
-}
diff -Nru libica-3.9.0/test/aes_256_test.c libica-4.0.0/test/aes_256_test.c
--- libica-3.9.0/test/aes_256_test.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/test/aes_256_test.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,162 +0,0 @@
-/* This program is released under the Common Public License V1.0
- *
- * You should have received a copy of Common Public License V1.0 along with
- * with this program.
- */
-
-/* Copyright IBM Corp. 2005, 2009, 2011 */
-#include <fcntl.h>
-#include <sys/errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include "ica_api.h"
-#include "testcase.h"
-
-unsigned char NIST_KEY3[] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-};
-
-unsigned char NIST_TEST_DATA[] = {
-	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
-};
-
-unsigned char NIST_TEST_RESULT[] = {
-	0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
-	0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89,
-};
-
-int test_aes256_new_api(int mode)
-{
-	ica_aes_vector_t iv;
-	unsigned char key[AES_KEY_LEN256];
-	int rc = 0;
-	unsigned char dec_text[sizeof(NIST_TEST_DATA)],
-		      enc_text[sizeof(NIST_TEST_DATA)];
-
-	bzero(dec_text, sizeof(dec_text));
-	bzero(enc_text, sizeof(enc_text));
-	bzero(iv, sizeof(iv));
-	bcopy(NIST_KEY3, key, sizeof(NIST_KEY3));
-
-	rc = ica_aes_encrypt(mode, sizeof(NIST_TEST_DATA), NIST_TEST_DATA, &iv,
-			     AES_KEY_LEN256, key, enc_text);
-	if (rc) {
-		VV_(printf("ica_aes_encrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	if (memcmp(enc_text, NIST_TEST_RESULT, sizeof(NIST_TEST_RESULT)) != 0) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) enc_text, sizeof(enc_text));
-		VV_(printf("This does NOT match the known result.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Yep, it's what it should be.\n"));
-	}
-
-	bzero(iv, sizeof(iv));
-	rc = ica_aes_decrypt(mode, sizeof(enc_text), enc_text, &iv,
-			     AES_KEY_LEN256, key, dec_text);
-	if (rc) {
-		VV_(printf("ica_aes_decrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	if (memcmp(dec_text, NIST_TEST_DATA, sizeof(NIST_TEST_DATA)) != 0) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) enc_text, sizeof(enc_text));
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array((unsigned char *) dec_text, sizeof(dec_text));
-		VV_(printf("This does NOT match the original data.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array((unsigned char *) NIST_TEST_DATA, sizeof(NIST_TEST_DATA));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array((unsigned char *) enc_text, sizeof(enc_text));
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array((unsigned char *) dec_text, sizeof(dec_text));
-		VV_(printf("Successful!\n"));
-	}
-
-	return TEST_SUCC;
-}
-
-/*
- * Performs ECB and CBC tests.
- */
-int main(int argc, char **argv)
-{
-#ifdef NO_CPACF
-	UNUSED(argc);
-	UNUSED(argv);
-	printf("Skipping AES-256 test, because CPACF support disabled via config option.\n");
-	return TEST_SKIP;
-#else
-	unsigned int mode = 0;
-	int rc = 0;
-	int error_count = 0;
-
-	if (argc > 1) {
-		if (strstr(argv[1], "ecb"))
-			mode = MODE_ECB;
-		if (strstr(argv[1], "cbc"))
-			mode = MODE_CBC;
-	}
-	if (argc > 2) {
-		if (strstr(argv[2], "ecb"))
-			mode = MODE_ECB;
-		if (strstr(argv[2], "cbc"))
-			mode = MODE_CBC;
-	}
-
-	set_verbosity(argc, argv);
-
-	if (mode != 0 && mode != MODE_ECB && mode != MODE_CBC) {
-		printf("Usage: %s [ ecb | cbc ]\n", argv[0]);
-		return TEST_ERR;
-	}
-
-	if (!mode) {
-	/* This is the standard loop that will perform all testcases */
-		mode = 2;
-		while (mode) {
-			rc = test_aes256_new_api(mode);
-			if (rc) {
-				error_count++;
-				V_(printf ("test_aes_new_api mode = %i failed \n", mode));
-			}
-			else {
-				V_(printf ("test_aes_new_api mode = %i finished.\n", mode));
-			}
-			mode--;
-		}
-		if (error_count)
-			printf("%i AES-256-ECB/CBC tests failed.\n", error_count);
-		else
-			printf("All AES-256-ECB/CBC tests passed.\n");
-	} else {
-	/* Perform only either in ECB or CBC mode */
-		rc = test_aes256_new_api(mode);
-		if (rc)
-			printf("test_aes_new_api mode = %i failed \n", mode);
-		else
-			printf("test_aes_new_api mode = %i finished.\n", mode);
-	}
-
-	if (rc)
-		return TEST_FAIL;
-
-	return TEST_SUCC;
-#endif /* NO_CPACF */
-}
diff -Nru libica-3.9.0/test/des_test.c libica-4.0.0/test/des_test.c
--- libica-3.9.0/test/des_test.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/test/des_test.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,157 +0,0 @@
-/* This program is released under the Common Public License V1.0
- *
- * You should have received a copy of Common Public License V1.0 along with
- * with this program.
- */
-
-/* Copyright IBM Corp. 2001, 2009, 2011 */
-#include <fcntl.h>
-#include <sys/errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include "ica_api.h"
-#include "testcase.h"
-
-const int cipher_buf_length = 8;
-
-unsigned char NIST_KEY1[] =
-		  { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 };
-
-unsigned char NIST_TEST_DATA[] =
-		  { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 };
-
-unsigned char NIST_TEST_RESULT[] =
-		  { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b };
-
-int test_des_new_api(int mode)
-{
-	ica_des_vector_t iv;
-	ica_des_key_single_t key;
-	int rc = 0;
-	unsigned char dec_text[sizeof NIST_TEST_DATA],
-		      enc_text[sizeof NIST_TEST_DATA];
-
-	bzero(dec_text, sizeof dec_text);
-	bzero(enc_text, sizeof enc_text);
-	bzero(iv, sizeof iv);
-	bcopy(NIST_KEY1, key, sizeof NIST_KEY1);
-
-	rc = ica_des_encrypt(mode, sizeof NIST_TEST_DATA, NIST_TEST_DATA, &iv,
-			     &key, enc_text);
-	if (rc) {
-		VV_(printf("\nOriginal data:\n");
-		dump_array(NIST_TEST_DATA, sizeof NIST_TEST_DATA));
-		VV_(printf("ica_des_encrypt failed with errno %d (0x%x).\n", rc, rc));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array(enc_text, sizeof enc_text);
-		return TEST_FAIL;
-	}
-
-	if (memcmp(enc_text, NIST_TEST_RESULT, sizeof NIST_TEST_RESULT) != 0) {
-		VV_(printf("This does NOT match the known result.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Yep, it's what it should be.\n"));
-	}
-
-	bzero(iv, sizeof iv);
-	rc = ica_des_decrypt(mode, sizeof enc_text, enc_text, &iv, &key,
-			     dec_text);
-	if (rc) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array(NIST_TEST_DATA, sizeof NIST_TEST_DATA);
-		VV_(printf("ica_des_encrypt failed with errno %d (0x%x).\n", rc, rc));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array(enc_text, sizeof enc_text);
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array(dec_text, sizeof dec_text);
-		VV_(printf("ica_des_decrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	if (memcmp(dec_text, NIST_TEST_DATA, sizeof NIST_TEST_DATA) != 0) {
-		VV_(printf("\nOriginal data:\n"));
-		dump_array(NIST_TEST_DATA, sizeof NIST_TEST_DATA);
-		VV_(printf("ica_des_encrypt failed with errno %d (0x%x).\n", rc, rc));
-		VV_(printf("\nEncrypted data:\n"));
-		dump_array(enc_text, sizeof enc_text);
-		VV_(printf("\nDecrypted data:\n"));
-		dump_array(dec_text, sizeof dec_text);
-		VV_(printf("This does NOT match the original data.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Successful!\n"));
-	}
-
-	return TEST_SUCC;
-}
-
-int main(int argc, char **argv)
-{
-#ifdef NO_CPACF
-	UNUSED(argc);
-	UNUSED(argv);
-	printf("Skipping DES test, because CPACF support disabled via config option.\n");
-	return TEST_SKIP;
-#else
-	unsigned int mode = 0;
-	int rc = 0;
-	int error_count = 0;
-
-	set_verbosity(argc, argv);
-
-#ifdef ICA_FIPS
-	if (ica_fips_status() & ICA_FIPS_MODE) {
-		printf("All DES new api tests skipped."
-		    " (DES not FIPS approved)\n");
-		return TEST_SKIP;
-	}
-#endif /* ICA_FIPS */
-
-	if (argc > 1) {
-		if (strstr(argv[1], "ecb"))
-			mode = MODE_ECB;
-		if (strstr(argv[1], "cbc"))
-			mode = MODE_CBC;
-		V_(printf("mode = %i \n", mode));
-	}
-
-	if (mode != 0 && mode != MODE_ECB && mode != MODE_CBC) {
-		printf("Usage: %s [ ecb | cbc ]\n", argv[0]);
-		return TEST_ERR;
-	}
-	if (!mode) {
-	/* This is the standard loop that will perform all testcases */
-		mode = 2;
-		while (mode) {
-			rc = test_des_new_api(mode);
-			if (rc) {
-				error_count++;
-				V_(printf ("test_des_new_api mode = %i failed \n", mode));
-			}
-			else {
-				V_(printf ("test_des_new_api mode = %i finished.\n", mode));
-			}
-			mode--;
-		}
-		if (error_count)
-			printf("%i tests failed.\n", error_count);
-		else
-			printf("All tests passed.\n");
-	} else {
-	/* Perform only either in ECB or CBC mode */
-		rc = test_des_new_api(mode);
-		if (rc)
-			printf ("test_des_new_api mode = %i failed \n", mode);
-		else
-			printf ("test_des_new_api mode = %i finished.\n", mode);
-	}
-
-	if (rc)
-		return TEST_FAIL;
-
-	return TEST_SUCC;
-#endif /* NO_CPACF */
-}
diff -Nru libica-3.9.0/test/get_functionlist_cex_test.c libica-4.0.0/test/get_functionlist_cex_test.c
--- libica-3.9.0/test/get_functionlist_cex_test.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/test/get_functionlist_cex_test.c	2021-12-06 12:01:54.000000000 +0100
@@ -23,11 +23,14 @@
  * For libica-cex, all CPACF-related functions and software fallbacks are
  * unavailable. Only RSA-ME, RSA-CRT, ECDH, ECDSA, and EC keygen may be
  * available via a CCA card. As we don't check for a CCA card here, just
- * skip these.
+ * skip these. Also RSA keygen is an exception: it's no sw fallback, but
+ * a sw implementation.
  */
 int cex_check_ok(libica_func_list_element func)
 {
 	switch (func.mech_mode_id) {
+	case RSA_KEY_GEN_ME:
+	case RSA_KEY_GEN_CRT:
 	case RSA_ME:
 	case RSA_CRT:
 	case EC_DH:
@@ -64,6 +67,12 @@
 	V_(printf("Retrieved number of elements: %d\n", count));
 
 	libica_func_list = malloc(sizeof(libica_func_list_element) * count);
+	if (!libica_func_list) {
+		V_(printf("Cannot malloc libica_func_list\n"));
+		failed++;
+		goto done;
+	}
+
 	rc = ica_get_functionlist(libica_func_list, &count);
 	if (rc) {
 		V_(printf("Retrieving function list for libica-cex failed with rc=%02x\n", rc));
@@ -88,6 +97,9 @@
 		failed++;
 	}
 
+done:
+	free(libica_func_list);
+
 	if (failed) {
 		printf("ica_get_functionlist tests for libica-cex failed.\n");
 		return TEST_FAIL;
diff -Nru libica-3.9.0/test/get_functionlist_test.c libica-4.0.0/test/get_functionlist_test.c
--- libica-3.9.0/test/get_functionlist_test.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/test/get_functionlist_test.c	2021-12-06 12:01:54.000000000 +0100
@@ -38,6 +38,12 @@
 	V_(printf("Retrieved number of elements: %d\n", count));
 
 	libica_func_list = malloc(sizeof(libica_func_list_element) * count);
+	if (!libica_func_list) {
+		V_(printf("Cannot malloc libica_func_list\n"));
+		failed++;
+		goto done;
+	}
+
 	rc = ica_get_functionlist(libica_func_list, &count);
 	if (rc) {
 		V_(printf("Retrieving function list failed with rc=%02x\n", rc));
@@ -58,6 +64,9 @@
 		failed++;
 	}
 
+done:
+	free(libica_func_list);
+
 	if (failed) {
 		printf("ica_get_functionlist tests failed.\n");
 		return TEST_FAIL;
diff -Nru libica-3.9.0/test/Makefile.am libica-4.0.0/test/Makefile.am
--- libica-3.9.0/test/Makefile.am	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/test/Makefile.am	2021-12-06 12:01:54.000000000 +0100
@@ -7,21 +7,16 @@
 rng_test \
 drbg_test \
 drbg_birthdays_test.pl \
-des_test \
 des_ecb_test \
 des_cbc_test \
 des_ctr_test \
 des_cfb_test \
 des_ofb_test \
-tdes_test \
 tdes_ecb_test \
 tdes_cbc_test \
 tdes_ctr_test \
 tdes_cfb_test \
 tdes_ofb_test \
-aes_128_test \
-aes_192_test \
-aes_256_test \
 aes_ecb_test \
 aes_cbc_test \
 aes_ctr_test \
@@ -68,17 +63,17 @@
 TESTS_ENVIRONMENT = export LD_LIBRARY_PATH=${builddir}/../src/.libs/ \
 			   PATH=${builddir}/../src/:$$PATH \
 			   LIBICA_TESTDATA=${srcdir}/testdata/;
-AM_CFLAGS = @FLAGS@ -I${srcdir}/../include/ -I${srcdir}/../src/include/
+AM_CFLAGS = @FLAGS@ -DNO_SW_FALLBACKS -I${srcdir}/../include/ -I${srcdir}/../src/include/
 LDADD = @LIBS@ ${top_builddir}/src/.libs/libica.so -lcrypto -lpthread
 
 get_functionlist_cex_test_SOURCES = get_functionlist_cex_test.c 
 get_functionlist_cex_test_LDADD = @LIBS@ ${top_builddir}/src/.libs/libica-cex.so -lcrypto -lpthread
 
 check_PROGRAMS = fips_test icastats_test get_functionlist_test \
-get_version_test rng_test drbg_test drbg_birthdays_test des_test \
+get_version_test rng_test drbg_test drbg_birthdays_test \
 des_ecb_test des_cbc_test des_ctr_test des_cfb_test des_ofb_test \
-tdes_test tdes_ecb_test tdes_cbc_test tdes_ctr_test tdes_cfb_test \
-tdes_ofb_test aes_128_test aes_192_test aes_256_test aes_ecb_test \
+tdes_ecb_test tdes_cbc_test tdes_ctr_test tdes_cfb_test \
+tdes_ofb_test aes_ecb_test \
 aes_cbc_test aes_ctr_test aes_cfb_test aes_ofb_test aes_xts_test \
 aes_gcm_test aes_gcm_kma_test cbccs_test ccm_test cmac_test sha_test \
 sha1_test sha256_test sha3_224_test sha3_256_test sha3_384_test \
diff -Nru libica-3.9.0/test/tdes_test.c libica-4.0.0/test/tdes_test.c
--- libica-3.9.0/test/tdes_test.c	2021-10-13 16:00:38.000000000 +0200
+++ libica-4.0.0/test/tdes_test.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,148 +0,0 @@
-/* This program is released under the Common Public License V1.0
- *
- * You should have received a copy of Common Public License V1.0 along with
- * with this program.
- */
-
-/* Copyright IBM Corp. 2001, 2009, 2011 */
-#include <fcntl.h>
-#include <sys/errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include "ica_api.h"
-#include "testcase.h"
-
-unsigned char KEY1[] =
-		  { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 };
-
-unsigned char KEY2[] =
-		  { 0x8c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 };
-
-unsigned char KEY3[] =
-		  { 0x9c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 };
-
-unsigned char TEST_DATA[] =
-		  { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 };
-
-unsigned char TEST_RESULT[] =
-		  { 0x90, 0x9c, 0xbc, 0x01, 0xc5, 0x1f, 0x09, 0x60 };
-
-int test_3des_new_api(int mode)
-{
-	ica_des_vector_t iv;
-	ica_des_key_triple_t key;
-	int rc = 0;
-	unsigned char dec_text[sizeof(TEST_DATA)],
-		      enc_text[sizeof(TEST_DATA)];
-
-	bzero(dec_text, sizeof(dec_text));
-	bzero(enc_text, sizeof(enc_text));
-	bzero(iv, sizeof(iv));
-	bcopy(KEY1, key.key1, sizeof(KEY1));
-	bcopy(KEY2, key.key2, sizeof(KEY2));
-	bcopy(KEY3, key.key3, sizeof(KEY3));
-
-	VV_(printf("\nOriginal data:\n"));
-	dump_array(TEST_DATA, sizeof(TEST_DATA));
-
-	rc = ica_3des_encrypt(mode, sizeof(TEST_DATA), TEST_DATA,
-			      &iv, &key, enc_text);
-	if (rc != 0) {
-		VV_(printf("ica_3des_encrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	VV_(printf("\nEncrypted data:\n"));
-	dump_array(enc_text, sizeof(enc_text));
-	if (memcmp(enc_text, TEST_RESULT, sizeof TEST_RESULT) != 0) {
-		VV_(printf("This does NOT match the known result.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Yep, it's what it should be.\n"));
-	}
-
-	bzero(iv, sizeof(iv));
-	rc = ica_3des_decrypt(mode, sizeof(enc_text), enc_text,
-			    &iv, &key, dec_text);
-	if (rc != 0) {
-		VV_(printf("ica_3des_decrypt failed with errno %d (0x%x).\n", rc, rc));
-		return TEST_FAIL;
-	}
-
-	VV_(printf("\nDecrypted data:\n"));
-	dump_array(dec_text, sizeof(dec_text));
-	if (memcmp(dec_text, TEST_DATA, sizeof(TEST_DATA)) != 0) {
-		VV_(printf("This does NOT match the original data.\n"));
-		return TEST_FAIL;
-	} else {
-		VV_(printf("Successful!\n"));
-	}
-
-	return TEST_SUCC;
-}
-
-/*
- * Performs ECB and CBC tests.
- */
-int main(int argc, char **argv)
-{
-#ifdef NO_CPACF
-	UNUSED(argc);
-	UNUSED(argv);
-	printf("Skipping TDES test, because CPACF support disabled via config option.\n");
-	return TEST_SKIP;
-#else
-	unsigned int mode = 0;
-	int rc = 0;
-	int error_count = 0;
-
-	if (argc > 1) {
-		if (strstr(argv[1], "ecb"))
-			mode = MODE_ECB;
-		if (strstr(argv[1], "cbc"))
-			mode = MODE_CBC;
-		V_(printf("mode = %i \n", mode));
-	}
-	if (mode != 0 && mode != MODE_ECB && mode != MODE_CBC) {
-		printf("Usage: %s [ ecb | cbc ]\n", argv[0]);
-		return TEST_ERR;
-	}
-
-	set_verbosity(argc, argv);
-
-	if (!mode) {
-	/* This is the standard loop that will perform all testcases */
-		mode = 2;
-		while (mode) {
-			rc = test_3des_new_api(mode);
-			if (rc) {
-				error_count++;
-				V_(printf ("test_des_new_api mode = %i failed \n", mode));
-			}
-			else {
-				V_(printf ("test_des_new_api mode = %i finished.\n", mode));
-			}
-
-			mode--;
-		}
-		if (error_count)
-			printf("%i tests failed.\n", error_count);
-		else
-			printf("All tests passed.\n");
-	} else {
-	/* Perform only either in ECB or CBC mode */
-		rc = test_3des_new_api(mode);
-		if (rc)
-			printf ("test_des_new_api mode = %i failed \n", mode);
-		else
-			printf ("test_des_new_api mode = %i finished.\n", mode);
-	}
-
-	if (rc || error_count)
-		return TEST_FAIL;
-
-	return TEST_SUCC;
-#endif /* NO_CPACF */
-}
-
