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]);
