Hi Nageswara,
Thanks for taking a look.

On 8/28/26 4:34 PM, R Nageswara Sastry wrote:
On 27. 08. 2026 11: 53 AM, Srish Srinivasan wrote: The PKWM trusted source uses a single wrapping key per LPAR, created only once during trust source initialization. All the wrap and unwrap requests are bound to this default wrapping key. Implement



On 27.08.2026 11:53 AM, Srish Srinivasan wrote:
The PKWM trusted source uses a single wrapping key per LPAR, created only
once during trust source initialization. All the wrap and unwrap requests
are bound to this default wrapping key.

Implement H_PKS_REVOKE_OBJECT, H_PKS_UNREVOKE_OBJECT, and
H_PKS_GET_OBJECTLABELS HCALLs to enable support for revoking and unrevoking
PKWM wrapping keys, and for retrieving wrapping key labels. The label
retrieval operation (H_PKS_GET_OBJECTLABELS) applies to all wrapping keys
including the default one, while the life cycle operations
(H_PKS_REVOKE_OBJECT/H_PKS_UNREVOKE_OBJECT) apply only to user-created
wrapping keys.

Signed-off-by: Srish Srinivasan<[email protected]>
---
  Documentation/arch/powerpc/papr_hcalls.rst |  33 ++
  arch/powerpc/include/asm/hvcall.h          |   5 +-
  arch/powerpc/include/asm/plpks.h           |  15 +
  arch/powerpc/platforms/pseries/plpks.c     | 475 ++++++++++++++++++++-
  4 files changed, 524 insertions(+), 4 deletions(-)

diff --git a/Documentation/arch/powerpc/papr_hcalls.rst 
b/Documentation/arch/powerpc/papr_hcalls.rst
index 44c9c8b32ae3..3455b403a048 100644
--- a/Documentation/arch/powerpc/papr_hcalls.rst
+++ b/Documentation/arch/powerpc/papr_hcalls.rst
@@ -343,6 +343,39 @@ is returned to the caller.
  H_PKS_UNWRAP_OBJECT is used to unwrap an object that was previously wrapped 
with
  H_PKS_WRAP_OBJECT.
+**H_PKS_REVOKE_OBJECT**
+
+| Input: authorization, objectlabel, objectlabellen, flags
+| Out: *object policy*
+| Return Value: *H_Success, H_Function, H_State, H_Parameter, H_P2, H_P3, H_P4,
+                H_Authority, H_Not_Found, H_Busy, H_Aborted*
+
+H_PKS_REVOKE_OBJECT is used to revoke an object in Platform Keystore.
+
+
+**H_PKS_UNREVOKE_OBJECT**
+
+| Input: authorization, objectlabel, objectlabellen, flags
+| Out: *object policy*
+| Return Value: *H_Success, H_Function, H_State, H_Parameter, H_P2, H_P3, H_P4,
+                H_Authority, H_Not_Found, H_Busy, H_Aborted*
+
+H_PKS_UNREVOKE_OBJECT is used to unrevoke an object that was previously revoked
+with H_PKS_REVOKE_OBJECT in Platform Keystore.
+
+
+**H_PKS_GET_OBJECTLABELS**
+
+| Input: authorization, continueToken, out, outlen
+| Out: *continue-token, number of object labels in the returned list, object
+        label list*
+| Return Value: *H_Success, H_Function, H_State, H_Parameter, H_P2, H_P3, H_P4,
+                H_Authority, H_Busy, H_Aborted, H_Continue*
+
+H_PKS_GET_OBJECTLABELS is used to retrieve a list of object labels owned by the
+specified consumer.
+
+
  References
  ==========
  .. [1] "Power Architecture Platform Reference"
diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index dff90a7d7f70..4d4c2ce1dd87 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -340,6 +340,7 @@
  #define H_PKS_GET_CONFIG      0x41C
  #define H_PKS_SET_PASSWORD    0x420
  #define H_PKS_GEN_PASSWORD    0x424
+#define H_PKS_GET_OBJECTLABELS 0x428
  #define H_PKS_WRITE_OBJECT    0x42C
  #define H_PKS_GEN_KEY         0x430
  #define H_PKS_READ_OBJECT     0x434
@@ -362,7 +363,9 @@
  #define H_GUEST_DELETE                0x488
  #define H_PKS_WRAP_OBJECT     0x490
  #define H_PKS_UNWRAP_OBJECT   0x494
