Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libzpc for openSUSE:Factory checked 
in at 2026-02-06 21:30:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libzpc (Old)
 and      /work/SRC/openSUSE:Factory/.libzpc.new.1670 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libzpc"

Fri Feb  6 21:30:26 2026 rev:13 rq:1331733 version:1.5.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/libzpc/libzpc.changes    2026-01-07 
16:03:36.772606703 +0100
+++ /work/SRC/openSUSE:Factory/.libzpc.new.1670/libzpc.changes  2026-02-06 
21:31:11.516342153 +0100
@@ -1,0 +2,6 @@
+Fri Feb  6 16:34:24 UTC 2026 - Nikolay Gueorguiev <[email protected]>
+
+- Upgrade libzpc to version 1.5.0 (jsc#PED-14603, jsc#PED-14275, 
jsc#PED-15049) 
+  * [FEATURE] Support live guest relocation
+
+-------------------------------------------------------------------

Old:
----
  libzpc-1.4.1.tar.gz

New:
----
  libzpc-1.5.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libzpc.spec ++++++
--- /var/tmp/diff_new_pack.TvL5xV/_old  2026-02-06 21:31:12.200370852 +0100
+++ /var/tmp/diff_new_pack.TvL5xV/_new  2026-02-06 21:31:12.204371020 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           libzpc
-Version:        1.4.1
+Version:        1.5.0
 Release:        0
 Summary:        IBM Z Protected-key Crypto library
 License:        MIT

++++++ libzpc-1.4.1.tar.gz -> libzpc-1.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/CHANGES.md new/libzpc-1.5.0/CHANGES.md
--- old/libzpc-1.4.1/CHANGES.md 2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/CHANGES.md 2026-02-05 18:05:05.000000000 +0100
@@ -1,6 +1,10 @@
 Changelog {#changes}
 ===
 
+**Version 1.5.0**
+
+- Support for live guest relocation
+
 **Version 1.4.1**
 
 - Bug fixes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/CMakeLists.txt 
new/libzpc-1.5.0/CMakeLists.txt
--- old/libzpc-1.4.1/CMakeLists.txt     2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/CMakeLists.txt     2026-02-05 18:05:05.000000000 +0100
@@ -2,8 +2,8 @@
 set(ZPC_NAME          "libzpc"                            )
 set(ZPC_DESCRIPTION   "IBM Z Protected-key Crypto library")
 set(ZPC_VERSION_MAJOR 1                                   )
-set(ZPC_VERSION_MINOR 4                                   )
-set(ZPC_VERSION_PATCH 1                                   )
+set(ZPC_VERSION_MINOR 5                                   )
+set(ZPC_VERSION_PATCH 0                                   )
 ###########################################################
 
 cmake_minimum_required(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/libzpc.spec new/libzpc-1.5.0/libzpc.spec
--- old/libzpc-1.4.1/libzpc.spec        2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/libzpc.spec        2026-02-05 18:05:05.000000000 +0100
@@ -1,5 +1,5 @@
 Name:          libzpc
-Version:       1.4.1
+Version:       1.5.0
 Release:       1%{?dist}
 Summary:       Open Source library for the IBM Z Protected-key crypto feature
 
@@ -75,6 +75,9 @@
 
 
 %changelog
+* Thu Feb 05 2026 Holger Dengler <[email protected]> - 1.5.0
+- Support for live guest relocation.
+
 * Mon Dec 15 2025 Holger Dengler <[email protected]> - 1.4.1
 - Bug fixes.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/src/aes_cbc.c 
new/libzpc-1.5.0/src/aes_cbc.c
--- old/libzpc-1.4.1/src/aes_cbc.c      2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/src/aes_cbc.c      2026-02-05 18:05:05.000000000 +0100
@@ -26,7 +26,7 @@
 
 static void __aes_cbc_set_iv(struct zpc_aes_cbc *, const u8 iv[16]);
 static int __aes_cbc_crypt(struct zpc_aes_cbc *, u8 *, const u8 *, size_t,
-    unsigned long);
+    unsigned long, size_t *);
 static void __aes_cbc_reset(struct zpc_aes_cbc *);
 static void __aes_cbc_reset_iv(struct zpc_aes_cbc *);
 
@@ -269,6 +269,9 @@
        struct pkey_protkey *protkey;
        unsigned long flags = 0;
        int rc, rv, i;
+       const u8 *in_pos = m;
+       u8 *out_pos = c;
+       size_t bytes_processed = 0, len = mlen;
 
        UNUSED(rv);
 
@@ -315,7 +318,7 @@
                param = &aes_cbc->param;
 
                for (;;) {
-                       rc = __aes_cbc_crypt(aes_cbc, c, m, mlen, flags);
+                       rc = __aes_cbc_crypt(aes_cbc, out_pos, in_pos, len, 
flags, &bytes_processed);
                        if (rc == 0) {
                                break;
                        } else {
@@ -335,6 +338,10 @@
 
                                        rv = 
pthread_mutex_unlock(&aes_cbc->aes_key->lock);
                                        assert(rv == 0);
+
+                                       in_pos += bytes_processed;
+                                       out_pos += bytes_processed;
+                                       len -= bytes_processed;
                                }
                                if (rc)
                                        break;
@@ -355,6 +362,9 @@
        struct pkey_protkey *protkey;
        unsigned long flags = CPACF_M;  /* decrypt */
        int rc, rv, i;
+       const u8 *in_pos = c;
+       u8 *out_pos = m;
+       size_t bytes_processed = 0, len = clen;
 
        UNUSED(rv);
 
@@ -401,7 +411,7 @@
                param = &aes_cbc->param;
 
                for (;;) {
-                       rc = __aes_cbc_crypt(aes_cbc, m, c, clen, flags);
+                       rc = __aes_cbc_crypt(aes_cbc, out_pos, in_pos, len, 
flags, &bytes_processed);
                        if (rc == 0) {
                                break;
                        } else {
@@ -421,6 +431,10 @@
 
                                        rv = 
pthread_mutex_unlock(&aes_cbc->aes_key->lock);
                                        assert(rv == 0);
+
+                                       in_pos += bytes_processed;
+                                       out_pos += bytes_processed;
+                                       len -= bytes_processed;
                                }
                                if (rc)
                                        break;
@@ -467,14 +481,14 @@
 
 static int
 __aes_cbc_crypt(struct zpc_aes_cbc *aes_cbc, u8 * out, const u8 * in,
-    size_t inlen, unsigned long flags)
+    size_t inlen, unsigned long flags, size_t *bytes_processed)
 {
        struct cpacf_kmc_aes_param *param;
        int rc, cc;
 
        param = &aes_cbc->param;
 
-       cc = cpacf_kmc(aes_cbc->fc | flags, param, out, in, inlen);
+       cc = cpacf_kmc(aes_cbc->fc | flags, param, out, in, inlen, 
bytes_processed);
        assert(cc == 0 || cc == 1 || cc == 2);
        if (cc == 1) {
                rc = ZPC_ERROR_WKVPMISMATCH;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/src/aes_ccm.c 
new/libzpc-1.5.0/src/aes_ccm.c
--- old/libzpc-1.4.1/src/aes_ccm.c      2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/src/aes_ccm.c      2026-02-05 18:05:05.000000000 +0100
@@ -33,10 +33,10 @@
 
 static void __aes_ccm_set_iv(struct zpc_aes_ccm *, const u8 *, size_t);
 static int __aes_ccm_crypt(struct zpc_aes_ccm *, u8 *, u8 *, size_t, const u8 
*,
-    size_t, const u8 *, size_t, unsigned long);
+    size_t, const u8 *, size_t, unsigned long, int);
 static int __aes_ccm_cbcmac(struct zpc_aes_ccm *, const u8 *, size_t);
 static int __aes_ccm_ctr(struct zpc_aes_ccm *, u8[16], u8 *, const u8 *,
-    size_t);
+    size_t, int);
 static void __aes_ccm_reset(struct zpc_aes_ccm *);
 static void __aes_ccm_reset_iv(struct zpc_aes_ccm *);
 
@@ -281,7 +281,7 @@
 
                for (;;) {
                        rc = __aes_ccm_crypt(aes_ccm, c, tag, taglen, aad,
-                           aadlen, m, mlen, flags);
+                           aadlen, m, mlen, flags, i);
                        if (rc == 0) {
                                break;
                        } else {
@@ -391,7 +391,7 @@
                for (;;) {
                        memcpy(tmp, tag, taglen);
                        rc = __aes_ccm_crypt(aes_ccm, m, tmp, taglen, aad,
-                           aadlen, c, clen, flags);
+                           aadlen, c, clen, flags, i);
                        if (rc == 0 || rc == ZPC_ERROR_TAGMISMATCH) {
                                break;
                        } else {
@@ -471,7 +471,7 @@
 static int
 __aes_ccm_crypt(struct zpc_aes_ccm *aes_ccm, u8 * out, u8 * tag, size_t taglen,
     const u8 * aad, size_t aadlen, const u8 * in, size_t inlen,
-    unsigned long flags)
+    unsigned long flags, int key_sec)
 {
        struct aes_ccm_flags b0flags;
        u8 b01[32], tmp[16];
@@ -567,7 +567,7 @@
                rc = __aes_ccm_cbcmac(aes_ccm, in, inlen);
                if (rc)
                        goto ret;
-               rc = __aes_ccm_ctr(aes_ccm, tmp, out, in, inlen);
+               rc = __aes_ccm_ctr(aes_ccm, tmp, out, in, inlen, key_sec);
                if (rc)
                        goto ret;
                for (i = 0; i < 16; i++)
@@ -575,7 +575,7 @@
                memcpy(tag, tmp, taglen);
        } else {
                /* decrypt-then-mac */
-               rc = __aes_ccm_ctr(aes_ccm, tmp, out, in, inlen);
+               rc = __aes_ccm_ctr(aes_ccm, tmp, out, in, inlen, key_sec);
                if (rc)
                        goto ret;
                rc = __aes_ccm_cbcmac(aes_ccm, out, inlen);
@@ -642,13 +642,21 @@
 
 static int
 __aes_ccm_ctr(struct zpc_aes_ccm *aes_ccm, u8 tagkey[16], u8 * out,
-    const u8 * in, size_t inlen)
+    const u8 * in, size_t inlen, int key_sec)
 {
        struct aes_ccm_flags aflags;
        unsigned int flags;
        u8 a[16];
        int rc, cc;
        u32 ctr;
+       u8 *in_pos = (u8 *)in;
+       u8 *out_pos = out;
+       size_t len = inlen;
+       size_t bytes_processed, dummy;
+       struct cpacf_kma_gcm_aes_param *param_kma;
+       struct cpacf_kmac_aes_param *param_kmac;
+       struct pkey_protkey *protkey;
+       int rv;
 
        flags = CPACF_KMA_LAAD | CPACF_KMA_HS;
 
@@ -673,7 +681,7 @@
        memset(tagkey, 0, 16);
 
        cc = cpacf_kma(aes_ccm->fc | flags, &aes_ccm->param_kma, tagkey, NULL,
-           0, tagkey, 16);
+           0, tagkey, 16, &dummy);
        /* Either incomplete processing or WKaVP mismatch. */
        assert(cc == 0 || cc == 2 || cc == 1);
        if (cc == 1) {
@@ -681,13 +689,57 @@
                goto ret;
        }
 
-       cc = cpacf_kma(aes_ccm->fc | flags | CPACF_KMA_LPC, &aes_ccm->param_kma,
-           out, NULL, 0, in, inlen);
-       /* Either incomplete processing or WKaVP mismatch. */
-       assert(cc == 0 || cc == 2 || cc == 1);
-       if (cc == 1) {
-               rc = ZPC_ERROR_WKVPMISMATCH;
-               goto ret;
+       for (;;) {
+               flags = len > 16 ? flags : flags | CPACF_KMA_LPC;
+
+               cc = cpacf_kma(aes_ccm->fc | flags, &aes_ccm->param_kma,
+                       out_pos, NULL, 0, in_pos, len, &bytes_processed);
+
+               /* Either incomplete processing or WKaVP mismatch. */
+               assert(cc == 0 || cc == 2 || cc == 1);
+               switch (cc) {
+               case 0:
+               case 2:
+                       /* No wkvp mismatch, but some rest may be left over 
because lpc not yet set */
+                       if (bytes_processed == len) {
+                               rc = 0;
+                               goto ret;
+                       }
+                       in_pos += bytes_processed;
+                       out_pos += bytes_processed;
+                       len -= bytes_processed;
+                       break;
+               case 1:
+                       /* wkvp mismatch, rederive protkey and continue */
+                       if (aes_ccm->aes_key->rand_protk) {
+                               rc = ZPC_ERROR_PROTKEYONLY;
+                               goto ret;
+                       }
+
+                       rv = pthread_mutex_lock(&aes_ccm->aes_key->lock);
+                       assert(rv == 0);
+                       DEBUG
+                               ("aes-ccm context at %p: re-derive protected 
key from %s secure key from aes key at %p",
+                               aes_ccm, key_sec == 0 ? "current" : "old",
+                               aes_ccm->aes_key);
+                       rc = aes_key_sec2prot(aes_ccm->aes_key, key_sec);
+                       param_kma = &aes_ccm->param_kma;
+                       param_kmac = &aes_ccm->param_kmac;
+                       protkey = &aes_ccm->aes_key->prot;
+                       memcpy(param_kma->protkey, protkey->protkey, 
sizeof(param_kma->protkey));
+                       memcpy(param_kmac->protkey, protkey->protkey, 
sizeof(param_kmac->protkey));
+                       rv = pthread_mutex_unlock(&aes_ccm->aes_key->lock);
+                       assert(rv == 0);
+
+                       in_pos += bytes_processed;
+                       out_pos += bytes_processed;
+                       inlen -= bytes_processed;
+                       len = inlen;
+                       break;
+               default:
+                       /* Cannot occur */
+                       break;
+               }
        }
 
        rc = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/src/aes_ecb.c 
new/libzpc-1.5.0/src/aes_ecb.c
--- old/libzpc-1.4.1/src/aes_ecb.c      2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/src/aes_ecb.c      2026-02-05 18:05:05.000000000 +0100
@@ -25,7 +25,7 @@
 #include <string.h>
 
 static int __aes_ecb_crypt(struct zpc_aes_ecb *, u8 *, const u8 *, size_t,
-    unsigned long);
+    unsigned long, size_t *);
 static void __aes_ecb_reset(struct zpc_aes_ecb *);
 
 int
@@ -149,6 +149,9 @@
        struct pkey_protkey *protkey;
        unsigned long flags = 0;
        int rc, rv, i;
+       const u8 *in_pos = m;
+       u8 *out_pos = c;
+       size_t bytes_processed = 0, len = mlen;
 
        UNUSED(rv);
 
@@ -191,7 +194,7 @@
                param = &aes_ecb->param;
 
                for (;;) {
-                       rc = __aes_ecb_crypt(aes_ecb, c, m, mlen, flags);
+                       rc = __aes_ecb_crypt(aes_ecb, out_pos, in_pos, len, 
flags, &bytes_processed);
                        if (rc == 0) {
                                break;
                        } else {
@@ -211,6 +214,10 @@
 
                                        rv = 
pthread_mutex_unlock(&aes_ecb->aes_key->lock);
                                        assert(rv == 0);
+
+                                       in_pos += bytes_processed;
+                                       out_pos += bytes_processed;
+                                       len -= bytes_processed;
                                }
                                if (rc)
                                        break;
@@ -231,6 +238,9 @@
        struct pkey_protkey *protkey;
        unsigned long flags = CPACF_M;  /* decrypt */
        int rc, rv, i;
+       const u8 *in_pos = c;
+       u8 *out_pos = m;
+       size_t bytes_processed = 0, len = clen;
 
        UNUSED(rv);
 
@@ -273,7 +283,7 @@
                param = &aes_ecb->param;
 
                for (;;) {
-                       rc = __aes_ecb_crypt(aes_ecb, m, c, clen, flags);
+                       rc = __aes_ecb_crypt(aes_ecb, out_pos, in_pos, len, 
flags, &bytes_processed);
                        if (rc == 0) {
                                break;
                        } else {
@@ -293,6 +303,10 @@
 
                                        rv = 
pthread_mutex_unlock(&aes_ecb->aes_key->lock);
                                        assert(rv == 0);
+
+                                       in_pos += bytes_processed;
+                                       out_pos += bytes_processed;
+                                       len -= bytes_processed;
                                }
                                if (rc)
                                        break;
@@ -328,14 +342,14 @@
 
 static int
 __aes_ecb_crypt(struct zpc_aes_ecb *aes_ecb, u8 * out, const u8 * in,
-    size_t inlen, unsigned long flags)
+    size_t inlen, unsigned long flags, size_t *bytes_processed)
 {
        struct cpacf_km_aes_param *param;
        int rc, cc;
 
        param = &aes_ecb->param;
 
-       cc = cpacf_km(aes_ecb->fc | flags, param, out, in, inlen);
+       cc = cpacf_km(aes_ecb->fc | flags, param, out, in, inlen, 
bytes_processed);
        assert(cc == 0 || cc == 1 || cc == 2);
        if (cc == 1) {
                rc = ZPC_ERROR_WKVPMISMATCH;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/src/aes_gcm.c 
new/libzpc-1.5.0/src/aes_gcm.c
--- old/libzpc-1.4.1/src/aes_gcm.c      2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/src/aes_gcm.c      2026-02-05 18:05:05.000000000 +0100
@@ -25,7 +25,7 @@
 #include <string.h>
 
 static int __aes_gcm_set_iv(struct zpc_aes_gcm *, const u8 *, size_t);
-static int __aes_gcm_crypt(struct zpc_aes_gcm *, u8 *, u8 *, size_t, const u8 
*,
+static int __aes_gcm_crypt(struct zpc_aes_gcm *, u8 *, u8 *, u8 *, size_t, 
const u8 *,
     size_t, const u8 *, size_t, unsigned long);
 static void __aes_gcm_reset(struct zpc_aes_gcm *);
 static void __aes_gcm_reset_iv(struct zpc_aes_gcm *);
@@ -373,8 +373,6 @@
 
        if ((m != NULL && c != NULL) || tag != NULL) {
                flags |= CPACF_KMA_LAAD;
-               if (tag != NULL)
-                       flags |= CPACF_KMA_LPC;
        }
        aes_gcm->param.taadl += (aadlen * 8);
        aes_gcm->param.tpcl += (mlen * 8);
@@ -387,7 +385,7 @@
                param = &aes_gcm->param;
 
                for (;;) {
-                       rc = __aes_gcm_crypt(aes_gcm, c, tag, taglen, aad,
+                       rc = __aes_gcm_crypt(aes_gcm, c, tag, tag, taglen, aad,
                            aadlen, m, mlen, flags);
                        if (rc == 0) {
                                break;
@@ -501,8 +499,6 @@
 
        if ((m != NULL && c != NULL) || tag != NULL) {
                flags |= CPACF_KMA_LAAD;
-               if (tag != NULL)
-                       flags |= CPACF_KMA_LPC;
        }
        aes_gcm->param.taadl += (aadlen * 8);
        aes_gcm->param.tpcl += (clen * 8);
@@ -515,7 +511,7 @@
                param = &aes_gcm->param;
 
                for (;;) {
-                       rc = __aes_gcm_crypt(aes_gcm, m, tmp, sizeof(tmp), aad,
+                       rc = __aes_gcm_crypt(aes_gcm, m, (u8 *)tag, tmp, 
sizeof(tmp), aad,
                            aadlen, c, clen, flags);
                        if (rc == 0) {
                                rc = memcmp_consttime(tmp, tag, taglen);
@@ -581,6 +577,7 @@
        size_t ivpadlen;
        u64 *ivpad = NULL;
        int rc, cc;
+       unsigned long dummy;
 
        assert(aes_gcm != NULL);
        assert(iv != NULL);
@@ -613,7 +610,8 @@
 
                memset(param->j0, 0, sizeof(param->j0));
 
-               cc = cpacf_kma(aes_gcm->fc, param, NULL, (u8 *) ivpad, 
ivpadlen, NULL, 0);
+               cc = cpacf_kma(aes_gcm->fc, param, NULL, (u8 *) ivpad, ivpadlen,
+                   NULL, 0, &dummy);
                /* Either incomplete processing or WKaVP mismatch. */
                assert(cc == 2 || cc == 1);
                if (cc == 1) {
@@ -634,25 +632,142 @@
 }
 
 static int
-__aes_gcm_crypt(struct zpc_aes_gcm *aes_gcm, u8 * out, u8 * tag, size_t taglen,
+__aes_kma_crypt(struct zpc_aes_gcm *aes_gcm, u8 * out, const u8 *ori_tag,
+                       const u8 * aad, size_t aadlen,
+                       u8 * in, size_t inlen, unsigned long flags)
+{
+       struct cpacf_kma_gcm_aes_param *param;
+       struct pkey_protkey *protkey;
+       int rc, cc, lpc_set = 0;
+       u8 *in_pos = in;
+       u8 *out_pos = out;
+       size_t len = inlen;
+       unsigned long bytes_processed;
+       int key_sec = AES_KEY_SEC_CUR;
+       int rv;
+
+       param = &aes_gcm->param;
+       protkey = &aes_gcm->aes_key->prot;
+
+       /*
+        * Process AAD before data. In case of an LGR this can be retried as a
+        * whole, as there are no possibly overlapping in and out buffers. This
+        * retry can be done via the old code.
+        */
+       for (;;) {
+               if (aadlen == 0)
+                       break;
+
+               cc = cpacf_kma(aes_gcm->fc | flags, param, NULL, aad, aadlen, 
NULL, 0, &bytes_processed);
+               assert(cc == 0 || cc == 1 || cc == 2);
+               if (cc == 1) {
+                       rc = ZPC_ERROR_WKVPMISMATCH;
+                       goto ret;
+               } else {
+                       break;
+               }
+       }
+
+       /*
+        * At this point all AAD have been processed correctly. Now process data
+        * with possibly overlapping in and out buffers. Note that even with a 
zero
+        * data length this code must be executed for a correct tag.
+        */
+       for (;;) {
+
+               if (len <= 16 && ori_tag != NULL) {
+                       if (in_pos != NULL && out_pos != NULL) {
+                               flags |= CPACF_KMA_LPC;
+                               lpc_set = 1;
+                       }
+               }
+
+               cc = cpacf_kma(aes_gcm->fc | flags, param, out_pos, NULL, 0, 
in_pos, len, &bytes_processed);
+
+               /* Either incomplete processing or WKaVP mismatch. */
+               assert(cc == 0 || cc == 2 || cc == 1);
+               switch (cc) {
+               case 0:
+               case 2:
+                       /* No wkvp mismatch, but some rest may be left over 
because lpc not yet set */
+                       if (bytes_processed == len) {
+                               rc = 0;
+                               if (!lpc_set) {
+                                       /* If data was a multiple of 16, we 
didn't set lpc above */
+                                       if (ori_tag != NULL) {
+                                               flags |= CPACF_KMA_LPC;
+                                               cc = cpacf_kma(aes_gcm->fc | 
flags, param, NULL, NULL, 0, NULL, 0, &bytes_processed);
+                                       }
+                               }
+                               goto ret;
+                       }
+                       in_pos += bytes_processed;
+                       out_pos += bytes_processed;
+                       len -= bytes_processed;
+                       break;
+               case 1:
+                       /* wkvp mismatch, rederive protkey and continue */
+                       if (aes_gcm->aes_key->rand_protk) {
+                               rc = ZPC_ERROR_PROTKEYONLY;
+                               goto ret;
+                       }
+
+                       rc = -1;
+                       rv = pthread_mutex_lock(&aes_gcm->aes_key->lock);
+                       assert(rv == 0);
+                       for (;;) {
+                               DEBUG
+                                       ("aes-gcm context at %p: re-derive 
protected key from %s secure key from aes key at %p",
+                                       aes_gcm, key_sec == 0 ? "current" : 
"old",
+                                       aes_gcm->aes_key);
+                               rc = aes_key_sec2prot(aes_gcm->aes_key, 
key_sec);
+                               if (rc == ZPC_ERROR_IOCTLBLOB2PROTK2) {
+                                       key_sec = key_sec == AES_KEY_SEC_CUR ? 
AES_KEY_SEC_OLD : AES_KEY_SEC_CUR;
+                                       continue;
+                               } else {
+                                       break;
+                               }
+                       }
+                       memcpy(param->protkey, protkey->protkey, 
sizeof(param->protkey));
+                       rv = pthread_mutex_unlock(&aes_gcm->aes_key->lock);
+                       assert(rv == 0);
+
+                       in_pos += bytes_processed;
+                       out_pos += bytes_processed;
+                       inlen -= bytes_processed;
+                       len = inlen;
+                       break;
+               default:
+                       /* Cannot occur */
+                       break;
+               }
+       }
+
+       rc = 0;
+
+ret:
+       return rc;
+}
+
+static int
+__aes_gcm_crypt(struct zpc_aes_gcm *aes_gcm, u8 * out, u8 *ori_tag, u8 * tag, 
size_t taglen,
     const u8 * aad, size_t aadlen, const u8 * in, size_t inlen,
     unsigned long flags)
 {
        struct cpacf_kma_gcm_aes_param *param;
-       int rc, cc;
+       int rc;
 
        param = &aes_gcm->param;
 
-       cc = cpacf_kma(aes_gcm->fc | flags, param, out, aad, aadlen, in, inlen);
-       assert(cc == 0 || cc == 1 || cc == 2);
-       if (cc == 1) {
-               rc = ZPC_ERROR_WKVPMISMATCH;
+       rc = __aes_kma_crypt(aes_gcm, out, ori_tag, aad, aadlen, (u8 *)in, 
inlen, flags);
+       if (rc != 0) {
                goto err;
        }
        aes_gcm->fc |= CPACF_KMA_HS;
 
-       memcpy(tag, param->t, taglen);
-       rc = 0;
+       if (tag != NULL)
+               memcpy(tag, param->t, taglen);
+
 err:
        return rc;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/src/aes_xts.c 
new/libzpc-1.5.0/src/aes_xts.c
--- old/libzpc-1.4.1/src/aes_xts.c      2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/src/aes_xts.c      2026-02-05 18:05:05.000000000 +0100
@@ -27,7 +27,7 @@
 static int __aes_xts_set_iv(struct zpc_aes_xts *, const u8 *);
 static int __aes_xts_set_intermediate_iv(struct zpc_aes_xts *, const u8 
iv[16]);
 static int __aes_xts_crypt(struct zpc_aes_xts *, u8 *, const u8 *, size_t,
-    unsigned long);
+    unsigned long, size_t *);
 static void __aes_xts_reset(struct zpc_aes_xts *);
 static void __aes_xts_reset_iv(struct zpc_aes_xts *);
 
@@ -342,6 +342,9 @@
        unsigned long flags = 0;
        u8 *param;
        int rc, rv, i;
+       const u8 *in_pos = m;
+       u8 *out_pos = c;
+       size_t bytes_processed = 0, len = mlen;
 
        UNUSED(rv);
 
@@ -388,7 +391,7 @@
                param = aes_xts->param_km;
 
                for (;;) {
-                       rc = __aes_xts_crypt(aes_xts, c, m, mlen, flags);
+                       rc = __aes_xts_crypt(aes_xts, out_pos, in_pos, len, 
flags, &bytes_processed);
                        if (rc == 0) {
                                break;
                        } else {
@@ -409,6 +412,10 @@
 
                                        rv = 
pthread_mutex_unlock(&aes_xts->aes_key1->lock);
                                        assert(rv == 0);
+
+                                       in_pos += bytes_processed;
+                                       out_pos += bytes_processed;
+                                       len -= bytes_processed;
                                }
                                if (rc)
                                        break;
@@ -429,6 +436,9 @@
        unsigned long flags = CPACF_M;  /* decrypt */
        u8 *param;
        int rc, rv, i;
+       const u8 *in_pos = c;
+       u8 *out_pos = m;
+       size_t bytes_processed = 0, len = clen;
 
        UNUSED(rv);
 
@@ -475,7 +485,7 @@
                param = aes_xts->param_km;
 
                for (;;) {
-                       rc = __aes_xts_crypt(aes_xts, m, c, clen, flags);
+                       rc = __aes_xts_crypt(aes_xts, out_pos, in_pos, len, 
flags, &bytes_processed);
                        if (rc == 0) {
                                break;
                        } else {
@@ -496,6 +506,10 @@
 
                                        rv = 
pthread_mutex_unlock(&aes_xts->aes_key1->lock);
                                        assert(rv == 0);
+
+                                       in_pos += bytes_processed;
+                                       out_pos += bytes_processed;
+                                       len -= bytes_processed;
                                }
                                if (rc)
                                        break;
@@ -586,7 +600,7 @@
 
 static int
 __aes_xts_crypt(struct zpc_aes_xts *aes_xts, u8 * out, const u8 * in,
-    size_t inlen, unsigned long flags)
+    size_t inlen, unsigned long flags, size_t *bytes_processed)
 {
        int rc, cc;
        size_t rem;
@@ -596,7 +610,8 @@
        inlen &= ~(size_t)0xf;
 
        if (rem == 0) {
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in, 
inlen);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in,
+                   inlen, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
@@ -610,7 +625,8 @@
 
        if (!(flags & CPACF_M)) {
                /* ciphertext-stealing (encrypt) */
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in, 
inlen + 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in,
+                   inlen + 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
@@ -621,7 +637,8 @@
                memcpy(tmp + rem, out + inlen + rem, 16 - rem);
                memcpy(out + inlen + 16, out + inlen, rem);
 
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen, tmp, 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km,
+                   out + inlen, tmp, 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
@@ -629,10 +646,11 @@
                }
        } else if ((flags & CPACF_M)) {
                /* ciphertext-stealing (decrypt) */
-       u8 xtsparam[16], buf[16];
+               u8 xtsparam[16], buf[16];
 
                if (inlen) {
-                       cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, 
out, in, inlen);
+                       cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km,
+                           out, in, inlen, bytes_processed);
                        assert(cc == 0 || cc == 2 || cc == 1);
                        if (cc == 1) {
                                rc = ZPC_ERROR_WKVPMISMATCH;
@@ -642,13 +660,15 @@
 
                memcpy(xtsparam, aes_xts->param_km + 
AES_XTS_KM_XTSPARAM(aes_xts->aes_key1->keysize), 16);
 
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, buf, in + 
inlen, 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, buf,
+                   in + inlen, 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
                        goto ret;
                }
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen, in + inlen, 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km,
+                   out + inlen, in + inlen, 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
@@ -661,7 +681,8 @@
 
                memcpy(aes_xts->param_km + 
AES_XTS_KM_XTSPARAM(aes_xts->aes_key1->keysize), xtsparam, 16);
 
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen, tmp, 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km,
+                   out + inlen, tmp, 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/src/aes_xts_full.c 
new/libzpc-1.5.0/src/aes_xts_full.c
--- old/libzpc-1.4.1/src/aes_xts_full.c 2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/src/aes_xts_full.c 2026-02-05 18:05:05.000000000 +0100
@@ -28,7 +28,8 @@
 
 static int __aes_xts_full_set_iv(struct zpc_aes_xts_full *, const u8 *);
 static int __aes_xts_full_set_intermediate_state(struct zpc_aes_xts_full *, 
const u8 state[32]);
-static int __aes_xts_full_crypt(struct zpc_aes_xts_full *, u8 *, const u8 *, 
size_t, unsigned long);
+static int __aes_xts_full_crypt(struct zpc_aes_xts_full *, u8 *, const u8 *,
+    size_t, unsigned long, size_t *);
 static void __aes_xts_full_reset(struct zpc_aes_xts_full *);
 static void __aes_xts_full_reset_iv(struct zpc_aes_xts_full *);
 
@@ -294,6 +295,9 @@
        unsigned long flags = 0;
        u8 *param;
        int rc, rv;
+       const u8 *in_pos = m;
+       u8 *out_pos = c;
+       size_t bytes_processed = 0, len = mlen;
 
        UNUSED(rv);
 
@@ -337,7 +341,8 @@
        param = aes_xts->param_km;
 
        for (;;) {
-               rc = __aes_xts_full_crypt(aes_xts, c, m, mlen, flags);
+               rc = __aes_xts_full_crypt(aes_xts, out_pos, in_pos, len, flags,
+                       &bytes_processed);
                if (rc == 0) {
                        break;
                } else {
@@ -359,6 +364,10 @@
 
                                rv = 
pthread_mutex_unlock(&aes_xts->xts_key->lock);
                                assert(rv == 0);
+
+                               in_pos += bytes_processed;
+                               out_pos += bytes_processed;
+                               len -= bytes_processed;
                        }
                        if (rc)
                                break;
@@ -377,6 +386,9 @@
        unsigned long flags = CPACF_M;  /* decrypt */
        u8 *param;
        int rc, rv;
+       const u8 *in_pos = c;
+       u8 *out_pos = m;
+       size_t bytes_processed = 0, len = clen;
 
        UNUSED(rv);
 
@@ -420,7 +432,8 @@
        param = aes_xts->param_km;
 
        for (;;) {
-               rc = __aes_xts_full_crypt(aes_xts, m, c, clen, flags);
+               rc = __aes_xts_full_crypt(aes_xts, out_pos, in_pos, len, flags,
+                       &bytes_processed);
                if (rc == 0) {
                        break;
                } else {
@@ -442,6 +455,10 @@
 
                                rv = 
pthread_mutex_unlock(&aes_xts->xts_key->lock);
                                assert(rv == 0);
+
+                               in_pos += bytes_processed;
+                               out_pos += bytes_processed;
+                               len -= bytes_processed;
                        }
                        if (rc)
                                break;
@@ -515,7 +532,8 @@
 }
 
 static int __aes_xts_full_crypt(struct zpc_aes_xts_full *aes_xts, u8 * out,
-               const u8 * in, size_t inlen, unsigned long flags)
+               const u8 * in, size_t inlen, unsigned long flags,
+               size_t * bytes_processed)
 {
        int rc, cc;
        size_t rem;
@@ -525,7 +543,8 @@
        inlen &= ~(size_t)0xf;
 
        if (rem == 0) {
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in, 
inlen);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in,
+                       inlen, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
@@ -539,7 +558,8 @@
 
        if (!(flags & CPACF_M)) {
                /* ciphertext-stealing (encrypt) */
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in, 
inlen + 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in,
+                       inlen + 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
@@ -550,7 +570,8 @@
                memcpy(tmp + rem, out + inlen + rem, 16 - rem);
                memcpy(out + inlen + 16, out + inlen, rem);
 
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen, tmp, 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen,
+                       tmp, 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
@@ -562,7 +583,8 @@
                u8 nap_n1[16];
 
                if (inlen) {
-                       cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, 
out, in, inlen);
+                       cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, 
out, in,
+                               inlen, bytes_processed);
                        assert(cc == 0 || cc == 2 || cc == 1);
                        if (cc == 1) {
                                rc = ZPC_ERROR_WKVPMISMATCH;
@@ -573,13 +595,15 @@
                memcpy(xtsparam, aes_xts->param_km + 
AES_FXTS_TWEAK_OFFSET(aes_xts->xts_key->keysize), 16);
                memcpy(nap_n1, aes_xts->param_km + 
AES_FXTS_NAP_OFFSET(aes_xts->xts_key->keysize), 16);
 
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, buf, in + 
inlen, 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, buf,
+                       in + inlen, 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
                        goto ret;
                }
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen, in + inlen, 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen,
+                       in + inlen, 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
@@ -593,7 +617,8 @@
                memcpy(aes_xts->param_km + 
AES_FXTS_TWEAK_OFFSET(aes_xts->xts_key->keysize), xtsparam, 16);
                memcpy(aes_xts->param_km + 
AES_FXTS_NAP_OFFSET(aes_xts->xts_key->keysize), nap_n1, 16);
 
-               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen, tmp, 16);
+               cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + 
inlen,
+                       tmp, 16, bytes_processed);
                assert(cc == 0 || cc == 2 || cc == 1);
                if (cc == 1) {
                        rc = ZPC_ERROR_WKVPMISMATCH;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/src/cpacf.h new/libzpc-1.5.0/src/cpacf.h
--- old/libzpc-1.4.1/src/cpacf.h        2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/src/cpacf.h        2026-02-05 18:05:05.000000000 +0100
@@ -54,7 +54,7 @@
 
 static inline int
 cpacf_km(unsigned long fc, void *param, u8 * out, const u8 * in,
-    unsigned long inlen)
+    unsigned long inlen, unsigned long *bytes_processed)
 {
         /* *INDENT-OFF* */
        register unsigned long r0 __asm__("0") = (unsigned long) fc;
@@ -76,6 +76,9 @@
        );
         /* *INDENT-ON* */
 
+       if (bytes_processed != NULL)
+               *bytes_processed = fc ? inlen - r3 : r3;
+
        return cc;
 }
 
@@ -93,7 +96,8 @@
 };
 
 static inline int
-cpacf_kmc(unsigned long fc, void *param, u8 * out, const u8 * in, long inlen)
+cpacf_kmc(unsigned long fc, void *param, u8 * out, const u8 * in, long inlen,
+          unsigned long *bytes_processed)
 {
         /* *INDENT-OFF* */
        register unsigned long r0 __asm__("0") = (unsigned long) fc;
@@ -115,6 +119,9 @@
        );
         /* *INDENT-ON* */
 
+       if (bytes_processed != NULL)
+               *bytes_processed = fc ? inlen - r3 : r3;
+
        return cc;
 }
 
@@ -263,7 +270,8 @@
 /*  KMA (cipher message with authentication) */
 static inline int
 cpacf_kma(unsigned long fc, void *param, u8 * out, const u8 * aad,
-    unsigned long aadlen, const u8 * in, unsigned long inlen)
+    unsigned long aadlen, const u8 * in, unsigned long inlen,
+    unsigned long *bytes_processed)
 {
         /* *INDENT-OFF* */
         register unsigned long r0 __asm__("0") = (unsigned long)fc;
@@ -288,6 +296,9 @@
         );
         /* *INDENT-ON* */
 
+       if (bytes_processed != NULL)
+               *bytes_processed = fc ? inlen - r3 : r3;
+
        return cc;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzpc-1.4.1/src/globals.c 
new/libzpc-1.5.0/src/globals.c
--- old/libzpc-1.4.1/src/globals.c      2025-12-16 08:50:22.000000000 +0100
+++ new/libzpc-1.5.0/src/globals.c      2026-02-05 18:05:05.000000000 +0100
@@ -215,7 +215,7 @@
                DEBUG("detected message-security-assist");
 
                memset(status_word, 0, sizeof(status_word));
-               cpacf_km(CPACF_KM_QUERY, &status_word, NULL, NULL, 0);
+               cpacf_km(CPACF_KM_QUERY, &status_word, NULL, NULL, 0, NULL);
                DEBUG("status word km: 0x%016llx:0x%016llx", status_word[0],
                    status_word[1]);
 
@@ -241,7 +241,7 @@
                }
 
                memset(status_word, 0, sizeof(status_word));
-               cpacf_kmc(CPACF_KMC_QUERY, &status_word, NULL, NULL, 0);
+               cpacf_kmc(CPACF_KMC_QUERY, &status_word, NULL, NULL, 0, NULL);
                DEBUG("status word kmc: 0x%016llx:0x%016llx", status_word[0],
                    status_word[1]);
 
@@ -314,7 +314,7 @@
 
                memset(status_word, 0, sizeof(status_word));
                cpacf_kma(CPACF_KMA_QUERY, &status_word, NULL, NULL, 0, NULL,
-                   0);
+                   0, NULL);
                DEBUG("status word kma: 0x%016llx:0x%016llx", status_word[0],
                    status_word[1]);
 

Reply via email to