diff -pruN 3.9.0-1/ChangeLog 4.0.3-0ubuntu1/ChangeLog
--- 3.9.0-1/ChangeLog	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/ChangeLog	2022-08-11 07:50:10.000000000 +0000
@@ -1,3 +1,16 @@
+v4.0.3
+ - [PATCH] Reduce the number of open file descriptors
+ - [PATCH] Various bug fixes
+v4.0.2
+ - [PATCH] Various bug fixes
+v4.0.1
+ - [PATCH] Various bug fixes
+ - [PATCH] Compute HMAC from installed library
+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 -pruN 3.9.0-1/configure.ac 4.0.3-0ubuntu1/configure.ac
--- 3.9.0-1/configure.ac	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/configure.ac	2022-08-11 07:50:10.000000000 +0000
@@ -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.3], [https://github.com/opencryptoki/libica/issues],, [https://github.com/opencryptoki/libica])
 
 # save cmdline flags
 cmdline_CFLAGS="$CFLAGS"
diff -pruN 3.9.0-1/debian/changelog 4.0.3-0ubuntu1/debian/changelog
--- 3.9.0-1/debian/changelog	2022-06-05 20:58:13.000000000 +0000
+++ 4.0.3-0ubuntu1/debian/changelog	2022-08-13 17:33:33.000000000 +0000
@@ -1,26 +1,99 @@
-libica (3.9.0-1) unstable; urgency=medium
+libica (4.0.3-0ubuntu1) kinetic; urgency=medium
 
-  * QA upload.
-  * Import OpenSSL 3 compatible version from Ubuntu (Closes: #1011042).
-  * Keep Homepage
-  * Update to debhelper-compat level 12
+  * New upstream release LP: #1986437
+  * Minor update (extension) of symbols file.
 
- -- Bastian Germann <bage@debian.org>  Sun, 05 Jun 2022 20:58:13 +0000
+ -- Frank Heimes <frank.heimes@canonical.com>  Sat, 13 Aug 2022 19:33:33 +0200
 
-libica (3.2.0-4) unstable; urgency=medium
+libica (4.0.1-0ubuntu1) jammy; urgency=medium
 
-  * QA upload.
-  * Add multiple_defines.patch, fixes a FTBFS with gcc 10 (Closes: 987614).
-  * Update homepage field.
+  * New upstream release LP: #1959421
+  * transition from libica3 to libica4
+    - adjust d/control
+    - migrate d/libica3.* to d/libica4.*
+    - extended symbols file
+  * adjusting d/copyright
+    - change tabs to spaces
+    - update relevant copyright years
 
- -- Jochen Sprickerhof <jspricke@debian.org>  Wed, 05 May 2021 09:27:48 +0200
+ -- Frank Heimes <frank.heimes@canonical.com>  Fri, 04 Feb 2022 19:40:38 +0100
 
-libica (3.2.0-3) unstable; urgency=medium
+libica (3.9.0-0ubuntu1) jammy; urgency=medium
 
-  * QA upload.
-  * Orphan the package.
+  * New upstream release LP: #1953087
 
- -- Dimitri John Ledkov <xnox@ubuntu.com>  Tue, 12 Mar 2019 04:04:53 +0000
+ -- Matthieu Clemenceau <matthieu.clemenceau@canonical.com>  Thu, 02 Dec 2021 17:42:09 -0600
+
+libica (3.8.0-0ubuntu2) jammy; urgency=medium
+
+  * No-change rebuild against openssl3
+
+ -- Simon Chopin <simon.chopin@canonical.com>  Mon, 29 Nov 2021 13:44:39 +0100
+
+libica (3.8.0-0ubuntu1) impish; urgency=medium
+
+  * New upstream release LP: #1928799
+
+ -- Matthieu Clemenceau <matthieu.clemenceau@canonical.com>  Thu, 05 Aug 2021 16:48:40 -0500
+
+libica (3.7.0-0ubuntu1) groovy; urgency=medium
+
+  * New upstream release LP: #1878650
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Thu, 18 Jun 2020 13:47:58 +0100
+
+libica (3.6.1-0ubuntu1) focal; urgency=medium
+
+  * New upstream release LP: #1852550
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Fri, 29 Nov 2019 14:57:43 +0000
+
+libica (3.6.0-0ubuntu1) eoan; urgency=medium
+
+  * New upstream release LP: #1836866
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Fri, 30 Aug 2019 10:47:15 +0100
+
+libica (3.5.0-0ubuntu1) eoan; urgency=medium
+
+  * New upstream release LP: #1826194
+  * Update packaging to debhelper 11.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Tue, 30 Apr 2019 11:58:10 +0100
+
+libica (3.4.0-0ubuntu1) disco; urgency=medium
+
+  * New upstream release LP: #1803962
+  * Update symbols.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Mon, 10 Dec 2018 11:45:54 +1100
+
+libica (3.3.3-0ubuntu1) cosmic; urgency=medium
+
+  * New upstream release. LP: #1776194
+  * Drop testsuite patches, upstream moved to automake 🎉.
+  * Update symbols file.
+  * Drop dh-autoreconf build-dep.
+
+ -- Dimitri John Ledkov 🌈 <xnox@ubuntu.com>  Thu, 14 Jun 2018 07:53:21 +0100
+
+libica (3.2.1-0ubuntu1) bionic; urgency=medium
+
+  * New upstream release
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Wed, 28 Feb 2018 18:27:25 +0000
+
+libica (3.2.0-2ubuntu1) bionic; urgency=medium
+
+  * Cherrypick upstream patches for ECC and z14 support.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Wed, 28 Feb 2018 12:01:37 +0000
+
+libica (3.2.0-2build1) bionic; urgency=high
+
+  * No change rebuild against openssl1.1.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Tue, 06 Feb 2018 12:41:46 +0000
 
 libica (3.2.0-2) unstable; urgency=medium
 
diff -pruN 3.9.0-1/debian/compat 4.0.3-0ubuntu1/debian/compat
--- 3.9.0-1/debian/compat	1970-01-01 00:00:00.000000000 +0000
+++ 4.0.3-0ubuntu1/debian/compat	2022-08-13 17:33:33.000000000 +0000
@@ -0,0 +1 @@
+11
diff -pruN 3.9.0-1/debian/control 4.0.3-0ubuntu1/debian/control
--- 3.9.0-1/debian/control	2022-06-05 20:58:13.000000000 +0000
+++ 4.0.3-0ubuntu1/debian/control	2022-08-13 17:33:33.000000000 +0000
@@ -1,23 +1,23 @@
 Source: libica
 Priority: optional
-Maintainer: Debian QA Group <packages@qa.debian.org>
-Build-Depends: debhelper-compat (= 12), libssl-dev, autoconf-archive
+Maintainer: Dimitri John Ledkov <xnox@ubuntu.com>
+Build-Depends: debhelper (>= 11), libssl-dev, autoconf-archive
 Standards-Version: 4.1.0
 Section: libs
-Homepage: https://github.com/opencryptoki/libica
+Homepage: http://sourceforge.net/projects/opencryptoki/files/libica/
 
 Package: libica-dev
 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 -pruN 3.9.0-1/debian/copyright 4.0.3-0ubuntu1/debian/copyright
--- 3.9.0-1/debian/copyright	2022-06-05 20:58:13.000000000 +0000
+++ 4.0.3-0ubuntu1/debian/copyright	2022-08-13 17:33:33.000000000 +0000
@@ -3,250 +3,250 @@ Upstream-Name: libica
 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 @@ License: BSD-2-clause
  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 -pruN 3.9.0-1/debian/libica3.install 4.0.3-0ubuntu1/debian/libica3.install
--- 3.9.0-1/debian/libica3.install	2022-06-05 20:58:13.000000000 +0000
+++ 4.0.3-0ubuntu1/debian/libica3.install	1970-01-01 00:00:00.000000000 +0000
@@ -1,2 +0,0 @@
-usr/lib/*/lib*.so.3
-usr/lib/*/lib*.so.3.*
diff -pruN 3.9.0-1/debian/libica3.symbols 4.0.3-0ubuntu1/debian/libica3.symbols
--- 3.9.0-1/debian/libica3.symbols	2022-06-05 20:58:13.000000000 +0000
+++ 4.0.3-0ubuntu1/debian/libica3.symbols	1970-01-01 00:00:00.000000000 +0000
@@ -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 -pruN 3.9.0-1/debian/libica4.install 4.0.3-0ubuntu1/debian/libica4.install
--- 3.9.0-1/debian/libica4.install	1970-01-01 00:00:00.000000000 +0000
+++ 4.0.3-0ubuntu1/debian/libica4.install	2022-08-13 17:33:33.000000000 +0000
@@ -0,0 +1,2 @@
+usr/lib/*/lib*.so.4
+usr/lib/*/lib*.so.4.*
diff -pruN 3.9.0-1/debian/libica4.symbols 4.0.3-0ubuntu1/debian/libica4.symbols
--- 3.9.0-1/debian/libica4.symbols	1970-01-01 00:00:00.000000000 +0000
+++ 4.0.3-0ubuntu1/debian/libica4.symbols	2022-08-13 17:33:33.000000000 +0000
@@ -0,0 +1,246 @@
+libica-cex.so.4 libica4 #MINVER#
+ ICA_DRBG_SHA512@LIBICA_3.0.0 4.0.1
+ LIBICA_3.0.0@LIBICA_3.0.0 4.0.1
+ LIBICA_3.0.0_FIPS@LIBICA_3.0.0_FIPS 4.0.1
+ LIBICA_3.1.0@LIBICA_3.1.0 4.0.1
+ LIBICA_3.2.0@LIBICA_3.2.0 4.0.1
+ LIBICA_3.3.0@LIBICA_3.3.0 4.0.1
+ LIBICA_3.4.0@LIBICA_3.4.0 4.0.1
+ LIBICA_3.5.0@LIBICA_3.5.0 4.0.1
+ LIBICA_3.6.0@LIBICA_3.6.0 4.0.1
+ LIBICA_4.0.2@LIBICA_4.0.2 4.0.3
+ ica_3des_cbc@LIBICA_3.0.0 4.0.1
+ ica_3des_cbc_cs@LIBICA_3.0.0 4.0.1
+ ica_3des_cfb@LIBICA_3.0.0 4.0.1
+ ica_3des_cmac@LIBICA_3.0.0 4.0.1
+ ica_3des_cmac_intermediate@LIBICA_3.0.0 4.0.1
+ ica_3des_cmac_last@LIBICA_3.0.0 4.0.1
+ ica_3des_ctr@LIBICA_3.0.0 4.0.1
+ ica_3des_ctrlist@LIBICA_3.0.0 4.0.1
+ ica_3des_ecb@LIBICA_3.0.0 4.0.1
+ ica_3des_ofb@LIBICA_3.0.0 4.0.1
+ ica_aes_cbc@LIBICA_3.0.0 4.0.1
+ ica_aes_cbc_cs@LIBICA_3.0.0 4.0.1
+ ica_aes_ccm@LIBICA_3.0.0 4.0.1
+ ica_aes_cfb@LIBICA_3.0.0 4.0.1
+ ica_aes_cmac@LIBICA_3.0.0 4.0.1
+ ica_aes_cmac_intermediate@LIBICA_3.0.0 4.0.1
+ ica_aes_cmac_last@LIBICA_3.0.0 4.0.1
+ ica_aes_ctr@LIBICA_3.0.0 4.0.1
+ ica_aes_ctrlist@LIBICA_3.0.0 4.0.1
+ ica_aes_ecb@LIBICA_3.0.0 4.0.1
+ ica_aes_gcm@LIBICA_3.0.0 4.0.1
+ ica_aes_gcm_initialize@LIBICA_3.0.0 4.0.1
+ ica_aes_gcm_intermediate@LIBICA_3.0.0 4.0.1
+ ica_aes_gcm_kma_ctx_free@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_ctx_new@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_get_tag@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_init@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_update@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_verify_tag@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_last@LIBICA_3.0.0 4.0.1
+ ica_aes_ofb@LIBICA_3.0.0 4.0.1
+ ica_aes_xts@LIBICA_3.0.0 4.0.1
+ ica_cleanup@LIBICA_4.0.2 4.0.3
+ ica_close_adapter@LIBICA_3.0.0 4.0.1
+ ica_des_cbc@LIBICA_3.0.0 4.0.1
+ ica_des_cbc_cs@LIBICA_3.0.0 4.0.1
+ ica_des_cfb@LIBICA_3.0.0 4.0.1
+ ica_des_cmac@LIBICA_3.0.0 4.0.1
+ ica_des_cmac_intermediate@LIBICA_3.0.0 4.0.1
+ ica_des_cmac_last@LIBICA_3.0.0 4.0.1
+ ica_des_ctr@LIBICA_3.0.0 4.0.1
+ ica_des_ctrlist@LIBICA_3.0.0 4.0.1
+ ica_des_ecb@LIBICA_3.0.0 4.0.1
+ ica_des_ofb@LIBICA_3.0.0 4.0.1
+ ica_drbg_generate@LIBICA_3.0.0 4.0.1
+ ica_drbg_health_test@LIBICA_3.0.0 4.0.1
+ ica_drbg_instantiate@LIBICA_3.0.0 4.0.1
+ ica_drbg_reseed@LIBICA_3.0.0 4.0.1
+ ica_drbg_uninstantiate@LIBICA_3.0.0 4.0.1
+ ica_ec_key_free@LIBICA_3.3.0 4.0.1
+ ica_ec_key_generate@LIBICA_3.3.0 4.0.1
+ ica_ec_key_get_private_key@LIBICA_3.3.0 4.0.1
+ ica_ec_key_get_public_key@LIBICA_3.3.0 4.0.1
+ ica_ec_key_init@LIBICA_3.3.0 4.0.1
+ ica_ec_key_new@LIBICA_3.3.0 4.0.1
+ ica_ecdh_derive_secret@LIBICA_3.3.0 4.0.1
+ ica_ecdsa_sign@LIBICA_3.3.0 4.0.1
+ ica_ecdsa_verify@LIBICA_3.3.0 4.0.1
+ ica_ed25519_ctx_del@LIBICA_3.6.0 4.0.1
+ ica_ed25519_ctx_new@LIBICA_3.6.0 4.0.1
+ ica_ed25519_key_gen@LIBICA_3.6.0 4.0.1
+ ica_ed25519_key_get@LIBICA_3.6.0 4.0.1
+ ica_ed25519_key_set@LIBICA_3.6.0 4.0.1
+ ica_ed25519_sign@LIBICA_3.6.0 4.0.1
+ ica_ed25519_verify@LIBICA_3.6.0 4.0.1
+ ica_ed448_ctx_del@LIBICA_3.6.0 4.0.1
+ ica_ed448_ctx_new@LIBICA_3.6.0 4.0.1
+ ica_ed448_key_gen@LIBICA_3.6.0 4.0.1
+ ica_ed448_key_get@LIBICA_3.6.0 4.0.1
+ ica_ed448_key_set@LIBICA_3.6.0 4.0.1
+ ica_ed448_sign@LIBICA_3.6.0 4.0.1
+ ica_ed448_verify@LIBICA_3.6.0 4.0.1
+ ica_fips_status@LIBICA_3.0.0_FIPS 4.0.1
+ ica_get_functionlist@LIBICA_3.0.0 4.0.1
+ ica_get_version@LIBICA_3.0.0 4.0.1
+ ica_mp_mul512@LIBICA_3.3.0 4.0.1
+ ica_mp_sqr512@LIBICA_3.3.0 4.0.1
+ ica_open_adapter@LIBICA_3.0.0 4.0.1
+ ica_random_number_generate@LIBICA_3.0.0 4.0.1
+ ica_rsa_crt@LIBICA_3.0.0 4.0.1
+ ica_rsa_crt_key_check@LIBICA_3.0.0 4.0.1
+ ica_rsa_key_generate_crt@LIBICA_3.0.0 4.0.1
+ ica_rsa_key_generate_mod_expo@LIBICA_3.0.0 4.0.1
+ ica_rsa_mod_expo@LIBICA_3.0.0 4.0.1
+ ica_set_fallback_mode@LIBICA_3.3.0 4.0.1
+ ica_set_offload_mode@LIBICA_3.5.0 4.0.1
+ ica_set_stats_mode@LIBICA_3.5.0 4.0.1
+ ica_sha1@LIBICA_3.0.0 4.0.1
+ ica_sha224@LIBICA_3.0.0 4.0.1
+ ica_sha256@LIBICA_3.0.0 4.0.1
+ ica_sha384@LIBICA_3.0.0 4.0.1
+ ica_sha3_224@LIBICA_3.1.0 4.0.1
+ ica_sha3_256@LIBICA_3.1.0 4.0.1
+ ica_sha3_384@LIBICA_3.1.0 4.0.1
+ ica_sha3_512@LIBICA_3.1.0 4.0.1
+ ica_sha512@LIBICA_3.0.0 4.0.1
+ ica_sha512_224@LIBICA_3.4.0 4.0.1
+ ica_sha512_256@LIBICA_3.4.0 4.0.1
+ ica_shake_128@LIBICA_3.1.0 4.0.1
+ ica_shake_256@LIBICA_3.1.0 4.0.1
+ ica_x25519_ctx_del@LIBICA_3.6.0 4.0.1
+ ica_x25519_ctx_new@LIBICA_3.6.0 4.0.1
+ ica_x25519_derive@LIBICA_3.6.0 4.0.1
+ ica_x25519_key_gen@LIBICA_3.6.0 4.0.1
+ ica_x25519_key_get@LIBICA_3.6.0 4.0.1
+ ica_x25519_key_set@LIBICA_3.6.0 4.0.1
+ ica_x448_ctx_del@LIBICA_3.6.0 4.0.1
+ ica_x448_ctx_new@LIBICA_3.6.0 4.0.1
+ ica_x448_derive@LIBICA_3.6.0 4.0.1
+ ica_x448_key_gen@LIBICA_3.6.0 4.0.1
+ ica_x448_key_get@LIBICA_3.6.0 4.0.1
+ ica_x448_key_set@LIBICA_3.6.0 4.0.1
+libica.so.4 libica4 #MINVER#
+ ICA_DRBG_SHA512@LIBICA_3.0.0 4.0.1
+ LIBICA_3.0.0@LIBICA_3.0.0 4.0.1
+ LIBICA_3.0.0_FIPS@LIBICA_3.0.0_FIPS 4.0.1
+ LIBICA_3.1.0@LIBICA_3.1.0 4.0.1
+ LIBICA_3.2.0@LIBICA_3.2.0 4.0.1
+ LIBICA_3.3.0@LIBICA_3.3.0 4.0.1
+ LIBICA_3.4.0@LIBICA_3.4.0 4.0.1
+ LIBICA_3.5.0@LIBICA_3.5.0 4.0.1
+ LIBICA_3.6.0@LIBICA_3.6.0 4.0.1
+ LIBICA_4.0.2@LIBICA_4.0.2 4.0.3
+ ica_3des_cbc@LIBICA_3.0.0 4.0.1
+ ica_3des_cbc_cs@LIBICA_3.0.0 4.0.1
+ ica_3des_cfb@LIBICA_3.0.0 4.0.1
+ ica_3des_cmac@LIBICA_3.0.0 4.0.1
+ ica_3des_cmac_intermediate@LIBICA_3.0.0 4.0.1
+ ica_3des_cmac_last@LIBICA_3.0.0 4.0.1
+ ica_3des_ctr@LIBICA_3.0.0 4.0.1
+ ica_3des_ctrlist@LIBICA_3.0.0 4.0.1
+ ica_3des_ecb@LIBICA_3.0.0 4.0.1
+ ica_3des_ofb@LIBICA_3.0.0 4.0.1
+ ica_aes_cbc@LIBICA_3.0.0 4.0.1
+ ica_aes_cbc_cs@LIBICA_3.0.0 4.0.1
+ ica_aes_ccm@LIBICA_3.0.0 4.0.1
+ ica_aes_cfb@LIBICA_3.0.0 4.0.1
+ ica_aes_cmac@LIBICA_3.0.0 4.0.1
+ ica_aes_cmac_intermediate@LIBICA_3.0.0 4.0.1
+ ica_aes_cmac_last@LIBICA_3.0.0 4.0.1
+ ica_aes_ctr@LIBICA_3.0.0 4.0.1
+ ica_aes_ctrlist@LIBICA_3.0.0 4.0.1
+ ica_aes_ecb@LIBICA_3.0.0 4.0.1
+ ica_aes_gcm@LIBICA_3.0.0 4.0.1
+ ica_aes_gcm_initialize@LIBICA_3.0.0 4.0.1
+ ica_aes_gcm_intermediate@LIBICA_3.0.0 4.0.1
+ ica_aes_gcm_kma_ctx_free@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_ctx_new@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_get_tag@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_init@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_update@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_kma_verify_tag@LIBICA_3.2.0 4.0.1
+ ica_aes_gcm_last@LIBICA_3.0.0 4.0.1
+ ica_aes_ofb@LIBICA_3.0.0 4.0.1
+ ica_aes_xts@LIBICA_3.0.0 4.0.1
+ ica_cleanup@LIBICA_4.0.2 4.0.3
+ ica_close_adapter@LIBICA_3.0.0 4.0.1
+ ica_des_cbc@LIBICA_3.0.0 4.0.1
+ ica_des_cbc_cs@LIBICA_3.0.0 4.0.1
+ ica_des_cfb@LIBICA_3.0.0 4.0.1
+ ica_des_cmac@LIBICA_3.0.0 4.0.1
+ ica_des_cmac_intermediate@LIBICA_3.0.0 4.0.1
+ ica_des_cmac_last@LIBICA_3.0.0 4.0.1
+ ica_des_ctr@LIBICA_3.0.0 4.0.1
+ ica_des_ctrlist@LIBICA_3.0.0 4.0.1
+ ica_des_ecb@LIBICA_3.0.0 4.0.1
+ ica_des_ofb@LIBICA_3.0.0 4.0.1
+ ica_drbg_generate@LIBICA_3.0.0 4.0.1
+ ica_drbg_health_test@LIBICA_3.0.0 4.0.1
+ ica_drbg_instantiate@LIBICA_3.0.0 4.0.1
+ ica_drbg_reseed@LIBICA_3.0.0 4.0.1
+ ica_drbg_uninstantiate@LIBICA_3.0.0 4.0.1
+ ica_ec_key_free@LIBICA_3.3.0 4.0.1
+ ica_ec_key_generate@LIBICA_3.3.0 4.0.1
+ ica_ec_key_get_private_key@LIBICA_3.3.0 4.0.1
+ ica_ec_key_get_public_key@LIBICA_3.3.0 4.0.1
+ ica_ec_key_init@LIBICA_3.3.0 4.0.1
+ ica_ec_key_new@LIBICA_3.3.0 4.0.1
+ ica_ecdh_derive_secret@LIBICA_3.3.0 4.0.1
+ ica_ecdsa_sign@LIBICA_3.3.0 4.0.1
+ ica_ecdsa_verify@LIBICA_3.3.0 4.0.1
+ ica_ed25519_ctx_del@LIBICA_3.6.0 4.0.1
+ ica_ed25519_ctx_new@LIBICA_3.6.0 4.0.1
+ ica_ed25519_key_gen@LIBICA_3.6.0 4.0.1
+ ica_ed25519_key_get@LIBICA_3.6.0 4.0.1
+ ica_ed25519_key_set@LIBICA_3.6.0 4.0.1
+ ica_ed25519_sign@LIBICA_3.6.0 4.0.1
+ ica_ed25519_verify@LIBICA_3.6.0 4.0.1
+ ica_ed448_ctx_del@LIBICA_3.6.0 4.0.1
+ ica_ed448_ctx_new@LIBICA_3.6.0 4.0.1
+ ica_ed448_key_gen@LIBICA_3.6.0 4.0.1
+ ica_ed448_key_get@LIBICA_3.6.0 4.0.1
+ ica_ed448_key_set@LIBICA_3.6.0 4.0.1
+ ica_ed448_sign@LIBICA_3.6.0 4.0.1
+ ica_ed448_verify@LIBICA_3.6.0 4.0.1
+ ica_fips_status@LIBICA_3.0.0_FIPS 4.0.1
+ ica_get_functionlist@LIBICA_3.0.0 4.0.1
+ ica_get_version@LIBICA_3.0.0 4.0.1
+ ica_mp_mul512@LIBICA_3.3.0 4.0.1
+ ica_mp_sqr512@LIBICA_3.3.0 4.0.1
+ ica_open_adapter@LIBICA_3.0.0 4.0.1
+ ica_random_number_generate@LIBICA_3.0.0 4.0.1
+ ica_rsa_crt@LIBICA_3.0.0 4.0.1
+ ica_rsa_crt_key_check@LIBICA_3.0.0 4.0.1
+ ica_rsa_key_generate_crt@LIBICA_3.0.0 4.0.1
+ ica_rsa_key_generate_mod_expo@LIBICA_3.0.0 4.0.1
+ ica_rsa_mod_expo@LIBICA_3.0.0 4.0.1
+ ica_set_fallback_mode@LIBICA_3.3.0 4.0.1
+ ica_set_offload_mode@LIBICA_3.5.0 4.0.1
+ ica_set_stats_mode@LIBICA_3.5.0 4.0.1
+ ica_sha1@LIBICA_3.0.0 4.0.1
+ ica_sha224@LIBICA_3.0.0 4.0.1
+ ica_sha256@LIBICA_3.0.0 4.0.1
+ ica_sha384@LIBICA_3.0.0 4.0.1
+ ica_sha3_224@LIBICA_3.1.0 4.0.1
+ ica_sha3_256@LIBICA_3.1.0 4.0.1
+ ica_sha3_384@LIBICA_3.1.0 4.0.1
+ ica_sha3_512@LIBICA_3.1.0 4.0.1
+ ica_sha512@LIBICA_3.0.0 4.0.1
+ ica_sha512_224@LIBICA_3.4.0 4.0.1
+ ica_sha512_256@LIBICA_3.4.0 4.0.1
+ ica_shake_128@LIBICA_3.1.0 4.0.1
+ ica_shake_256@LIBICA_3.1.0 4.0.1
+ ica_x25519_ctx_del@LIBICA_3.6.0 4.0.1
+ ica_x25519_ctx_new@LIBICA_3.6.0 4.0.1
+ ica_x25519_derive@LIBICA_3.6.0 4.0.1
+ ica_x25519_key_gen@LIBICA_3.6.0 4.0.1
+ ica_x25519_key_get@LIBICA_3.6.0 4.0.1
+ ica_x25519_key_set@LIBICA_3.6.0 4.0.1
+ ica_x448_ctx_del@LIBICA_3.6.0 4.0.1
+ ica_x448_ctx_new@LIBICA_3.6.0 4.0.1
+ ica_x448_derive@LIBICA_3.6.0 4.0.1
+ ica_x448_key_gen@LIBICA_3.6.0 4.0.1
+ ica_x448_key_get@LIBICA_3.6.0 4.0.1
+ ica_x448_key_set@LIBICA_3.6.0 4.0.1
diff -pruN 3.9.0-1/doc/icastats.1 4.0.3-0ubuntu1/doc/icastats.1
--- 3.9.0-1/doc/icastats.1	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/doc/icastats.1	2022-08-11 07:50:10.000000000 +0000
@@ -12,8 +12,8 @@ icastats \- display statistic data for t
 .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 @@ Here is a shortened sample output:
       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 @@ memory area exists in one table accumula
 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 -pruN 3.9.0-1/doc/Makefile.am 4.0.3-0ubuntu1/doc/Makefile.am
--- 3.9.0-1/doc/Makefile.am	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/doc/Makefile.am	2022-08-11 07:50:10.000000000 +0000
@@ -1 +1,2 @@
 dist_man1_MANS = icastats.1 icainfo.1 icainfo-cex.1
+MAINTAINERCLEANFILES = Makefile.in
diff -pruN 3.9.0-1/include/ica_api.h 4.0.3-0ubuntu1/include/ica_api.h
--- 3.9.0-1/include/ica_api.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/include/ica_api.h	2022-08-11 07:50:10.000000000 +0000
@@ -597,7 +597,7 @@ unsigned int ica_random_number_generate(
 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 @@ unsigned int ica_sha1(unsigned int messa
 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 @@ unsigned int ica_sha224(unsigned int mes
 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 @@ unsigned int ica_sha256(unsigned int mes
 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 @@ unsigned int ica_sha384(unsigned int mes
 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 @@ unsigned int ica_sha512(unsigned int mes
 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 @@ unsigned int ica_sha512_224(unsigned int
  */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 @@ unsigned int ica_shake_128(unsigned int
 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 @@ ICA_EXPORT
 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.
@@ -1291,6 +1291,7 @@ int ica_ed448_ctx_del(ICA_ED448_CTX **ct
  *
  * @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 @@ unsigned int ica_rsa_key_generate_mod_ex
  *
  * @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,12 +1348,13 @@ unsigned int ica_rsa_key_generate_crt(ic
  *
  * @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.
  */
 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);
 
@@ -1375,12 +1378,13 @@ unsigned int ica_rsa_mod_expo(ica_adapte
  *
  * @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.
  */
 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 +1404,6 @@ ICA_EXPORT
 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 +3379,6 @@ void ica_aes_gcm_kma_ctx_free(kma_ctx* c
 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 +3642,6 @@ int ica_mp_mul512(uint64_t r[16], const
 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 +3651,11 @@ int ica_mp_sqr512(uint64_t r[16], const
 ICA_EXPORT
 int ica_fips_status(void);
 
+#ifdef ICA_FIPS
+/*
+ * Additional FIPS interfaces are available for built-in FIPS mode.
+ */
+
 /*
  * FIPS powerups tests.
  *
@@ -3891,4 +3665,12 @@ ICA_EXPORT
 void ica_fips_powerup_tests(void);
 #endif /* ICA_FIPS */
 
+/*
+ * Cleanup ICA resources. Should be called before the application terminates,
+ * or the libica library is unloaded.
+ *
+ */
+ICA_EXPORT
+void ica_cleanup(void);
+
 #endif /* __ICA_API_H__ */
diff -pruN 3.9.0-1/include/Makefile.am 4.0.3-0ubuntu1/include/Makefile.am
--- 3.9.0-1/include/Makefile.am	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/include/Makefile.am	2022-08-11 07:50:10.000000000 +0000
@@ -1 +1,2 @@
 include_HEADERS = ica_api.h
+MAINTAINERCLEANFILES = Makefile.in
diff -pruN 3.9.0-1/libica.map 4.0.3-0ubuntu1/libica.map
--- 3.9.0-1/libica.map	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/libica.map	2022-08-11 07:50:10.000000000 +0000
@@ -3,15 +3,11 @@ LIBICA_3.0.0 {
 	_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 @@ LIBICA_3.0.0 {
 	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 @@ LIBICA_3.0.0 {
 	ica_3des_cmac_intermediate;
 	ica_3des_cmac_last;
 
-	ica_aes_encrypt;
-	ica_aes_decrypt;
 	ica_aes_ecb;
 	ica_aes_cbc;
 	ica_aes_cbc_cs;
@@ -174,3 +166,9 @@ LIBICA_3.6.0 {
 	ica_ed448_ctx_del;
     local: *;
 } LIBICA_3.5.0;
+
+LIBICA_4.0.2 {
+    global:
+	ica_cleanup;
+    local: *;
+} LIBICA_3.6.0;
diff -pruN 3.9.0-1/libica.spec 4.0.3-0ubuntu1/libica.spec
--- 3.9.0-1/libica.spec	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/libica.spec	2022-08-11 07:50:10.000000000 +0000
@@ -1,5 +1,5 @@
 Name:          libica
-Version:       3.9.0
+Version:       4.0.3
 Release:       1%{?dist}
 Summary:       Interface library to the ICA device driver
 
@@ -62,6 +62,10 @@ rm -rf $RPM_BUILD_ROOT
 %{_includedir}/ica_api.h
 
 %changelog
+* Thu Jun 23 2022 Joerg Schmidbauer <jschmidb@linux.vnet.ibm.com>
+- Version v4.0.2
+* Thu Feb 03 2022 Joerg Schmidbauer <jschmidb@linux.vnet.ibm.com>
+- Version v4.0.1
 * Tue Oct 12 2021 Joerg Schmidbauer <jschmidb@linux.vnet.ibm.com>
 - Version v3.9.0
 * Thu May 06 2021 Joerg Schmidbauer <jschmidb@linux.vnet.ibm.com>
diff -pruN 3.9.0-1/Makefile.am 4.0.3-0ubuntu1/Makefile.am
--- 3.9.0-1/Makefile.am	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/Makefile.am	2022-08-11 07:50:10.000000000 +0000
@@ -4,6 +4,11 @@ SUBDIRS = doc include src test
 
 dist_doc_DATA = AUTHORS ChangeLog INSTALL LICENSE README.md
 EXTRA_DIST = libica.map libica.spec
+DISTCLEANFILES = *~
+MAINTAINERCLEANFILES = test-driver \
+	Makefile.in aclocal.m4 compile configure config.guess \
+	config.sub depcomp install-sh ltmain.sh m4/* missing \
+	depcomp ylwrap
 MAJOR := `echo $(VERSION) | cut -d. -f1`
 
 coverage: check
@@ -17,11 +22,8 @@ coverage: check
 	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 +40,5 @@ if ICA_OPENSSL3
 endif
 endif
 
+.PHONY: fipsinstall
+
diff -pruN 3.9.0-1/src/fips.c 4.0.3-0ubuntu1/src/fips.c
--- 3.9.0-1/src/fips.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/fips.c	2022-08-11 07:50:10.000000000 +0000
@@ -59,6 +59,7 @@ int openssl_in_fips_mode(void)
 #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 @@ static const char hmackey[] =
 	"0000000000000000000000000000000000000000000000000000000000000000"
 	"0000000000000000000000000000000000000000000000000000000000000000";
 
+#endif /* ICA_INTERNAL_TEST */
+
 int fips;
 
 #define LIBICA_FIPS_CONFIG		LIBICA_CONFDIR "/libica/openssl3-fips.cnf"
@@ -254,9 +257,22 @@ fips_init(void)
 
 		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;
@@ -317,6 +333,7 @@ static int compute_file_hmac(const char
 		}
 	}
 
+	hlen = sizeof(rbuf);
 	if (EVP_DigestSignFinal(mdctx, rbuf, &hlen) <= 0)
 		goto end;
 
@@ -343,31 +360,20 @@ end:
 	return rc;
 }
 
-/**
- * Performs the FIPS check.
- *
- * @return  1 if check succeeded
- *          0 otherwise
- */
-static int FIPSCHECK_verify(const char *path)
+static int load_known_hmac(const char *path, unsigned char **hmac, long *hmaclen)
 {
-	int rc = 0;
+	int rc = -1;
 	FILE *fp;
-	unsigned char *known_hmac = NULL;
-	long hmaclen;
-	char *hmacpath, *p;
 	char *known_hmac_str = NULL;
-	size_t n, computed_hmac_len;
-	void *computed_hmac = NULL;
+	char *hmacpath, *p;
+	size_t n;
 
 	hmacpath = make_hmac_path(path);
 	if (hmacpath == NULL)
-		return 0;
+		return rc;
 
-	fp = fopen(hmacpath, "r");
-	if (fp == NULL) {
-		goto end;
-	}
+	if ((fp = fopen(hmacpath, "r")) == NULL)
+		return rc;
 
 	if (getline(&known_hmac_str, &n, fp) <= 0)
 		goto end;
@@ -375,27 +381,47 @@ static int FIPSCHECK_verify(const char *
 	if ((p = strchr(known_hmac_str, '\n')) != NULL)
 		*p = '\0';
 
-	known_hmac = OPENSSL_hexstr2buf(known_hmac_str, &hmaclen);
+	*hmac = OPENSSL_hexstr2buf(known_hmac_str, hmaclen);
+	rc = 0;
+end:
+	fclose(fp);
+	free(known_hmac_str);
+	free(hmacpath);
+
+	return rc;
+}
+
+/**
+ * Performs the FIPS check.
+ *
+ * @return  1 if check succeeded
+ *          0 otherwise
+ */
+static int FIPSCHECK_verify(const char *path)
+{
+	int rc = 0;
+	unsigned char *known_hmac = NULL;
+	long known_hmac_len;
+	void *computed_hmac = NULL;
+	size_t computed_hmac_len;
+
+	if (load_known_hmac(path, &known_hmac,  &known_hmac_len) != 0)
+		goto end;
 
 	if (compute_file_hmac(path, &computed_hmac, &computed_hmac_len) != 0)
 		goto end;
 
+	if ((size_t)known_hmac_len != computed_hmac_len)
+		goto end;
+
 	if (memcmp(computed_hmac, known_hmac, computed_hmac_len) != 0)
 		goto end;
 
 	rc = 1;
-
 end:
-
 	free(computed_hmac);
-	free(known_hmac_str);
-	free(hmacpath);
-
 	OPENSSL_free(known_hmac);
 
-	if (fp)
-		fclose(fp);
-
 	return rc;
 }
 
@@ -469,6 +495,7 @@ static void fips_lib_integrity_check(voi
 
 	syslog(LOG_INFO, msg3);
 }
+#endif /* ICA_INTERNAL_TEST */
 
 void
 fips_powerup_tests(void)
@@ -1058,7 +1085,7 @@ _err_:
 }
 
 static int
-des3_cbc_cs_kat(void){
+des3_cbc_cs_kat(void) {
 	const struct des3_cbc_cs_tv *tv;
 	size_t i;
 	unsigned char iv[DES3_BLKSIZE], *out;
@@ -1287,11 +1314,34 @@ rsa_kat(void)
 	ica_adapter_handle_t ah;
 	const struct rsa_tv *tv;
 	size_t i, keylen, crtparamlen;
-	unsigned char *out;
+	unsigned char *out = NULL;
+	libica_func_list_element* libica_func_list = NULL;
+	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 +1390,12 @@ rsa_kat(void)
 		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 -pruN 3.9.0-1/src/ica_api.c 4.0.3-0ubuntu1/src/ica_api.c
--- 3.9.0-1/src/ica_api.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/ica_api.c	2022-08-11 07:50:10.000000000 +0000
@@ -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
@@ -88,6 +90,7 @@ void ica_set_stats_mode(int stats_mode)
 	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)
@@ -99,7 +102,6 @@ static unsigned int fips_check_3des_key(
 }
 #endif
 
-#ifndef NO_CPACF
 static unsigned int check_des_parms(unsigned int mode,
 				    unsigned long data_length,
 				    const unsigned char *in_data,
@@ -394,7 +396,7 @@ unsigned int ica_close_adapter(ica_adapt
 
 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 +451,7 @@ unsigned int ica_sha1(unsigned int messa
 
 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 +498,7 @@ unsigned int ica_sha224(unsigned int mes
 
 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 +545,7 @@ unsigned int ica_sha256(unsigned int mes
 
 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 +593,7 @@ unsigned int ica_sha384(unsigned int mes
 
 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 +641,7 @@ unsigned int ica_sha512(unsigned int mes
 
 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 +689,7 @@ unsigned int ica_sha512_224(unsigned int
 
 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 +737,7 @@ unsigned int ica_sha512_256(unsigned int
 
 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 +784,7 @@ unsigned int ica_sha3_224(unsigned int m
 
 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 +831,7 @@ unsigned int ica_sha3_256(unsigned int m
 
 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 +879,7 @@ unsigned int ica_sha3_384(unsigned int m
 
 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 +927,7 @@ unsigned int ica_sha3_512(unsigned int m
 
 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 +982,7 @@ unsigned int ica_shake_128(unsigned int
 
 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)
 {
@@ -1071,9 +1073,12 @@ unsigned int ica_rsa_key_generate_mod_ex
 	/* 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 @@ unsigned int ica_rsa_key_generate_crt(ic
 		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;
@@ -1127,7 +1134,7 @@ unsigned int ica_rsa_key_generate_crt(ic
 }
 
 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)
 {
@@ -1145,14 +1152,16 @@ unsigned int ica_rsa_mod_expo(ica_adapte
 
 	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 = (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 +1180,9 @@ unsigned int ica_rsa_mod_expo(ica_adapte
 				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 +1235,11 @@ unsigned int ica_rsa_crt_key_check(ica_r
 		/* 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 +1255,7 @@ unsigned int ica_rsa_crt_key_check(ica_r
 }
 
 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)
 {
@@ -1259,20 +1273,22 @@ unsigned int ica_rsa_crt(ica_adapter_han
 
 	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 = (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)
@@ -1284,14 +1300,16 @@ unsigned int ica_rsa_crt(ica_adapter_han
 		else
 			rc = ENODEV;
 
-		if(!rc)
+		if (!rc)
 			hardware = ALGO_HW;
 		else
 			rc = ica_fallbacks_enabled ?
 				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));
 
@@ -1318,9 +1336,15 @@ ICA_EC_KEY* ica_ec_key_new(unsigned int
 
 	/* 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;
@@ -1422,7 +1446,9 @@ int ica_ec_key_generate(ica_adapter_hand
 	}
 
 	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 +1509,9 @@ int ica_ecdh_derive_secret(ica_adapter_h
 	}
 
 	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 +1566,9 @@ int ica_ecdsa_sign(ica_adapter_handle_t
 	}
 
 	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 +1625,9 @@ int ica_ecdsa_verify(ica_adapter_handle_
 	}
 
 	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;
 }
@@ -2279,7 +2311,9 @@ int ica_x25519_key_gen(ICA_X25519_CTX *c
 	memset(ctx, 0, sizeof(*ctx));
 	ctx->pub_init = 0;
 
-	rng_gen(ctx->priv, 32);
+	if (rng_gen(ctx->priv, 32))
+		return -1;
+
 	ctx->priv_init = 1;
 	return 0;
 #endif /* NO_CPACF */
@@ -2297,7 +2331,9 @@ int ica_x448_key_gen(ICA_X448_CTX *ctx)
 	memset(ctx, 0, sizeof(*ctx));
 	ctx->pub_init = 0;
 
-	rng_gen(ctx->priv, 56);
+	if (rng_gen(ctx->priv, 56))
+		return -1;
+
 	ctx->priv_init = 1;
 	return 0;
 #endif /* NO_CPACF */
@@ -2315,7 +2351,9 @@ int ica_ed25519_key_gen(ICA_ED25519_CTX
 	memset(ctx, 0, sizeof(*ctx));
 	ctx->pub_init = 0;
 
-	rng_gen(ctx->sign_param.priv, sizeof(ctx->sign_param.priv));
+	if (rng_gen(ctx->sign_param.priv, sizeof(ctx->sign_param.priv)))
+		return -1;
+
 	ctx->priv_init = 1;
 	return 0;
 #endif /* NO_CPACF */
@@ -2333,8 +2371,10 @@ int ica_ed448_key_gen(ICA_ED448_CTX *ctx
 	memset(ctx, 0, sizeof(*ctx));
 	ctx->pub_init = 0;
 
-	rng_gen(ctx->sign_param.priv + 64 - 57,
-		sizeof(ctx->sign_param.priv) - (64 - 57));
+	if (rng_gen(ctx->sign_param.priv + 64 - 57,
+		    sizeof(ctx->sign_param.priv) - (64 - 57)))
+		return -1;
+
 	ctx->priv_init = 1;
 	return 0;
 #endif /* NO_CPACF */
@@ -2346,264 +2386,6 @@ int ica_ed448_key_gen(ICA_ED448_CTX *ctx
  *
  ******************************************************************************/
 
-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)
@@ -2866,7 +2648,7 @@ unsigned int ica_des_cmac_intermediate(c
 		       DES_BLOCK_SIZE, NULL,	/* no mac available (intermediate) */
 		       iv);
 
-	if(!rc)
+	if (!rc)
 		stats_increment(ICA_STATS_DES_CMAC, ALGO_HW, ICA_DECRYPT);
 	return rc;
 #endif /* NO_CPACF */
@@ -3639,7 +3421,9 @@ unsigned int ica_aes_cmac_intermediate(c
 		       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 +3468,10 @@ unsigned int ica_aes_cmac_last(const uns
 			       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 +3480,10 @@ unsigned int ica_aes_cmac_last(const uns
 			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;
@@ -4259,7 +4047,7 @@ ica_drbg_mech_t *const ICA_DRBG_SHA512 =
 
 static inline int ica_drbg_error(int status)
 {
-	switch(status){
+	switch(status) {
 	case 0:
 		return 0;
 	case DRBG_RESEED_REQUIRED:
@@ -4309,20 +4097,20 @@ int ica_drbg_instantiate(ica_drbg_t **sh
 #endif /* ICA_FIPS */
 
 	status = drbg_mech_valid(mech);
-	if(status)
+	if (status)
 		return ica_drbg_error(status);
 
 	/* Run instantiate health test (11.3.2). */
 	pthread_rwlock_wrlock(&mech->lock);
 	status = drbg_health_test(drbg_instantiate, sec, pr, mech);
 	pthread_rwlock_unlock(&mech->lock);
-	if(status)
+	if (status)
 		return ica_drbg_error(status);
 
 	/* Instantiate. */
 	status = drbg_instantiate(sh, sec, pr, mech, pers, pers_len, false,
 				  NULL, 0, NULL, 0);
-	if(0 > status)
+	if (0 > status)
 		mech->error_state = status;
 
 	return ica_drbg_error(status);
@@ -4348,17 +4136,17 @@ int ica_drbg_reseed(ica_drbg_t *sh,
 		return EACCES;
 #endif /* ICA_FIPS */
 
-	if(!sh)
+	if (!sh)
 		return ica_drbg_error(DRBG_SH_INV);
 	status = drbg_mech_valid(sh->mech);
-	if(status)
+	if (status)
 		return ica_drbg_error(status);
 
 	/* Reseed health test runs whenever generate is tested (11.3.4). */
 
 	/* Reseed. */
 	status = drbg_reseed(sh, pr, add, add_len, false, NULL, 0);
-	if(0 > status)
+	if (0 > status)
 		sh->mech->error_state = status;
 
 	return ica_drbg_error(status);
@@ -4390,21 +4178,21 @@ int ica_drbg_generate(ica_drbg_t *sh,
 		return EACCES;
 #endif /* ICA_FIPS */
 
-	if(!sh)
+	if (!sh)
 		return ica_drbg_error(DRBG_SH_INV);
 	status = drbg_mech_valid(sh->mech);
-	if(status)
+	if (status)
 		return ica_drbg_error(status);
 
 	/* Run generate and reseed health tests before first use of these
 	 * functions and when indicated by the test counter (11.3.3). */
 	pthread_rwlock_wrlock(&sh->mech->lock);
-	if(!(sh->mech->test_ctr %= sh->mech->test_intervall)){
+	if (!(sh->mech->test_ctr %= sh->mech->test_intervall)) {
 		status = drbg_health_test(drbg_reseed, sec, pr, sh->mech);
-		if(!status)
+		if (!status)
 			status = drbg_health_test(drbg_generate, sec, pr,
 						  sh->mech);
-		if(status){
+		if (status) {
 			pthread_rwlock_unlock(&sh->mech->lock);
 			return ica_drbg_error(status);
 		}
@@ -4414,16 +4202,16 @@ int ica_drbg_generate(ica_drbg_t *sh,
 
 	/* Generate. */
 	status = pthread_rwlock_rdlock(&sh->mech->lock);
-	if(EAGAIN == status)
+	if (EAGAIN == status)
 		return ica_drbg_error(DRBG_REQUEST_INV);
 	status = drbg_generate(sh, sec, pr, add, add_len, false, NULL, 0, prnd,
 			       prnd_len);
 	pthread_rwlock_unlock(&sh->mech->lock);
-	if(0 > status)
+	if (0 > status)
 		sh->mech->error_state = status;
 
 	/* Inhibit output if mechanism is in error state (11.3.6). */
-	if(sh->mech->error_state)
+	if (sh->mech->error_state)
 		drbg_zmem(prnd, prnd_len);
 
 	return ica_drbg_error(status);
@@ -4459,18 +4247,18 @@ int ica_drbg_health_test(void *func,
 	int status;
 
 	status = drbg_mech_valid(mech);
-	if(status)
+	if (status)
 		return ica_drbg_error(status);
 
 	/* Health test. */
 	pthread_rwlock_wrlock(&mech->lock);
-	if(ica_drbg_instantiate == func)
+	if (ica_drbg_instantiate == func)
 		status = drbg_health_test(drbg_instantiate, sec, pr, mech);
-	else if(ica_drbg_reseed == func)
+	else if (ica_drbg_reseed == func)
 		status = drbg_health_test(drbg_reseed, sec, pr, mech);
-	else if(ica_drbg_generate == func){
+	else if (ica_drbg_generate == func) {
 		status = drbg_health_test(drbg_reseed, sec, pr, mech);
-		if(!status)
+		if (!status)
 			status = drbg_health_test(drbg_generate, sec, pr,
 						  mech);
 		mech->test_ctr = 1; /* reset test counter */
@@ -4483,14 +4271,18 @@ int ica_drbg_health_test(void *func,
 #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 -pruN 3.9.0-1/src/icainfo.c 4.0.3-0ubuntu1/src/icainfo.c
--- 3.9.0-1/src/icainfo.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/icainfo.c	2022-08-11 07:50:10.000000000 +0000
@@ -333,6 +333,8 @@ static struct crypt_pair crypt_map[] = {
 	{"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},
@@ -383,6 +385,7 @@ int main(int argc, char **argv)
 		default:
 			fprintf(stderr, "Try '%s --help' for more"
 				" information.\n", basename(argv[0]));
+			ica_cleanup();
 			exit(1);
 		}
 	}
@@ -390,6 +393,7 @@ int main(int argc, char **argv)
 		fprintf(stderr, "%s: invalid option.\n"
 			"Try '%s --help' for more information.\n",
 			argv[0], basename(argv[0]));
+		ica_cleanup();
 		exit(1);
 	}
 
@@ -398,12 +402,14 @@ int main(int argc, char **argv)
 
 	if (ica_get_functionlist(NULL, &mech_len) != 0){
 		perror("get_functionlist: ");
+		ica_cleanup();
 		return EXIT_FAILURE;
 	}
 	pmech_list = malloc(sizeof(libica_func_list_element)*mech_len);
 	if (ica_get_functionlist(pmech_list, &mech_len) != 0){
 		perror("get_functionlist: ");
 		free(pmech_list);
+		ica_cleanup();
 		return EXIT_FAILURE;
 	}
 
@@ -462,11 +468,12 @@ int main(int argc, char **argv)
 #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");
 #endif
 
+	ica_cleanup();
 	return EXIT_SUCCESS;
 }
diff -pruN 3.9.0-1/src/icastats.c 4.0.3-0ubuntu1/src/icastats.c
--- 3.9.0-1/src/icastats.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/icastats.c	2022-08-11 07:50:10.000000000 +0000
@@ -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 @@ void print_help(char *cmd)
 	       " -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 @@ static struct option getopt_long_options
 	{"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 @@ const char *const STATS_DESC[ICA_NUM_STA
 
 
 #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,
@@ -96,13 +106,100 @@ void print_stats(stats_entry_t *stats)
 			       stats[i].enc.sw,
 			       CELL_SIZE,
 			       stats[i].dec.sw);
+		}
+	}
+}
+
+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 +210,8 @@ int main(int argc, char *argv[])
 	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,
@@ -122,7 +221,7 @@ int main(int argc, char *argv[])
 			reset = 1;
 			break;
 		case 'R':
-			if(geteuid() != 0){
+			if (geteuid() != 0) {
 				fprintf(stderr,"You have no rights to reset all shared memory"
 					" segments!\n");
 				return EXIT_FAILURE;
@@ -133,16 +232,15 @@ int main(int argc, char *argv[])
 			delete = 1;
 			break;
 		case 'D':
-			if(geteuid() != 0){
+			if (geteuid() != 0) {
 				fprintf(stderr,"You have no rights to delete all shared memory"
 					" segments!\n");
 				return EXIT_FAILURE;
 			}
-
 			delete = 2;
 			break;
 		case 'U':
-			if((pswd = getpwnam(optarg)) == NULL){
+			if ((pswd = getpwnam(optarg)) == NULL) {
 				fprintf(stderr, "The username %s is not known"
 					" on this system.\n", optarg );
 				return EXIT_FAILURE;
@@ -155,6 +253,12 @@ int main(int argc, char *argv[])
 		case 'A':
 			all = 1;
 			break;
+		case 'k':
+			key_sizes = 1;
+			break;
+		case 'j':
+			json = 1;
+			break;
 		case 'v':
 			print_version();
 			exit(0);
@@ -177,56 +281,68 @@ int main(int argc, char *argv[])
 		return EXIT_FAILURE;
 	}
 
-	if(delete == 2){
-		if(delete_all() == -1){
+	if (delete == 2) {
+		if (delete_all() == -1) {
 			perror("deleteall: ");
 			return EXIT_FAILURE;
 		}
 		return EXIT_SUCCESS;
-	} else if(delete){
+	} else if (delete) {
 		stats_mmap(user);
-		stats_munmap(SHM_DESTROY);
+		stats_munmap(user, SHM_DESTROY);
 		return EXIT_SUCCESS;
 	}
-	if(all){
+	if (all) {
 		char *usr;
 		stats_entry_t *entries;
-		while((usr = get_next_usr()) != NULL){
-			if((entries = malloc(sizeof(stats_entry_t)*ICA_NUM_STATS)) == NULL){
+		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;
 	}
 
 	if (sum){
 		stats_entry_t *entries;
-		if((entries = malloc(sizeof(stats_entry_t)*ICA_NUM_STATS)) == NULL){
+		if ((entries = malloc(sizeof(stats_entry_t)*ICA_NUM_STATS)) == NULL) {
 			perror("malloc: ");
 			return EXIT_FAILURE;
 		}
 
-		if(!get_stats_sum(entries)){
+		if (!get_stats_sum(entries)) {
 			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){
-		while(get_next_usr() != NULL)
+	if (reset == 2) {
+		while (get_next_usr() != NULL)
 			stats_reset();
 		return EXIT_SUCCESS;
-
 	}
+
 	/* Need to open shm before it can be reseted */
 	if (stats_mmap(user)) {
 		fprintf(stderr, "Could not map shared memory region to local "
@@ -236,14 +352,25 @@ int main(int argc, char *argv[])
 
 	if (reset) {
 		stats_reset();
-	} else{
+	} else {
 		stats_entry_t *stats;
-		if((stats = malloc(sizeof(stats_entry_t)*ICA_NUM_STATS)) == NULL){
+		if ((stats = malloc(sizeof(stats_entry_t)*ICA_NUM_STATS)) == NULL) {
 			perror("malloc: ");
 			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 -pruN 3.9.0-1/src/icastats_shared.c 4.0.3-0ubuntu1/src/icastats_shared.c
--- 3.9.0-1/src/icastats_shared.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/icastats_shared.c	2022-08-11 07:50:10.000000000 +0000
@@ -27,29 +27,11 @@
 #include "icastats.h"
 #include "init.h"
 
-#define NOT_INITIALIZED (-1)
 #define NAME_LENGHT 20
 
 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
+/* map shared memory segment for statistics
  * Arguments:
  * @user: if user is -1 stats_mmap will open the shared memory segent of the same
  * user.
@@ -62,59 +44,75 @@ static inline void atomic_add(uint64_t *
 
 int stats_mmap(int user)
 {
+	int stats_shm_handle, rc = -1;
 	char shm_id[NAME_LENGHT];
+	struct stat stat_buf;
 
-	if (stats == NULL) {
-		sprintf(shm_id, "icastats_%d",
-			user == -1 ? geteuid() : (uid_t)user);
+	if (stats != NULL)
+		return 0;
 
-		stats_shm_handle = shm_open(shm_id, O_CREAT | O_RDWR,
-						    S_IRUSR | S_IWUSR);
+	sprintf(shm_id, "icastats_%d",
+		user == -1 ? geteuid() : (uid_t)user);
 
-		if (stats_shm_handle == NOT_INITIALIZED)
-			return -1;
+	stats_shm_handle = shm_open(shm_id,
+				    O_CREAT | O_RDWR,
+				    S_IRUSR | S_IWUSR);
 
-		if (user > 0 && geteuid() == 0) {
-			if (fchown(stats_shm_handle, user, user) == -1)
-				return -1;
-		}
+	if (stats_shm_handle == -1)
+		return rc;
 
-		if (ftruncate(stats_shm_handle, STATS_SHM_SIZE) == -1)
-			return -1;
+	if ((user > 0 && geteuid() == 0) &&
+	    (fchown(stats_shm_handle, user, user) == -1))
+		goto end;
 
-		stats = (stats_entry_t *) mmap(NULL, STATS_SHM_SIZE, PROT_READ |
-						 PROT_WRITE, MAP_SHARED,
-						 stats_shm_handle, 0);
-		if (stats == MAP_FAILED){
-			close(stats_shm_handle);
-			stats = NULL;
-			return -1;
-		}
+	if (fstat(stats_shm_handle, &stat_buf))
+		goto end;
+
+	if (ftruncate(stats_shm_handle, STATS_SHM_SIZE) == -1)
+		goto end;
+
+	stats = (stats_entry_t *) mmap(NULL, STATS_SHM_SIZE, PROT_READ |
+					 PROT_WRITE, MAP_SHARED,
+					 stats_shm_handle, 0);
+
+	if (stats == MAP_FAILED) {
+		stats = NULL;
+		goto end;
 	}
-	return 0;
+
+	if (stat_buf.st_size != STATS_SHM_SIZE)
+		memset(stats, 0, STATS_SHM_SIZE);
+
+	rc = 0;
+end:
+	close(stats_shm_handle);
+	return rc;
 }
 
-/* Close and/or delete the shared memory segment
+/* unmap and (optionally) delete the shared memory segment for statistics
  * Argument:
+ * @user: uid for the shm segment handle. If user is -1, the effective uid is used.
  * @unlink - if unlink is true the shared memory segment will be
  * deleted. If it is false it will only be closed.
  */
 
-void stats_munmap(int unlink)
+void stats_munmap(int user, int unlink)
 {
-	char shm_id[NAME_LENGHT];
-	sprintf(shm_id, "icastats_%d", geteuid());
 
 	if (stats == NULL)
 		return;
 
 	munmap(stats, STATS_SHM_SIZE);
-	close(stats_shm_handle);
-	stats_shm_handle = NOT_INITIALIZED;
+	stats = NULL;
+
+	if (unlink == SHM_DESTROY) {
+		char shm_id[NAME_LENGHT];
+
+		sprintf(shm_id, "icastats_%d",
+			user == -1 ? geteuid() : (uid_t)user);
 
-	if(unlink == SHM_DESTROY)
 		shm_unlink(shm_id);
-	stats = NULL;
+	}
 }
 
 /* query the shared memory segment for a specific field
@@ -142,18 +140,87 @@ uint64_t stats_query(stats_fields_t fiel
 			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;
+		}
 	}
 }
 
@@ -176,32 +243,32 @@ int get_stats_sum(stats_entry_t *sum)
 	DIR *shmDir;
 
 	memset(sum, 0, sizeof(stats_entry_t)*ICA_NUM_STATS);
-	if((shmDir = opendir("/dev/shm")) == NULL)
+	if ((shmDir = opendir("/dev/shm")) == NULL)
 		return 0;
 
-	while((direntp = readdir(shmDir)) != NULL){
-		if(strstr(direntp->d_name, "icastats_") != NULL){
+	while ((direntp = readdir(shmDir)) != NULL) {
+		if (strstr(direntp->d_name, "icastats_") != NULL) {
 			int fd;
 			stats_entry_t *tmp;
 
-			if((getpwuid(atoi(&direntp->d_name[9]))) == NULL){
+			if ((getpwuid(atoi(&direntp->d_name[9]))) == NULL) {
 				closedir(shmDir);
 				return 0;
 			}
 
-			if ((fd = shm_open(direntp->d_name, O_RDONLY, 0)) == -1){
+			if ((fd = shm_open(direntp->d_name, O_RDONLY, 0)) == -1) {
 				closedir(shmDir);
 				return 0;
 			}
 			if ((tmp = (stats_entry_t *)mmap(NULL, STATS_SHM_SIZE,
 						    PROT_READ, MAP_SHARED,
-						    fd, 0)) == MAP_FAILED){
+						    fd, 0)) == MAP_FAILED) {
 				closedir(shmDir);
 				close(fd);
 				return 0;
 			}
 
-			for(i = 0; i<ICA_NUM_STATS; ++i){
+			for (i = 0; i<ICA_NUM_STATS; ++i) {
 				sum[i].enc.hw += tmp[i].enc.hw;
 				sum[i].enc.sw += tmp[i].enc.sw;
 				sum[i].dec.hw += tmp[i].dec.hw;
@@ -233,23 +300,23 @@ char *get_next_usr()
 	static DIR *shmDir = NULL;
 
 	/* Closes shm and set stats NULL */
-	stats_munmap(SHM_CLOSE);
+	stats_munmap(-1, SHM_CLOSE);
 
-	if(shmDir == NULL){
-		if((shmDir = opendir("/dev/shm")) == NULL)
+	if (shmDir == NULL) {
+		if ((shmDir = opendir("/dev/shm")) == NULL)
 			return NULL;
 	}
-	while((direntp = readdir(shmDir)) != NULL){
-		if(strstr(direntp->d_name, "icastats_") != NULL){
+	while ((direntp = readdir(shmDir)) != NULL) {
+		if (strstr(direntp->d_name, "icastats_") != NULL) {
 			int uid = atoi(&direntp->d_name[9]);
 			struct passwd *pwd;
-			if((pwd = getpwuid(uid)) == NULL)
+			if ((pwd = getpwuid(uid)) == NULL)
 				return NULL;
-			if(stats_mmap(uid) == -1)
+			if (stats_mmap(uid) == -1)
 				return NULL;
 
 			return pwd->pw_name;
-		} else{
+		} else {
 			continue;
 		}
 	}
@@ -275,16 +342,16 @@ void stats_increment(stats_fields_t fiel
 	if (stats == NULL)
 		return;
 
-	if(direction == ENCRYPT)
+	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
 
@@ -308,15 +375,16 @@ void stats_reset()
 
 int delete_all()
 {
-	stats_munmap(SHM_DESTROY);
+	stats_munmap(-1, SHM_DESTROY);
 	struct dirent *direntp;
 	DIR *shmDir;
-	if((shmDir = opendir("/dev/shm")) == NULL)
+
+	if ((shmDir = opendir("/dev/shm")) == NULL)
 		return 0;
 
-	while((direntp = readdir(shmDir)) != NULL){
-		if(strstr(direntp->d_name, "icastats_") != NULL){
-			if(shm_unlink(direntp->d_name) == -1)
+	while ((direntp = readdir(shmDir)) != NULL) {
+		if (strstr(direntp->d_name, "icastats_") != NULL) {
+			if (shm_unlink(direntp->d_name) == -1)
 				return 0;
 		}
 	}
diff -pruN 3.9.0-1/src/include/icastats.h 4.0.3-0ubuntu1/src/include/icastats.h
--- 3.9.0-1/src/include/icastats.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/include/icastats.h	2022-08-11 07:50:10.000000000 +0000
@@ -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 @@ typedef enum stats_fields {
 	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 @@ typedef enum stats_fields {
 	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 @@ typedef enum stats_fields {
 	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 @@ typedef enum stats_fields {
 	"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 @@ typedef enum stats_fields {
 	"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 @@ typedef enum stats_fields {
 	"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
@@ -158,7 +285,7 @@ typedef enum stats_fields {
 
 
 int stats_mmap(int user);
-void stats_munmap(int unlink);
+void stats_munmap(int user, int unlink);
 uint64_t stats_query(stats_fields_t field, int hardware, int direction);
 void get_stats_data(stats_entry_t *entries);
 void stats_increment(stats_fields_t field, int hardware, int direction);
@@ -167,5 +294,64 @@ char *get_next_usr();
 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 -pruN 3.9.0-1/src/include/rng.h 4.0.3-0ubuntu1/src/include/rng.h
--- 3.9.0-1/src/include/rng.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/include/rng.h	2022-08-11 07:50:10.000000000 +0000
@@ -14,7 +14,7 @@
  * directly via the api.
  */
 void rng_init(void);
-void rng_gen(unsigned char *buf, size_t buflen);
+int rng_gen(unsigned char *buf, size_t buflen);
 void rng_fini(void);
 
 #endif
diff -pruN 3.9.0-1/src/include/s390_aes.h 4.0.3-0ubuntu1/src/include/s390_aes.h
--- 3.9.0-1/src/include/s390_aes.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/include/s390_aes.h	2022-08-11 07:50:10.000000000 +0000
@@ -140,7 +140,7 @@ static inline int s390_aes_gcm(unsigned
 	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 @@ static inline int __s390_aes_ctrlist(uns
 	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 @@ static inline int s390_aes_ecb(unsigned
 				     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 @@ static inline int s390_aes_cbc(unsigned
 				     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 @@ static inline int __s390_aes_cfb(unsigne
 	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 @@ static inline int __s390_aes_ofb(unsigne
 	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 @@ static inline int s390_aes_xts(unsigned
 	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 -pruN 3.9.0-1/src/include/s390_cmac.h 4.0.3-0ubuntu1/src/include/s390_cmac.h
--- 3.9.0-1/src/include/s390_cmac.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/include/s390_cmac.h	2022-08-11 07:50:10.000000000 +0000
@@ -90,7 +90,9 @@ static inline void _stats_increment(unsi
 		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 -pruN 3.9.0-1/src/include/s390_crypto.h 4.0.3-0ubuntu1/src/include/s390_crypto.h
--- 3.9.0-1/src/include/s390_crypto.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/include/s390_crypto.h	2022-08-11 07:50:10.000000000 +0000
@@ -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 -pruN 3.9.0-1/src/include/s390_gcm.h 4.0.3-0ubuntu1/src/include/s390_gcm.h
--- 3.9.0-1/src/include/s390_gcm.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/include/s390_gcm.h	2022-08-11 07:50:10.000000000 +0000
@@ -745,9 +745,13 @@ static inline int s390_aes_gcm_kma(const
 	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 -pruN 3.9.0-1/src/include/s390_prng.h 4.0.3-0ubuntu1/src/include/s390_prng.h
--- 3.9.0-1/src/include/s390_prng.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/include/s390_prng.h	2022-08-11 07:50:10.000000000 +0000
@@ -16,5 +16,6 @@
 
 int s390_prng_init(void);
 int s390_prng(unsigned char *output_data, unsigned int output_length);
+void s390_prng_fini(void);
 #endif
 
diff -pruN 3.9.0-1/src/include/s390_sha.h 4.0.3-0ubuntu1/src/include/s390_sha.h
--- 3.9.0-1/src/include/s390_sha.h	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/include/s390_sha.h	2022-08-11 07:50:10.000000000 +0000
@@ -104,67 +104,67 @@ static const SHA_CONSTANTS sha_constants
 	{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 @@ static inline int is_sha3(unsigned int n
 	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 -pruN 3.9.0-1/src/init.c 4.0.3-0ubuntu1/src/init.c
--- 3.9.0-1/src/init.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/init.c	2022-08-11 07:50:10.000000000 +0000
@@ -65,6 +65,19 @@ void end_sigill_section(struct sigaction
 	sigprocmask(SIG_SETMASK, oldset, NULL);
 }
 
+
+void ica_cleanup(void)
+{
+#if OPENSSL_VERSION_PREREQ(3, 0)
+	if (openssl_provider != NULL)
+		OSSL_PROVIDER_unload(openssl_provider);
+	openssl_provider = NULL;
+	if (openssl_libctx != NULL)
+		OSSL_LIB_CTX_free(openssl_libctx);
+	openssl_libctx = NULL;
+#endif
+}
+
 void __attribute__ ((constructor)) icainit(void)
 {
 	int value;
@@ -74,7 +87,7 @@ void __attribute__ ((constructor)) icain
 	if (!strcmp(program_invocation_name, "icastats"))
 		return;
 
-	if(stats_mmap(-1) == -1){
+	if (stats_mmap(-1) == -1) {
 		syslog(LOG_INFO,
 		  "Failed to access shared memory segment for libica statistics.");
 	}
@@ -139,19 +152,15 @@ void __attribute__ ((constructor)) icain
 #if OPENSSL_VERSION_PREREQ(3, 0)
 	openssl3_initialized = 1;
 #endif
+	/* close the remaining open syslog file descriptor */
+	closelog();
 }
 
 void __attribute__ ((destructor)) icaexit(void)
 {
 	rng_fini();
 
-	stats_munmap(SHM_CLOSE);
-
-#if OPENSSL_VERSION_PREREQ(3, 0)
-	if (openssl_provider != NULL)
-		OSSL_PROVIDER_unload(openssl_provider);
-	if (openssl_libctx != NULL)
-		OSSL_LIB_CTX_free(openssl_libctx);
-#endif
+	s390_prng_fini();
 
+	stats_munmap(-1, SHM_CLOSE);
 }
diff -pruN 3.9.0-1/src/Makefile.am 4.0.3-0ubuntu1/src/Makefile.am
--- 3.9.0-1/src/Makefile.am	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/Makefile.am	2022-08-11 07:50:10.000000000 +0000
@@ -1,4 +1,4 @@
-VERSION = 3:9:0
+VERSION = 4:0:3
 
 AM_CFLAGS = @FLAGS@
 MAJOR := `echo $(VERSION) | cut -d: -f1`
@@ -10,7 +10,7 @@ VERSION1 := $(MAJOR).$(MINOR).$(PATCH)
 
 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_LIBADD = ${LIBS_common}
 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}
@@ -47,6 +47,12 @@ mp.S	: mp.pl
 	./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 -sf .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 -sf .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
@@ -64,7 +70,7 @@ endif
 
 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,18 +79,18 @@ icainfo_CFLAGS = ${icainfo_CFLAGS_COMMON
 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
 
 # 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	\
@@ -110,4 +116,7 @@ internal_tests_ec_internal_test_SOURCES
 		    include/rng.h ../test/testcase.h
 endif
 
-.PHONY: hmac-file hmac-file-lnk
+.PHONY: hmac-file hmac-file-lnk fipsinstall
+
+CLEANFILES = mp.S
+MAINTAINERCLEANFILES = Makefile.in
diff -pruN 3.9.0-1/src/rng.c 4.0.3-0ubuntu1/src/rng.c
--- 3.9.0-1/src/rng.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/rng.c	2022-08-11 07:50:10.000000000 +0000
@@ -8,6 +8,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <syslog.h>
 
 #include "ica_api.h"
@@ -38,7 +39,7 @@ void rng_init(void)
 			     sizeof("INTERNAL INSTANCE"));
 }
 
-void rng_gen(unsigned char *buf, size_t buflen)
+int rng_gen(unsigned char *buf, size_t buflen)
 {
 	const char *rngdev;
 	FILE *rng_fh;
@@ -47,7 +48,7 @@ void rng_gen(unsigned char *buf, size_t
 	if (rng_sh != NULL) {
 	    rc = ica_drbg_generate(rng_sh, 256, false, NULL, 0, buf, buflen);
 	    if (!rc)
-		return;
+		return 0;
 	}
 
 	for (rngdev = RNGDEV[0]; rngdev != NULL; rngdev++) {
@@ -56,13 +57,13 @@ void rng_gen(unsigned char *buf, size_t
 			rc = fread(buf, buflen, 1, rng_fh);
 			fclose(rng_fh);
 			if (rc == 1)
-				return;
+				return 0;
 		}
 	}
 
-	syslog(LOG_ERR, "Libica internal RNG error..");
-	fprintf(stderr, "Libica internal RNG error.");
-	exit(1);
+	/* unable to get any random data. cleanup and return with error */
+	memset(buf, 0, buflen);
+	return 1;
 }
 
 void rng_fini(void)
diff -pruN 3.9.0-1/src/s390_crypto.c 4.0.3-0ubuntu1/src/s390_crypto.c
--- 3.9.0-1/src/s390_crypto.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/s390_crypto.c	2022-08-11 07:50:10.000000000 +0000
@@ -680,14 +680,20 @@ int s390_get_functionlist(libica_func_li
 #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 -pruN 3.9.0-1/src/s390_ecc.c 4.0.3-0ubuntu1/src/s390_ecc.c
--- 3.9.0-1/src/s390_ecc.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/s390_ecc.c	2022-08-11 07:50:10.000000000 +0000
@@ -146,12 +146,12 @@ static EVP_PKEY *make_eckey(int nid, con
 	EC_GROUP *group = NULL;
 	EC_POINT *point = NULL;
 	BIGNUM *bn_priv = NULL;
+#if !OPENSSL_VERSION_PREREQ(3, 0)
+	EC_KEY *ec_key = NULL;
+#else
 	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
 	OSSL_PARAM_BLD *tmpl = NULL;
 	int rc;
 #endif
@@ -175,18 +175,13 @@ static EVP_PKEY *make_eckey(int nid, con
 		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 @@ static EVP_PKEY *make_eckey(int nid, con
 	}
 
 #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 @@ err:
 #else
 	if (tmpl)
 		OSSL_PARAM_BLD_free(tmpl);
+	if (pub_key)
+		OPENSSL_free(pub_key);
 #endif
 
 	if (ok)
@@ -260,7 +262,7 @@ static EVP_PKEY *make_public_eckey(int n
 {
 	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;
@@ -1889,6 +1891,13 @@ unsigned int ecdsa_verify_hw(ica_adapter
 		goto ret;
 	}
 
+	/* Treat return code 12 / 769 also as bad signature as per CCA doc */
+	if (((struct CPRBX*)reply_p)->ccp_rtcode == 12 &&
+		((struct CPRBX*)reply_p)->ccp_rscode == 769) {
+		rc = EFAULT;
+		goto ret;
+	}
+
 	if (((struct CPRBX*)reply_p)->ccp_rtcode != 0 ||
 		((struct CPRBX*)reply_p)->ccp_rscode != 0) {
 		rc = EIO;
@@ -2456,6 +2465,8 @@ int ec_key_check(ICA_EC_KEY *ica_key)
 	BIGNUM *d = NULL, *x = NULL, *y = NULL;
 	int privlen, rc = EINVAL;
 
+	BEGIN_OPENSSL_LIBCTX(openssl_libctx, rc);
+
 	if (!ica_key)
 		goto done;
 
@@ -2487,6 +2498,7 @@ done:
 	if (privkey)
 		EVP_PKEY_free(privkey);
 
+	END_OPENSSL_LIBCTX(rc);
 	return rc;
 }
 
diff -pruN 3.9.0-1/src/s390_prng.c 4.0.3-0ubuntu1/src/s390_prng.c
--- 3.9.0-1/src/s390_prng.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/s390_prng.c	2022-08-11 07:50:10.000000000 +0000
@@ -360,3 +360,9 @@ static int s390_prng_seed(void *srv, uns
 	return rc;
 }
 #endif /* ICA_FIPS */
+
+void s390_prng_fini(void)
+{
+	if (ica_drbg_global != NULL)
+		ica_drbg_uninstantiate(&ica_drbg_global);
+}
diff -pruN 3.9.0-1/src/s390_rsa.c 4.0.3-0ubuntu1/src/s390_rsa.c
--- 3.9.0-1/src/s390_rsa.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/s390_rsa.c	2022-08-11 07:50:10.000000000 +0000
@@ -42,24 +42,24 @@ extern OSSL_LIB_CTX *openssl_libctx;
 #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)
@@ -113,6 +113,7 @@ EVP_PKEY* rsa_key_generate(unsigned int
 	EVP_PKEY *pkey = NULL;
 	EVP_PKEY_CTX *pctx = NULL;
 	BIGNUM *e = NULL;
+	int try;
 
 #ifdef ICA_FIPS
 	if ((fips & ICA_FIPS_MODE) && (!openssl_in_fips_mode()))
@@ -128,7 +129,8 @@ EVP_PKEY* rsa_key_generate(unsigned int
 		} 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;
 	}
@@ -144,7 +146,14 @@ EVP_PKEY* rsa_key_generate(unsigned int
 		goto done;
 	}
 
-	if (EVP_PKEY_keygen(pctx, &pkey) != 1) {
+	/*
+	 * In OpenSSL 3.0 the RSA key gen algorithm has been changed and can now
+	 * fail to generate a key. Retry up to 10 times in such a case.
+	 */
+	for (try = 1; try <= 10; try++) {
+		if (EVP_PKEY_keygen(pctx, &pkey) == 1)
+			break;
+
 		if (pkey)
 			EVP_PKEY_free(pkey);
 		pkey = NULL;
@@ -259,6 +268,8 @@ err:
 #if !OPENSSL_VERSION_PREREQ(3, 0)
 	RSA_free(rsa);
 #else
+	BN_free(n);
+	BN_free(d);
 	EVP_PKEY_free(pkey);
 #endif
 
@@ -410,6 +421,12 @@ err:
 #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
 
@@ -450,9 +467,9 @@ unsigned int rsa_mod_mult_sw(ica_rsa_mod
  * 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 +604,9 @@ unsigned int rsa_mod_expo_sw(ica_rsa_mod
  *
  * 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 +717,11 @@ unsigned int rsa_crt_sw(ica_rsa_modexpo_
 	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 +842,8 @@ unsigned int rsa_crt_sw(ica_rsa_modexpo_
  *
  * 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 +923,9 @@ static unsigned int mod_sw(int arg_lengt
  * 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 +1027,8 @@ static unsigned int mod_sub_sw(int min_l
  * 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 +1096,8 @@ static unsigned int add_sw(int aug_lengt
  *
  * 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 -pruN 3.9.0-1/src/s390_sha.c 4.0.3-0ubuntu1/src/s390_sha.c
--- 3.9.0-1/src/s390_sha.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/src/s390_sha.c	2022-08-11 07:50:10.000000000 +0000
@@ -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 @@ int s390_sha1(unsigned char *iv, unsigne
 	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 @@ int s390_sha224(unsigned char *iv, unsig
 	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 @@ int s390_sha256(unsigned char *iv, unsig
 
 	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 @@ int s390_sha384(unsigned char *iv, unsig
 	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 @@ int s390_sha512(unsigned char *iv, unsig
 	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 @@ int s390_sha512_224(unsigned char *iv, u
 	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 @@ int s390_sha512_256(unsigned char *iv, u
 	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 @@ int s390_sha3_224(unsigned char *iv, uns
 	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 @@ int s390_sha3_256(unsigned char *iv, uns
 	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 @@ int s390_sha3_384(unsigned char *iv, uns
 	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 @@ int s390_sha3_512(unsigned char *iv, uns
 	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 @@ int s390_shake_128(unsigned char *iv, un
 	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 -pruN 3.9.0-1/test/adapter_handle_test.c 4.0.3-0ubuntu1/test/adapter_handle_test.c
--- 3.9.0-1/test/adapter_handle_test.c	1970-01-01 00:00:00.000000000 +0000
+++ 4.0.3-0ubuntu1/test/adapter_handle_test.c	2022-08-11 07:50:10.000000000 +0000
@@ -0,0 +1,36 @@
+/* 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. 2022 */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "ica_api.h"
+#include "testcase.h"
+
+int main(int argc, char **argv)
+{
+	ica_adapter_handle_t adapter_handle;
+	int rc;
+
+	set_verbosity(argc, argv);
+
+	rc = ica_open_adapter(&adapter_handle);
+	if (rc != 0) {
+		V_(perror("ica_open_adapter failed"));
+		return TEST_FAIL;
+	}
+
+	if (adapter_handle > 3) {
+		V_(printf("ica_open_adapter: file descriptor value is greater than 3 (current %d).\n",
+			  adapter_handle));
+		return TEST_FAIL;
+	}
+
+	printf("All adapter handle tests passed.\n");
+	return TEST_SUCC;
+}
diff -pruN 3.9.0-1/test/aes_128_test.c 4.0.3-0ubuntu1/test/aes_128_test.c
--- 3.9.0-1/test/aes_128_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/aes_128_test.c	1970-01-01 00:00:00.000000000 +0000
@@ -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 -pruN 3.9.0-1/test/aes_192_test.c 4.0.3-0ubuntu1/test/aes_192_test.c
--- 3.9.0-1/test/aes_192_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/aes_192_test.c	1970-01-01 00:00:00.000000000 +0000
@@ -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 -pruN 3.9.0-1/test/aes_256_test.c 4.0.3-0ubuntu1/test/aes_256_test.c
--- 3.9.0-1/test/aes_256_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/aes_256_test.c	1970-01-01 00:00:00.000000000 +0000
@@ -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 -pruN 3.9.0-1/test/des_test.c 4.0.3-0ubuntu1/test/des_test.c
--- 3.9.0-1/test/des_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/des_test.c	1970-01-01 00:00:00.000000000 +0000
@@ -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 -pruN 3.9.0-1/test/ecdh_test.c 4.0.3-0ubuntu1/test/ecdh_test.c
--- 3.9.0-1/test/ecdh_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/ecdh_test.c	2022-08-11 07:50:10.000000000 +0000
@@ -339,6 +339,8 @@ int main(int argc, char **argv)
 
 		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 @@ int main(int argc, char **argv)
 		}
 
 		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 @@ int main(int argc, char **argv)
 			errors++;
 
 		ica_ec_key_free(eckey_A);
+		eckey_A = NULL;
 		ica_ec_key_free(eckey_B);
+		eckey_B = NULL;
 		unset_env_icapath();
 	}
 
diff -pruN 3.9.0-1/test/ecdsa_test.c 4.0.3-0ubuntu1/test/ecdsa_test.c
--- 3.9.0-1/test/ecdsa_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/ecdsa_test.c	2022-08-11 07:50:10.000000000 +0000
@@ -225,6 +225,8 @@ int main(int argc, char **argv)
 
 		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 @@ int main(int argc, char **argv)
 			errors++;
 
 		ica_ec_key_free(eckey);
+		eckey = NULL;
 		unset_env_icapath();
 	}
 
diff -pruN 3.9.0-1/test/ec_keygen_test.c 4.0.3-0ubuntu1/test/ec_keygen_test.c
--- 3.9.0-1/test/ec_keygen_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/ec_keygen_test.c	2022-08-11 07:50:10.000000000 +0000
@@ -115,6 +115,8 @@ int main(int argc, char **argv)
 
 			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 @@ int main(int argc, char **argv)
 					}
 				}
 			}
+
+			ica_ec_key_free(eckey);
+			eckey = NULL;
 		}
 
 		if (test_failed)
 			errors++;
 
-		ica_ec_key_free(eckey);
 		unset_env_icapath();
 	}
 
diff -pruN 3.9.0-1/test/get_functionlist_cex_test.c 4.0.3-0ubuntu1/test/get_functionlist_cex_test.c
--- 3.9.0-1/test/get_functionlist_cex_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/get_functionlist_cex_test.c	2022-08-11 07:50:10.000000000 +0000
@@ -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 @@ int main(int argc, char **argv)
 	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 @@ int main(int argc, char **argv)
 		failed++;
 	}
 
+done:
+	free(libica_func_list);
+
 	if (failed) {
 		printf("ica_get_functionlist tests for libica-cex failed.\n");
 		return TEST_FAIL;
diff -pruN 3.9.0-1/test/get_functionlist_test.c 4.0.3-0ubuntu1/test/get_functionlist_test.c
--- 3.9.0-1/test/get_functionlist_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/get_functionlist_test.c	2022-08-11 07:50:10.000000000 +0000
@@ -38,6 +38,12 @@ int main(int argc, char **argv)
 	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 @@ int main(int argc, char **argv)
 		failed++;
 	}
 
+done:
+	free(libica_func_list);
+
 	if (failed) {
 		printf("ica_get_functionlist tests failed.\n");
 		return TEST_FAIL;
diff -pruN 3.9.0-1/test/icastats_test.c.in 4.0.3-0ubuntu1/test/icastats_test.c.in
--- 3.9.0-1/test/icastats_test.c.in	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/icastats_test.c.in	2022-08-11 07:50:10.000000000 +0000
@@ -186,6 +186,7 @@ int is_crypto_card_loaded()
 			}
 			if((c = fgetc(file)) == '1'){
 				fclose(file);
+				closedir(sysDir);
 				return 1;
 			}
 			fclose(file);
diff -pruN 3.9.0-1/test/Makefile.am 4.0.3-0ubuntu1/test/Makefile.am
--- 3.9.0-1/test/Makefile.am	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/Makefile.am	2022-08-11 07:50:10.000000000 +0000
@@ -7,21 +7,16 @@ get_version_test \
 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 \
@@ -57,7 +52,8 @@ ecdh2_test.sh \
 ecdsa2_test.sh \
 eddsa_test \
 x_test \
-mp_test
+mp_test \
+adapter_handle_test
 
 if ICA_INTERNAL_TESTS
 TESTS += \
@@ -68,23 +64,23 @@ TEST_EXTENSIONS = .sh .pl
 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 \
 sha3_512_test shake_128_test shake_256_test rsa_keygen_test \
 rsa_key_check_test rsa_test ec_keygen_test ecdh_test ecdsa_test mp_test \
-eddsa_test x_test get_functionlist_cex_test
+eddsa_test x_test get_functionlist_cex_test adapter_handle_test
 
 EXTRA_DIST = testdata testcase.h rsa_test.h aes_gcm_test.h ecdsa1_test.sh \
 sha2_test.sh ecdh1_test.sh ecdsa2_test.sh ecdh2_test.sh \
@@ -95,3 +91,6 @@ rsa_keygen3072_test.sh rsa_keygen_test.s
 icastats_test.c: icastats_test.c.in
 	@SED@   -e s!\@builddir\@!"@abs_top_builddir@/src/"!g < $< > $@-t
 	mv $@-t $@
+
+CLEANFILES = icastats_test.c
+MAINTAINERCLEANFILES = Makefile.in
diff -pruN 3.9.0-1/test/tdes_test.c 4.0.3-0ubuntu1/test/tdes_test.c
--- 3.9.0-1/test/tdes_test.c	2021-10-13 14:00:38.000000000 +0000
+++ 4.0.3-0ubuntu1/test/tdes_test.c	1970-01-01 00:00:00.000000000 +0000
@@ -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 */
-}
-