-#define MAX_HCALL_OPCODE       H_PKS_UNWRAP_OBJECT
+#define H_PKS_REVOKE_OBJECT    0x4AC
+#define H_PKS_UNREVOKE_OBJECT  0x4B0
+#define MAX_HCALL_OPCODE       H_PKS_UNREVOKE_OBJECT
/* Scope args for H_SCM_UNBIND_ALL */
  #define H_UNBIND_SCOPE_ALL (0x1)
diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
index 8b2ffb27db5a..c39d1f07017e 100644
--- a/arch/powerpc/include/asm/plpks.h
+++ b/arch/powerpc/include/asm/plpks.h
@@ -25,6 +25,7 @@
  #define PLPKS_SIGNEDUPDATE    PPC_BIT32(7) // Object can only be modified by 
signed updates
  #define PLPKS_WRAPPINGKEY     PPC_BIT32(8) // Object contains a wrapping key
  #define PLPKS_HVPROVISIONED   PPC_BIT32(28) // Hypervisor has provisioned 
this object
+#define PLPKS_REVOKED          PPC_BIT32(30) // Object is revoked
// Signature algorithm flags from signed_update_algorithms
  #define PLPKS_ALG_RSA2048     PPC_BIT(0)
@@ -123,6 +124,20 @@ int plpks_wrap_object(u8 **input_buf, u64 input_len, u16 
wrap_flags,
int plpks_unwrap_object(u8 **input_buf, u64 input_len,
                        u8 **output_buf, u64 *output_len);
+
+int plpks_revoke_wrapping_key(struct plpks_var *var);
+
+int plpks_unrevoke_wrapping_key(struct plpks_var *var);
+
+int plpks_del_wrapping_key(struct plpks_var *var);
+
+int plpks_is_wrapping_key_revoked(struct plpks_var *var);
+
+int plpks_get_object_labels(u8 **output_buf, u64 *output_len,
+                           char *comp_prefix);
+
+bool plpks_revoke_is_supported(void);
+
  #else // CONFIG_PSERIES_PLPKS
  static inline bool plpks_is_available(void) { return false; }
  static inline u16 plpks_get_passwordlen(void) { BUILD_BUG(); }
diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index b553f7b130b6..48a86497eb2b 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -23,8 +23,17 @@
   */
  #define PLPKS_WRAPPING_BUF_DIFF       1024
+/*
+ * Maximum length for the buffer to store the retrieved object labels
+ */
+#define PLPKS_OBJLABEL_BUF_MAX 2550
+
+#define PLPKS_OBJLABEL_LEN_FIELD_SIZE  2
+#define PLPKS_OBJLABEL_PREFIX_LEN      8
+
  #define PLPKS_WRAP_INTERFACE_BIT      3
  #define PLPKS_WRAPPING_KEY_LENGTH     32
+#define PLPKS_REVOKE_INTERFACE_BIT     4
#define WRAPFLAG_BE_BIT_SET(be_bit) \
        BIT_ULL(63 - (be_bit))
@@ -46,6 +55,7 @@
  #include <linux/libfdt.h>
  #include <linux/memblock.h>
  #include <linux/bitfield.h>
+#include <linux/unaligned.h>
  #include <asm/hvcall.h>
  #include <asm/machdep.h>
  #include <asm/plpks.h>
@@ -67,6 +77,7 @@ static u32 maxlargeobjectsize;
  static u64 signedupdatealgorithms;
  static u64 wrappingfeatures;
  static bool wrapsupport;
+static bool revokesupport;
struct plpks_auth {
        u8 version;
@@ -146,6 +157,9 @@ static int pseries_status_to_err(int rc)
        case H_ABORTED:
                err = -EIO;
                break;
+       case H_CONTINUE:
+               err = -EAGAIN;
+               break;
        default:
                err = -EINVAL;
        }
@@ -312,6 +326,7 @@ static int _plpks_get_config(void)
        signedupdatealgorithms = be64_to_cpu(config->signedupdatealgorithms);
        wrappingfeatures = be64_to_cpu(config->wrappingfeatures);
        wrapsupport = config->flags & PPC_BIT8(PLPKS_WRAP_INTERFACE_BIT);
+       revokesupport = config->flags & PPC_BIT8(PLPKS_REVOKE_INTERFACE_BIT);
// Validate that the numbers we get back match the requirements of the spec
        if (maxpwsize < 32) {
@@ -831,9 +846,6 @@ static int plpks_read_var(u8 consumer, struct plpks_var 
*var)
        if (var->namelen > PLPKS_MAX_NAME_SIZE)
                return -EINVAL;
- if (var->policy & PLPKS_WRAPPINGKEY)
-               return -EPERM;
-
        auth = construct_auth(consumer);
        if (IS_ERR(auth))
                return PTR_ERR(auth);
@@ -903,6 +915,23 @@ bool plpks_wrapping_is_supported(void)
  }
  EXPORT_SYMBOL_GPL(plpks_wrapping_is_supported);
+/**
+ * plpks_revoke_is_supported() - Get the H_PKS_REVOKE_OBJECT and
+ * H_PKS_UNREVOKE_OBJECT interfaces availability status for the LPAR.
+ *
+ * Successful execution of the H_PKS_GET_CONFIG HCALL during initialization
+ * sets bit 4 of the flags variable in the PLPKS config structure if the
+ * H_PKS_REVOKE_OBJECT and H_PKS_UNREVOKE_OBJECT interfaces are supported.
+ *
+ * Returns: true if the H_PKS_REVOKE_OBJECT and H_PKS_UNREVOKE_OBJECT 
interfaces
+ * are supported, false if not.
+ */
+bool plpks_revoke_is_supported(void)
+{
+       return revokesupport;
+}
+EXPORT_SYMBOL_GPL(plpks_revoke_is_supported);
+
  /**
   * plpks_gen_wrapping_key() - Generate a new random key with the 'wrapping 
key'
   * policy set.
@@ -1189,6 +1218,446 @@ int plpks_unwrap_object(u8 **input_buf, u64 input_len, 
u8 **output_buf,
  }
  EXPORT_SYMBOL_GPL(plpks_unwrap_object);
+/**
+ * plpks_revoke_wrapping_key() - Revoke a wrapping key stored in the PLPKS.
+ * @var: variable representing the wrapping key to be revoked
+ *
+ * The H_PKS_REVOKE_OBJECT HCALL revokes an object stored in the PLPKS.
+ *
+ * Possible reasons for the returned errno values:
+ *
+ * -ENXIO      if PLPKS is not supported
+ * -EIO                if PLPKS access is blocked due to the LPAR's state
+ *             if PLPKS modification is blocked due to the LPAR's state
+ *             if an error occurred while processing the request
+ * -EINVAL     if invalid authorization parameter
+ *             if invalid wrapping key label parameter
+ *             if invalid wrapping key label length parameter
+ *             if invalid or unsupported wrapping key revoking flags
+ * -EPERM      if access is denied
+ * -ENOENT     if the requested wrapping key was not found
+ * -EBUSY      if unable to handle the request or long running operation
+ *             initiated, retry later.
+ *
+ * Returns: On success 0 is returned, a negative errno if not.
+ */
+int plpks_revoke_wrapping_key(struct plpks_var *var)
+{
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
+       struct plpks_auth *auth = NULL;
+       struct label *label;
+       u64 objrevokeflags = 0;
+       int rc = 0, pseries_status = 0;
+
+       if (!var->name || !*var->name) {

Can you please add null check for 'var' also.

if (! var || !var->name || !*var->name)


Noted.
I will fix this.


+               pr_err("key label cannot be NULL/empty\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       if (!strcmp((char *)var->name, PLPKS_DEFAULT_WRAPKEY_LABEL)) {
+               pr_warn("the default wrapping key must not be revoked!\n");
+               rc = -EPERM;
+               goto out;
+       }
+
+       auth = construct_auth(PLPKS_OS_OWNER);
+       if (IS_ERR(auth)) {
+               rc = PTR_ERR(auth);
+               goto out;
+       }
+
+       label = construct_label(var->component, var->os, var->name,
+                               var->namelen);
+       if (IS_ERR(label)) {
+               rc = PTR_ERR(label);
+               goto out;
+       }
+
+       rc = plpar_hcall(H_PKS_REVOKE_OBJECT, retbuf, virt_to_phys(auth),
+                        virt_to_phys(label), label->size, objrevokeflags);
+
+       pseries_status = rc;
+       rc = pseries_status_to_err(rc);
+
+       if (rc) {
+               pr_err("H_PKS_REVOKE_OBJECT failed. pseries_status=%d, rc=%d\n",
+                      pseries_status, rc);
+       }
+
+       if (!rc || (rc == -EPERM && retbuf[0]))
+               var->policy = (u32)retbuf[0];
+
+       kfree(label);
+out:
+       kfree(auth);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(plpks_revoke_wrapping_key);
+
+/**
+ * plpks_unrevoke_wrapping_key() - Unrevoke a revoked wrapping key in the 
PLPKS.
+ * @var: variable representing the revoked wrapping key to be unrevoked
+ *
+ * The H_PKS_UNREVOKE_OBJECT HCALL unrevokes a revoked object stored in the
+ * PLPKS.
+ *
+ * Possible reasons for the returned errno values:
+ *
+ * -ENXIO      if PLPKS is not supported
+ * -EIO                if PLPKS access is blocked due to the LPAR's state
+ *             if PLPKS modification is blocked due to the LPAR's state
+ *             if an error occurred while processing the request
+ * -EINVAL     if invalid authorization parameter
+ *             if invalid object label parameter
+ *             if invalid object label length parameter
+ *             if invalid or unsupported object revoking flags
+ * -EPERM      if access is denied
+ * -ENOENT     if the requested object was not found
+ * -EBUSY      if unable to handle the request or long running operation
+ *             initiated, retry later.
+ *
+ * Returns: On success 0 is returned, a negative errno if not.
+ */
+int plpks_unrevoke_wrapping_key(struct plpks_var *var)
+{
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
+       struct plpks_auth *auth = NULL;
+       struct label *label;
+       u64 objrevokeflags = 0;
+       int rc = 0, pseries_status = 0;
+
+       if (!var->name || !*var->name) {
same comment as above


Yup. I will fix this.


+               pr_err("key label cannot be NULL/empty\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       if (!strcmp((char *)var->name, PLPKS_DEFAULT_WRAPKEY_LABEL)) {
+               pr_warn("unrevoke on the default wrapping key is invalid\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       auth = construct_auth(PLPKS_OS_OWNER);
+       if (IS_ERR(auth)) {
+               rc = PTR_ERR(auth);
+               goto out;
+       }
+
+       label = construct_label(var->component, var->os, var->name,
+                               var->namelen);
+       if (IS_ERR(label)) {
+               rc = PTR_ERR(label);
+               goto out;
+       }
+
+       rc = plpar_hcall(H_PKS_UNREVOKE_OBJECT, retbuf,
+                        virt_to_phys(auth), virt_to_phys(label),
+                        label->size, objrevokeflags);
+
+       pseries_status = rc;
+       rc = pseries_status_to_err(rc);
+
+       if (rc)
+               pr_err("H_PKS_UNREVOKE_OBJECT failed. pseries_status=%d, 
rc=%d\n",
+                      pseries_status, rc);
+
+       if (!rc || (rc == -EPERM && retbuf[0]))
+               var->policy = (u32)retbuf[0];
+
+       kfree(label);
+out:
+       kfree(auth);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(plpks_unrevoke_wrapping_key);
+
+/**
+ * plpks_is_wrapping_key_revoked() - Check if a given wrapping key has been
+ * revoked.
+ * @var: variable representing the wrapping key to be checked
+ *
+ * When the H_PKS_READ_OBJECT HCALL tries reads an object that exists but when
+ * the policy is not met, it returns H_AUTHORITY along with the 4-byte object
+ * policy. This policy is inspected to determine if the object has been 
revoked.
+ *
+ * Possible reasons for the returned errno values:
+ *
+ * -ENXIO      if PLPKS is not supported
+ * -EIO                if PLPKS access is blocked due to the LPAR's state
+ *             if an error occurred while processing the request
+ * -EINVAL     if invalid authorization parameter
+ *             if invalid object label parameter
+ *             if invalid object label len parameter
+ *             if invalid output data parameter
+ *             if invalid output data len parameter
+ * -EPERM      if access is denied
+ * -ENOENT     if the requested object was not found
+ * -EFBIG      if the requested object couldn't be
+ *             stored in the buffer provided
+ * -EBUSY      if unable to handle the request
+ *
+ * Returns: 1 is returned if the wrapping key has been revoked. 0 is returned 
if
+ *         the wrapping key has not been revoked. Otherwise, a negative errno
+ *         is returned.
+ */
+int plpks_is_wrapping_key_revoked(struct plpks_var *var)
+{
+       int rc;
+
+       if (!var->name || !*var->name) {
same comment as above


Yup. I will fix this.


+               pr_err("key label cannot be NULL/empty\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       rc = plpks_read_var(PLPKS_OS_OWNER, var);
+       if (!rc) {
+               pr_err("unexpected successful read of wrapping key\n");
+               rc = -EIO;
+       } else if (rc == -EPERM) {
+               if (var->policy & PLPKS_WRAPPINGKEY) {
+                       if (var->policy & PLPKS_REVOKED)
+                               rc = 1;
+                       else
+                               rc = 0;
+               }
+       }
+
+out:
+       return rc;
+}
+EXPORT_SYMBOL_GPL(plpks_is_wrapping_key_revoked);
+
+/**
+ * plpks_del_wrapping_key() - Delete a wrapping key from the PLPKS.
+ * @var: variable representing the revoked wrapping key to be deleted
+ *
+ * The plpks_remove_var function removes the specified variable and its data
+ * from the PLPKS by invoking the H_PKS_REMOVE_OBJECT HCALL.
+ *
+ * Possible reasons for the returned errno values:
+ *
+ * -ENXIO      if PLPKS is not supported
+ * -EIO                if PLPKS access is blocked due to the LPAR's state
+ *             if PLPKS modification is blocked due to the LPAR's state
+ *             if an error occurred while processing the request
+ * -EINVAL     if invalid authorization parameter
+ *             if invalid object label parameter
+ *             if invalid object label len parameter
+ * -EPERM      if access is denied
+ * -ENOENT     if the requested object was not found
+ * -EBUSY      if unable to handle the request
+ *
+ * Returns: On success 0 is returned, a negative errno if not.
+ */
+int plpks_del_wrapping_key(struct plpks_var *var)
+{
+       int rc;
+       struct plpks_var_name vname;
+
+       if (!var->name || !*var->name) {
same comment as above


Yup. I will fix this.


Thanks,
Srish.


+               pr_err("key label cannot be NULL/empty\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       if (!strcmp((char *)var->name, PLPKS_DEFAULT_WRAPKEY_LABEL)) {
+               pr_warn("the default wrapping key must not be deleted!\n");
+               rc = -EPERM;
+               goto out;
+       }
+
+       rc = plpks_is_wrapping_key_revoked(var);
+       if (rc == 1) {
+               vname = (struct plpks_var_name) {
+                       .name = var->name,
+                       .namelen = var->namelen
+               };
+
+               rc = plpks_remove_var(PLPKS_WRAPKEY_COMPONENT, var->os,
+                                     vname);
+               if (rc)
+                       pr_err("deletion of <%s> failed. rc=%d\n",
+                              (char *)var->name, rc);
+               goto out;
+       } else if (!rc) {
+               pr_err("revoke <%s> before deletion\n", (char *)var->name);
+               rc = -EPERM;
+               goto out;
+       } else {
+               pr_err("revocation status check failed for <%s>. rc = %d\n",
+                      (char *)var->name, rc);
+       }
+
+out:
+       return rc;
+}
+EXPORT_SYMBOL_GPL(plpks_del_wrapping_key);
+
+/**
+ * plpks_get_object_labels() - retrieve a list of object labels for the objects
+ * stored in the PLPKS
+ * @output_buf: buffer to store the retrieved object labels
+ * @output_len: number of object labels retrieved
+ * @comp_prefix: component prefix string
+ *
+ * The H_PKS_GET_OBJECTLABELS HCALL retrieves a list of object labels for the
+ * objects with the given component prefix stored in the PLPKS.
+ *
+ * Possible reasons for the returned errno values:
+ *
+ * -ENXIO      if PLPKS is not supported
+ * -EIO                if PLPKS access is blocked due to the LPAR's state
+ *             if PLPKS modification is blocked due to the LPAR's state
+ *             if an error occurred while processing the request
+ * -EINVAL     if invalid authorization parameter
+ *             if invalid output buffer parameter
+ *             if invalid output buffer length parameter
+ *             if invalid continue token parameter
+ *             if the provided component prefix is NULL
+ * -EPERM      if access is denied
+ * -EBUSY      if unable to handle the request or long running operation
+ *             initiated, retry later.
+ *
+ * Returns: On success 0 is returned, a negative errno if not.
+ */
+int plpks_get_object_labels(u8 **output_buf, u64 *output_len,
+                           char *comp_prefix)
+{
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
+       u8 *labels_buf = NULL;
+       u8 *tmp_buf = NULL;
+       struct plpks_auth *auth = NULL;
+       struct label_attr *metadata = NULL;
+       u16 label_len;
+       u64 labels_count;
+       u64 continuetoken = 0, output_buf_len = 0;
+       int rc = 0, pseries_status = 0;
+       size_t labels_buf_offset = 0, output_buf_offset = 0;
+       size_t obj_label_entry_size, i;
+
+       *output_buf = NULL;
+       *output_len = 0;
+
+       if (!comp_prefix) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+       auth = construct_auth(PLPKS_OS_OWNER);
+       if (IS_ERR(auth)) {
+               rc = PTR_ERR(auth);
+               goto out;
+       }
+
+       do {
+               labels_buf =
+                       kzalloc(roundup_pow_of_two(PLPKS_OBJLABEL_BUF_MAX),
+                               GFP_KERNEL);
+
+               if (!labels_buf) {
+                       pr_err("labels_buf buffer allocation failed\n");
+                       rc = -ENOMEM;
+                       goto out_free_output_buf;
+               }
+
+               rc = plpar_hcall(H_PKS_GET_OBJECTLABELS, retbuf,
+                                virt_to_phys(auth), continuetoken,
+                                virt_to_phys(labels_buf),
+                                roundup_pow_of_two(PLPKS_OBJLABEL_BUF_MAX));
+
+               pseries_status = rc;
+               rc = pseries_status_to_err(rc);
+
+               if (rc && rc != -EAGAIN) {
+                       pr_err("H_PKS_GET_OBJECTLABELS failed. pseries_status=%d 
rc=%d\n",
+                              pseries_status, rc);
+                       goto out_free_labels_buf;
+               } else {
+                       /*
+                        * Setting an incorrect countinuetoken upon
+                        * receiving H_CONTINUE would result in H_P2. Since
+                        * the continuetoken is being set to the expected
+                        * value from the previous call, H_P2 must not be
+                        * returned.
+                        */
+                       continuetoken = retbuf[1];
+
+                       labels_count = retbuf[0];
+                       if (!labels_count) {
+                               kfree(labels_buf);
+                               labels_buf = NULL;
+                               goto out;
+                       }
+
+                       /*
+                        * Filter out object labels that don't have the provided
+                        * component prefix.
+                        */
+
+                       output_buf_len +=
+                               roundup_pow_of_two(PLPKS_OBJLABEL_BUF_MAX);
+
+                       tmp_buf = krealloc(*output_buf, output_buf_len,
+                                          GFP_KERNEL);
+
+                       if (!tmp_buf) {
+                               pr_err("output buffer re-allocation failed\n");
+                               rc = -ENOMEM;
+                               goto out_free_labels_buf;
+                       }
+
+                       *output_buf = tmp_buf;
+
+                       for (i = 0; i < labels_count; ++i) {
+                               label_len =
+                                       get_unaligned_be16(labels_buf +
+                                                          labels_buf_offset);
+
+                               obj_label_entry_size =
+                                       PLPKS_OBJLABEL_LEN_FIELD_SIZE +
+                                       label_len;
+
+                               metadata =
+                                       (struct label_attr *)(labels_buf +
+                                       labels_buf_offset +
+                                       PLPKS_OBJLABEL_LEN_FIELD_SIZE);
+
+                               if (!memcmp(metadata->prefix, comp_prefix,
+                                           PLPKS_OBJLABEL_PREFIX_LEN)) {
+                                       memcpy(*output_buf + output_buf_offset,
+                                              labels_buf + labels_buf_offset,
+                                              obj_label_entry_size);
+
+                                       output_buf_offset +=
+                                               obj_label_entry_size;
+                                       (*output_len) += 1;
+                               }
+                               labels_buf_offset += obj_label_entry_size;
+                       }
+                       kfree(labels_buf);
+                       labels_buf = NULL;
+                       labels_buf_offset = 0;
+               }
+       } while (rc == -EAGAIN);
+
+       goto out;
+
+out_free_labels_buf:
+       kfree(labels_buf);
+       labels_buf = NULL;
+out_free_output_buf:
+       kfree(*output_buf);
+       *output_buf = NULL;
+       *output_len = 0;
+out:
+       kfree(auth);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(plpks_get_object_labels);
+
  /**
   * plpks_read_os_var() - Fetch the data for the specified variable that is 
owned
   * by the OS consumer.
--
Thanks and Regards
R.Nageswara Sastry

Reply via email to