The object wrapping and unwrapping HCALLs use 64-bit length values, but
plpks_wrap_object() and plpks_unwrap_object() currently use u32 for the
input and output length parameters.

Use u64 for the length parameters to match the underlying HCALL interfaces,
and update the PKWM consumer accordingly. Validate input lengths against
the HCALL-defined limits before calculating output buffer sizes.

Fixes: 133aa79e211d ("pseries/plpks: add HCALLs for PowerVM Key Wrapping 
Module")
Fixes: c99fcb0d735b ("keys/trusted_keys: establish PKWM as a trusted source")
Cc: [email protected] # 7.0
Signed-off-by: Srish Srinivasan <[email protected]>
---
 arch/powerpc/include/asm/plpks.h          |  8 ++++----
 arch/powerpc/platforms/pseries/plpks.c    | 18 ++++++++++++++----
 security/keys/trusted-keys/trusted_pkwm.c |  4 ++--
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
index e87f90e40d4e..8b2ffb27db5a 100644
--- a/arch/powerpc/include/asm/plpks.h
+++ b/arch/powerpc/include/asm/plpks.h
@@ -118,11 +118,11 @@ bool plpks_wrapping_is_supported(void);
 
 int plpks_gen_wrapping_key(void);
 
-int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 wrap_flags,
-                     u8 **output_buf, u32 *output_len);
+int plpks_wrap_object(u8 **input_buf, u64 input_len, u16 wrap_flags,
+                     u8 **output_buf, u64 *output_len);
 
-int plpks_unwrap_object(u8 **input_buf, u32 input_len,
-                       u8 **output_buf, u32 *output_len);
+int plpks_unwrap_object(u8 **input_buf, u64 input_len,
+                       u8 **output_buf, u64 *output_len);
 #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 584091f9aa08..ca750c250374 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -22,6 +22,9 @@
  * than the input buffer's length during the WRAP H_CALL
  */
 #define PLPKS_WRAPPING_BUF_DIFF        1024
+#define PLPKS_MAX_WRAPPING_INPUT_SIZE  (32 * 1024)
+#define PLPKS_MAX_WRAPPED_OBJECT_SIZE  \
+       (PLPKS_MAX_WRAPPING_INPUT_SIZE + PLPKS_WRAPPING_BUF_DIFF)
 
 #define PLPKS_WRAP_INTERFACE_BIT       3
 #define PLPKS_WRAPPING_KEY_LENGTH      32
@@ -1023,8 +1026,8 @@ EXPORT_SYMBOL_GPL(plpks_gen_wrapping_key);
  *
  * Returns: On success 0 is returned, a negative errno if not.
  */
-int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 wrap_flags,
-                     u8 **output_buf, u32 *output_len)
+int plpks_wrap_object(u8 **input_buf, u64 input_len, u16 wrap_flags,
+                     u8 **output_buf, u64 *output_len)
 {
        unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
        struct plpks_auth *auth;
@@ -1041,6 +1044,9 @@ int plpks_wrap_object(u8 **input_buf, u32 input_len, u16 
wrap_flags,
                .component = PLPKS_WRAPKEY_COMPONENT
        };
 
+       if (!input_len || input_len > PLPKS_MAX_WRAPPING_INPUT_SIZE)
+               return -EINVAL;
+
        auth = construct_auth(PLPKS_OS_OWNER);
        if (IS_ERR(auth))
                return PTR_ERR(auth);
@@ -1142,8 +1148,8 @@ EXPORT_SYMBOL_GPL(plpks_wrap_object);
  *
  * Returns: On success 0 is returned, a negative errno if not.
  */
-int plpks_unwrap_object(u8 **input_buf, u32 input_len, u8 **output_buf,
-                       u32 *output_len)
+int plpks_unwrap_object(u8 **input_buf, u64 input_len, u8 **output_buf,
+                       u64 *output_len)
 {
        unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
        struct plpks_auth *auth;
@@ -1151,6 +1157,10 @@ int plpks_unwrap_object(u8 **input_buf, u32 input_len, 
u8 **output_buf,
        u64 objwrapflags = 0;
        int rc = 0, pseries_status = 0;
 
+       if (input_len <= PLPKS_WRAPPING_BUF_DIFF ||
+           input_len > PLPKS_MAX_WRAPPED_OBJECT_SIZE)
+               return -EINVAL;
+
        auth = construct_auth(PLPKS_OS_OWNER);
        if (IS_ERR(auth))
                return PTR_ERR(auth);
diff --git a/security/keys/trusted-keys/trusted_pkwm.c 
b/security/keys/trusted-keys/trusted_pkwm.c
index bf42c6679245..b6b5697426a8 100644
--- a/security/keys/trusted-keys/trusted_pkwm.c
+++ b/security/keys/trusted-keys/trusted_pkwm.c
@@ -83,7 +83,7 @@ static int trusted_pkwm_seal(struct trusted_key_payload *p, 
char *datablob)
        struct trusted_key_options *options = NULL;
        struct trusted_pkwm_options *pkwm = NULL;
        u8 *input_buf, *output_buf;
-       u32 output_len, input_len;
+       u64 output_len, input_len;
        int rc;
 
        options = trusted_options_alloc();
@@ -130,7 +130,7 @@ static int trusted_pkwm_seal(struct trusted_key_payload *p, 
char *datablob)
 static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *datablob)
 {
        u8 *input_buf, *output_buf;
-       u32 input_len, output_len;
+       u64 input_len, output_len;
        int rc;
 
        input_len = p->blob_len;
-- 
2.52.0


Reply via email to