From 838ede224ad29ac3e1e6769bd00bf6be52185b5b Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Mon, 30 Mar 2026 10:19:40 +0200
Subject: [PATCH] COMMON: Fix possible out-of-bounds access in BER decode
 functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When decoding BER encoded data the length of the BER encoded data as well as
any length fields inside the BER encoded data must be validated to not cause
an out-of-bounds access to data behind the BER encoded data.

Add length parameters to any of the BER decoder functions to allow validation
of the decoded length information.

Reported-by: Sebastián Alba <sebasjosue84@gmail.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
 usr/lib/cca_stdll/cca_specific.c      |   4 +-
 usr/lib/common/asn1.c                 | 531 +++++++++++++++++---------
 usr/lib/common/h_extern.h             |  21 +-
 usr/lib/common/key_mgr.c              |   5 +-
 usr/lib/common/mech_ec.c              |   4 +-
 usr/lib/common/pkey_utils.c           |   8 +-
 usr/lib/ep11_stdll/ep11_login.c       |   9 +-
 usr/lib/ep11_stdll/ep11_specific.c    |  62 +--
 usr/lib/ica_s390_stdll/ica_specific.c |   4 +-
 9 files changed, 426 insertions(+), 222 deletions(-)

diff --git a/usr/lib/cca_stdll/cca_specific.c b/usr/lib/cca_stdll/cca_specific.c
index c6f088824..b99f99da8 100644
--- a/usr/lib/cca_stdll/cca_specific.c
+++ b/usr/lib/cca_stdll/cca_specific.c
@@ -12404,8 +12404,8 @@ static CK_RV import_ec_pubkey(STDLL_TokData_t *tokdata, TEMPLATE *pub_templ)
             return rc;
         }
 
-        rc = ber_decode_OCTET_STRING(attr->pValue, &pubkey, &publen,
-                                     &field_len);
+        rc = ber_decode_OCTET_STRING(attr->pValue, attr->ulValueLen,
+                                     &pubkey, &publen, &field_len);
         if (rc != CKR_OK || attr->ulValueLen != field_len) {
             TRACE_DEVEL("ber decoding of public key failed\n");
             return CKR_ATTRIBUTE_VALUE_INVALID;
diff --git a/usr/lib/common/asn1.c b/usr/lib/common/asn1.c
index 93af67d39..c2e2d4b5b 100644
--- a/usr/lib/common/asn1.c
+++ b/usr/lib/common/asn1.c
@@ -155,13 +155,13 @@ CK_ULONG ber_encode_INTEGER(CK_BBOOL length_only,
 
 //
 //
-CK_RV ber_decode_INTEGER(CK_BYTE *ber_int,
+CK_RV ber_decode_INTEGER(CK_BYTE *ber_int, CK_ULONG ber_int_len,
                          CK_BYTE **data, CK_ULONG *data_len,
                          CK_ULONG *field_len)
 {
     CK_ULONG len, length_octets;
 
-    if (!ber_int) {
+    if (ber_int == NULL || ber_int_len < 2) {
         TRACE_ERROR("Invalid function argument.\n");
         return CKR_FUNCTION_FAILED;
     }
@@ -181,9 +181,13 @@ CK_RV ber_decode_INTEGER(CK_BYTE *ber_int,
     //
     if ((ber_int[1] & 0x80) == 0) {
         len = ber_int[1] & 0x7F;
+        if (1 + 1 + len > ber_int_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
         *data = &ber_int[2];
         *data_len = len;
-        if (ber_int[2] == 0x00) {
+        if (len > 0 && ber_int[2] == 0x00) {
             *data = &ber_int[3];
             *data_len = len - 1;
         }
@@ -192,12 +196,20 @@ CK_RV ber_decode_INTEGER(CK_BYTE *ber_int,
     }
 
     length_octets = ber_int[1] & 0x7F;
+    if (1 + 1 + length_octets > ber_int_len) {
+        TRACE_ERROR("BER length is larger than encoded data.\n");
+        return CKR_FUNCTION_FAILED;
+    }
 
     if (length_octets == 1) {
         len = ber_int[2];
+        if (1 + (1 + 1) + len > ber_int_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
         *data = &ber_int[3];
         *data_len = len;
-        if (ber_int[3] == 0x00) {
+        if (len > 0 && ber_int[3] == 0x00) {
             *data = &ber_int[4];
             *data_len = len - 1;
         }
@@ -209,9 +221,13 @@ CK_RV ber_decode_INTEGER(CK_BYTE *ber_int,
         len = ber_int[2];
         len = len << 8;
         len |= ber_int[3];
+        if (1 + (1 + 2) + len > ber_int_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
         *data = &ber_int[4];
         *data_len = len;
-        if (ber_int[4] == 0x00) {
+        if (len > 0 && ber_int[4] == 0x00) {
             *data = &ber_int[5];
             *data_len = len - 1;
         }
@@ -225,9 +241,13 @@ CK_RV ber_decode_INTEGER(CK_BYTE *ber_int,
         len |= ber_int[3];
         len = len << 8;
         len |= ber_int[4];
+        if (1 + (1 + 3) + len > ber_int_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
         *data = &ber_int[5];
         *data_len = len;
-        if (ber_int[5] == 0x00) {
+        if (len > 0 && ber_int[5] == 0x00) {
             *data = &ber_int[6];
             *data_len = len - 1;
         }
@@ -343,7 +363,7 @@ CK_RV ber_encode_OCTET_STRING(CK_BBOOL length_only,
 
 //
 //
-CK_RV ber_decode_OCTET_STRING(CK_BYTE *str,
+CK_RV ber_decode_OCTET_STRING(CK_BYTE *str, CK_ULONG str_len,
                               CK_BYTE **data,
                               CK_ULONG *data_len, CK_ULONG *field_len)
 {
@@ -352,7 +372,7 @@ CK_RV ber_decode_OCTET_STRING(CK_BYTE *str,
     // I only support decoding primitive OCTET STRINGS
     //
 
-    if (!str) {
+    if (!str || str_len < 2) {
         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
         return CKR_FUNCTION_FAILED;
     }
@@ -364,6 +384,10 @@ CK_RV ber_decode_OCTET_STRING(CK_BYTE *str,
     //
     if ((str[1] & 0x80) == 0) {
         len = str[1] & 0x7F;
+        if (1 + 1 + len > str_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &str[2];
         *data_len = len;
@@ -372,9 +396,17 @@ CK_RV ber_decode_OCTET_STRING(CK_BYTE *str,
     }
 
     length_octets = str[1] & 0x7F;
+    if (1 + 1 + length_octets > str_len) {
+        TRACE_ERROR("BER length is larger than encoded data.\n");
+        return CKR_FUNCTION_FAILED;
+    }
 
     if (length_octets == 1) {
         len = str[2];
+        if (1 + (1 + 1) + len > str_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &str[3];
         *data_len = len;
@@ -386,6 +418,10 @@ CK_RV ber_decode_OCTET_STRING(CK_BYTE *str,
         len = str[2];
         len = len << 8;
         len |= str[3];
+        if (1 + (1 + 2) + len > str_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &str[4];
         *data_len = len;
@@ -399,6 +435,10 @@ CK_RV ber_decode_OCTET_STRING(CK_BYTE *str,
         len |= str[3];
         len = len << 8;
         len |= str[4];
+        if (1 + (1 + 3) + len > str_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &str[5];
         *data_len = len;
@@ -515,13 +555,13 @@ CK_ULONG ber_encode_BIT_STRING(CK_BBOOL length_only,
  * The first byte of output parm *data is the number of unused bits and must
  * be removed later by the calling function.
  */
-CK_RV ber_decode_BIT_STRING(CK_BYTE *str,
+CK_RV ber_decode_BIT_STRING(CK_BYTE *str, CK_ULONG str_len,
                             CK_BYTE **data,
                             CK_ULONG *data_len, CK_ULONG *field_len)
 {
     CK_ULONG len, length_octets;
 
-    if (!str) {
+    if (!str || str_len < 2) {
         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
         return CKR_FUNCTION_FAILED;
     }
@@ -532,6 +572,15 @@ CK_RV ber_decode_BIT_STRING(CK_BYTE *str,
 
     if ((str[1] & 0x80) == 0) {
         len = str[1] & 0x7F;
+        if (1 + 1 + len > str_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
+        if (len < 1) {
+            TRACE_ERROR("BER length is too small to include the "
+                        "unused-bits-byte\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &str[2];
         *data_len = len;
@@ -540,9 +589,22 @@ CK_RV ber_decode_BIT_STRING(CK_BYTE *str,
     }
 
     length_octets = str[1] & 0x7F;
+    if (1 + 1 + length_octets > str_len) {
+        TRACE_ERROR("BER length is larger than encoded data.\n");
+        return CKR_FUNCTION_FAILED;
+    }
 
     if (length_octets == 1) {
         len = str[2];
+        if (1 + (1 + 1) + len > str_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
+        if (len < 1) {
+            TRACE_ERROR("BER length is too small to include the "
+                        "unused-bits-byte\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &str[3];
         *data_len = len;
@@ -554,6 +616,15 @@ CK_RV ber_decode_BIT_STRING(CK_BYTE *str,
         len = str[2];
         len = len << 8;
         len |= str[3];
+        if (1 + (1 + 2) + len > str_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
+        if (len < 1) {
+            TRACE_ERROR("BER length is too small to include the "
+                        "unused-bits-byte\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &str[4];
         *data_len = len;
@@ -567,6 +638,15 @@ CK_RV ber_decode_BIT_STRING(CK_BYTE *str,
         len |= str[3];
         len = len << 8;
         len |= str[4];
+        if (1 + (1 + 3) + len > str_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
+        if (len < 1) {
+            TRACE_ERROR("BER length is too small to include the "
+                        "unused-bits-byte\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &str[5];
         *data_len = len;
@@ -674,14 +754,14 @@ CK_RV ber_encode_SEQUENCE(CK_BBOOL length_only,
 
 //
 //
-CK_RV ber_decode_SEQUENCE(CK_BYTE *seq,
+CK_RV ber_decode_SEQUENCE(CK_BYTE *seq, CK_ULONG seq_len,
                           CK_BYTE **data, CK_ULONG *data_len,
                           CK_ULONG *field_len)
 {
     CK_ULONG len, length_octets;
 
 
-    if (!seq) {
+    if (!seq || seq_len < 2) {
         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
         return CKR_FUNCTION_FAILED;
     }
@@ -693,6 +773,10 @@ CK_RV ber_decode_SEQUENCE(CK_BYTE *seq,
     //
     if ((seq[1] & 0x80) == 0) {
         len = seq[1] & 0x7F;
+        if (1 + 1 + len > seq_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &seq[2];
         *data_len = len;
@@ -701,9 +785,17 @@ CK_RV ber_decode_SEQUENCE(CK_BYTE *seq,
     }
 
     length_octets = seq[1] & 0x7F;
+    if (1 + 1 + length_octets > seq_len) {
+        TRACE_ERROR("BER length is larger than encoded data.\n");
+        return CKR_FUNCTION_FAILED;
+    }
 
     if (length_octets == 1) {
         len = seq[2];
+        if (1 + (1 + 1) + len > seq_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &seq[3];
         *data_len = len;
@@ -715,6 +807,10 @@ CK_RV ber_decode_SEQUENCE(CK_BYTE *seq,
         len = seq[2];
         len = len << 8;
         len |= seq[3];
+        if (1 + (1 + 2) + len > seq_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &seq[4];
         *data_len = len;
@@ -728,6 +824,10 @@ CK_RV ber_decode_SEQUENCE(CK_BYTE *seq,
         len |= seq[3];
         len = len << 8;
         len |= seq[4];
+        if (1 + (1 + 3) + len > seq_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
 
         *data = &seq[5];
         *data_len = len;
@@ -834,7 +934,8 @@ CK_RV ber_encode_CHOICE(CK_BBOOL length_only,
     return CKR_FUNCTION_FAILED;
 }
 
-CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed,
+CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_ULONG choice_len,
+                        CK_BBOOL constructed,
                         CK_BYTE **data,
                         CK_ULONG *data_len, CK_ULONG *field_len,
                         CK_ULONG *option)
@@ -842,7 +943,7 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed,
     CK_ULONG len, length_octets;
 
 
-    if (!choice) {
+    if (!choice || choice_len < 2) {
         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
         return CKR_FUNCTION_FAILED;
     }
@@ -858,6 +959,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed,
     //
     if ((choice[1] & 0x80) == 0) {
         len = choice[1] & 0x7F;
+        if (1 + 1 + len > choice_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
         *data = &choice[2];
         *data_len = len;
         *field_len = 1 + (1) + len;
@@ -865,9 +970,17 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed,
     }
 
     length_octets = choice[1] & 0x7F;
+    if (1 + 1 + length_octets > choice_len) {
+        TRACE_ERROR("BER length is larger than encoded data.\n");
+        return CKR_FUNCTION_FAILED;
+    }
 
     if (length_octets == 1) {
         len = choice[2];
+        if (1 + (1 + 1) + len > choice_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
         *data = &choice[3];
         *data_len = len;
         *field_len = 1 + (1 + 1) + len;
@@ -878,6 +991,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed,
         len = choice[2];
         len = len << 8;
         len |= choice[3];
+        if (1 + (1 + 2) + len > choice_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
         *data = &choice[4];
         *data_len = len;
         *field_len = 1 + (1 + 2) + len;
@@ -890,6 +1007,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed,
         len |= choice[3];
         len = len << 8;
         len |= choice[4];
+        if (1 + (1 + 3) + len > choice_len) {
+            TRACE_ERROR("BER length is larger than encoded data.\n");
+            return CKR_FUNCTION_FAILED;
+        }
         *data = &choice[5];
         *data_len = len;
         *field_len = 1 + (1 + 3) + len;
@@ -1000,10 +1121,9 @@ CK_RV ber_encode_PrivateKeyInfo(CK_BBOOL length_only,
 
 //
 //
-CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data,
-                                CK_ULONG data_len,
-                                CK_BYTE **algorithm,
-                                CK_ULONG *alg_len, CK_BYTE **priv_key)
+CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data, CK_ULONG data_len,
+                                CK_BYTE **algorithm, CK_ULONG *alg_len,
+                                CK_BYTE **priv_key, CK_ULONG *priv_key_len)
 {
     CK_BYTE *buf = NULL;
     CK_BYTE *alg = NULL;
@@ -1015,7 +1135,7 @@ CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data,
         TRACE_ERROR("Invalid function arguments.\n");
         return CKR_FUNCTION_FAILED;
     }
-    rc = ber_decode_SEQUENCE(data, &buf, &buf_len, &field_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &buf, &buf_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
@@ -1023,7 +1143,8 @@ CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data,
     // version -- we just ignore this
     //
     offset = 0;
-    rc = ber_decode_INTEGER(buf + offset, &ver, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &ver, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
@@ -1032,15 +1153,18 @@ CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data,
 
     // 'buf' is now pointing to the PrivateKeyAlgorithmIdentifier
     //
-    rc = ber_decode_SEQUENCE(buf + offset, &alg, &len, &field_len);
+    rc = ber_decode_SEQUENCE(buf + offset, buf_len - offset, &alg, &len,
+                             &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
     }
+    offset += field_len;
     *algorithm = alg;
     *alg_len = len;
 
-    rc = ber_decode_OCTET_STRING(alg + len, priv_key, &buf_len, &field_len);
+    rc = ber_decode_OCTET_STRING(buf + offset, buf_len - offset,
+                                 priv_key, priv_key_len, &field_len);
     if (rc != CKR_OK)
         TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
 
@@ -1058,13 +1182,14 @@ CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data,
  *     parameters  ANY DEFINED BY algorithm OPTIONAL
  *   }
  */
-CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_BYTE **alg_oid, CK_ULONG *alg_oid_len,
+CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_ULONG spki_len,
+                      CK_BYTE **alg_oid, CK_ULONG *alg_oid_len,
                       CK_BYTE **param, CK_ULONG *param_len,
                       CK_BYTE **key, CK_ULONG *key_len)
 {
     CK_BYTE *out_seq, *id_seq, *bit_str;
     CK_BYTE *data;
-    CK_ULONG data_len;
+    CK_ULONG data_len, out_seq_len, id_seq_len, bit_str_len;
     CK_ULONG field_len;
     CK_RV rc;
 
@@ -1072,7 +1197,9 @@ CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_BYTE **alg_oid, CK_ULONG *alg_oid_len,
     *param_len = 0;
     *key_len = 0;
     out_seq = spki;
-    rc = ber_decode_SEQUENCE(out_seq, &data, &data_len, &field_len);
+    out_seq_len = spki_len;
+    rc = ber_decode_SEQUENCE(out_seq, out_seq_len, &data, &data_len,
+                             &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE #1 failed rc=0x%lx\n",
                     __func__, rc);
@@ -1080,23 +1207,35 @@ CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_BYTE **alg_oid, CK_ULONG *alg_oid_len,
     }
 
     id_seq = out_seq + field_len - data_len;
+    id_seq_len = out_seq_len - field_len + data_len;
     /* get id seq */
-    rc = ber_decode_SEQUENCE(id_seq, &data, &data_len, &field_len);
+    rc = ber_decode_SEQUENCE(id_seq, id_seq_len, &data, &data_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE #2 failed rc=0x%lx\n",
                     __func__, rc);
         return rc;
     }
 
+    if (data_len < 2) {
+        TRACE_ERROR("%s Length of id_seq is too short\n", __func__);
+        return CKR_FUNCTION_FAILED;
+    }
+
     *alg_oid = data;
     *alg_oid_len = data[1] + 2;
 
+    if (*alg_oid_len > data_len) {
+        TRACE_ERROR("%s Length of id_seq is too short\n", __func__);
+        return CKR_FUNCTION_FAILED;
+    }
+
     *param = data + *alg_oid_len;
     *param_len = data_len - *alg_oid_len;
 
     bit_str = id_seq + field_len;
+    bit_str_len = id_seq_len - field_len;
     /* get bitstring */
-    rc = ber_decode_BIT_STRING(bit_str, key, key_len, &field_len);
+    rc = ber_decode_BIT_STRING(bit_str, bit_str_len, key, key_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_BIT_STRING failed rc=0x%lx\n",
                     __func__, rc);
@@ -1363,10 +1502,11 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
     CK_BYTE *rsa_priv_key = NULL;
     CK_BYTE *buf = NULL;
     CK_BYTE *tmp = NULL;
-    CK_ULONG offset, buf_len, field_len, len;
+    CK_ULONG offset, buf_len, field_len, len, rsa_priv_key_len;
     CK_RV rc;
 
-    rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &len, &rsa_priv_key);
+    rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &len,
+                                   &rsa_priv_key, &rsa_priv_key_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
         return rc;
@@ -1378,7 +1518,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
         return CKR_FUNCTION_FAILED;
     }
-    rc = ber_decode_SEQUENCE(rsa_priv_key, &buf, &buf_len, &field_len);
+    rc = ber_decode_SEQUENCE(rsa_priv_key, rsa_priv_key_len,
+                             &buf, &buf_len, &field_len);
     if (rc != CKR_OK)
         return rc;
 
@@ -1388,7 +1529,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // Version
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1397,7 +1539,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // modulus
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1406,7 +1549,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // public exponent
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1415,7 +1559,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // private exponent
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1424,7 +1569,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // prime #1
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1433,7 +1579,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // prime #2
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1442,7 +1589,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // exponent #1
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1451,7 +1599,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // exponent #2
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1460,7 +1609,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // coefficient
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1480,7 +1630,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // skip the version
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1489,7 +1640,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // modulus
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1504,7 +1656,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // public exponent
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1519,7 +1672,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // private exponent
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1534,7 +1688,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // prime #1
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1549,7 +1704,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // prime #2
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1564,7 +1720,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // exponent #1
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1579,7 +1736,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // exponent #2
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1594,7 +1752,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data,
 
     // coefficient
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -1782,9 +1941,7 @@ CK_RV ber_decode_RSAPublicKey(CK_BYTE *data,
     CK_ULONG field_len, offset, len;
     CK_RV rc;
 
-    UNUSED(data_len); // XXX can this parameter be removed ?
-
-    rc = ber_decode_SPKI(data, &algid, &algid_len, &param, &param_len,
+    rc = ber_decode_SPKI(data, data_len, &algid, &algid_len, &param, &param_len,
                          &val, &val_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
@@ -1794,7 +1951,8 @@ CK_RV ber_decode_RSAPublicKey(CK_BYTE *data,
     /*
      * Make sure we're dealing with an DH key.
      */
-    rc = ber_decode_SEQUENCE((CK_BYTE *)ber_AlgIdRSAEncryption, &algid_RSABase,
+    rc = ber_decode_SEQUENCE((CK_BYTE *)ber_AlgIdRSAEncryption,
+                             ber_AlgIdRSAEncryptionLen, &algid_RSABase,
                              &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
@@ -1806,20 +1964,21 @@ CK_RV ber_decode_RSAPublicKey(CK_BYTE *data,
         return CKR_FUNCTION_FAILED;
     }
 
-    rc = ber_decode_SEQUENCE(val, &seq, &seq_len, &field_len);
+    rc = ber_decode_SEQUENCE(val, val_len, &seq, &seq_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
     }
 
-    rc = ber_decode_INTEGER(seq, &mod, &mod_len, &field_len);
+    rc = ber_decode_INTEGER(seq, seq_len, &mod, &mod_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
     }
 
     offset = field_len;
-    rc = ber_decode_INTEGER(seq + offset, &exp, &exp_len, &field_len);
+    rc = ber_decode_INTEGER(seq + offset, seq_len - offset, &exp, &exp_len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
@@ -2053,11 +2212,12 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
     CK_BYTE *buf = NULL;
     CK_BYTE *dsakey = NULL;
     CK_BYTE *tmp = NULL;
-    CK_ULONG buf_len, field_len, len, offset;
+    CK_ULONG buf_len, field_len, len, dsakey_len, offset;
     CK_RV rc;
 
 
-    rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &len, &dsakey);
+    rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &len,
+                                   &dsakey, &dsakey_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
         return rc;
@@ -2071,7 +2231,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
     }
     // extract the parameter data into ATTRIBUTES
     //
-    rc = ber_decode_SEQUENCE(alg + ber_idDSALen, &buf, &buf_len, &field_len);
+    rc = ber_decode_SEQUENCE(alg + ber_idDSALen, len- ber_idDSALen,
+                             &buf, &buf_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
@@ -2080,7 +2241,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
 
     // prime
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -2089,7 +2251,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
 
     // subprime
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -2098,7 +2261,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
 
     // base
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -2117,7 +2281,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
 
     // prime
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -2132,7 +2297,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
 
     // subprime
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                           &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -2147,7 +2313,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
 
     // base
     //
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -2162,7 +2329,7 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data,
 
     // now get the private key
     //
-    rc = ber_decode_INTEGER(dsakey, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(dsakey, dsakey_len, &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -2405,9 +2572,7 @@ CK_RV ber_decode_DSAPublicKey(CK_BYTE *data,
     CK_ULONG field_len, offset;
     CK_RV rc;
 
-    UNUSED(data_len); // XXX can this parameter be removed ?
-
-    rc = ber_decode_SPKI(data, &algid, &algid_len, &param, &param_len,
+    rc = ber_decode_SPKI(data, data_len, &algid, &algid_len, &param, &param_len,
                          &val, &val_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
@@ -2422,27 +2587,29 @@ CK_RV ber_decode_DSAPublicKey(CK_BYTE *data,
         return CKR_FUNCTION_FAILED;
     }
 
-    rc = ber_decode_SEQUENCE(param, &seq, &seq_len, &field_len);
+    rc = ber_decode_SEQUENCE(param, param_len, &seq, &seq_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
     }
 
-    rc = ber_decode_INTEGER(seq, &p, &p_len, &field_len);
+    rc = ber_decode_INTEGER(seq, seq_len, &p, &p_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
     }
 
     offset = field_len;
-    rc = ber_decode_INTEGER(seq + offset, &sp, &sp_len, &field_len);
+    rc = ber_decode_INTEGER(seq + offset, seq_len - offset, &sp, &sp_len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
     }
 
     offset += field_len;
-    rc = ber_decode_INTEGER(seq + offset, &b, &b_len, &field_len);
+    rc = ber_decode_INTEGER(seq + offset, seq_len - offset, &b, &b_len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
@@ -2541,8 +2708,8 @@ CK_RV der_encode_ECPrivateKey(CK_BBOOL length_only,
     }
     // public key bit string
     if (pubkey && pubkey->pValue) {
-        rc = ber_decode_OCTET_STRING(pubkey->pValue, &ecpoint, &ecpoint_len,
-                                     &field_len);
+        rc = ber_decode_OCTET_STRING(pubkey->pValue, pubkey->ulValueLen,
+                                     &ecpoint, &ecpoint_len, &field_len);
         if (rc != CKR_OK || pubkey->ulValueLen != field_len) {
             TRACE_DEVEL("ber decoding of public key failed\n");
             return CKR_ATTRIBUTE_VALUE_INVALID;
@@ -2624,8 +2791,8 @@ CK_RV der_encode_ECPrivateKey(CK_BBOOL length_only,
 
     /* generate optional bit-string of public key */
     if (pubkey && pubkey->pValue) {
-        rc = ber_decode_OCTET_STRING(pubkey->pValue, &ecpoint, &ecpoint_len,
-                                     &field_len);
+        rc = ber_decode_OCTET_STRING(pubkey->pValue, pubkey->ulValueLen,
+                                     &ecpoint, &ecpoint_len, &field_len);
         if (rc != CKR_OK || pubkey->ulValueLen != field_len) {
             TRACE_DEVEL("ber decoding of public key failed\n");
             rc = CKR_ATTRIBUTE_VALUE_INVALID;
@@ -2717,7 +2884,7 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
     CK_BYTE *version = NULL;
     CK_BYTE *choice = NULL;
     CK_ULONG version_len, alg_len, priv_len, pub_len, parm_len, buf_len;
-    CK_ULONG buf_offset, field_len, offset, choice_len, option;
+    CK_ULONG buf_offset, field_len, offset, choice_len, option, eckey_len;
     CK_ULONG pubkey_available = 0;
     CK_BYTE *ecpoint = NULL;
     CK_ULONG ecpoint_len;
@@ -2731,7 +2898,7 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
      * know the actual length to be able to find out of the optional public key
      * is present or not.
      */
-    rc = ber_decode_SEQUENCE(data, &buf, &buf_len, &field_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &buf, &buf_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
@@ -2743,7 +2910,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
     data_len = field_len;
 
     /* Decode PrivateKeyInfo into alg and eckey */
-    rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &alg_len, &eckey);
+    rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &alg_len,
+                                   &eckey, &eckey_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
         return rc;
@@ -2756,7 +2924,7 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
     }
 
     /* Decode the ecdhkey into buf */
-    rc = ber_decode_SEQUENCE(eckey, &buf, &buf_len, &field_len);
+    rc = ber_decode_SEQUENCE(eckey, eckey_len, &buf, &buf_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
@@ -2764,7 +2932,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
     offset = 0;
 
     /* Decode version (INTEGER) */
-    rc = ber_decode_INTEGER(buf + offset, &version, &version_len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset,
+                            &version, &version_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -2772,8 +2941,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
     offset += field_len;
 
     /* Decode private key (OCTET_STRING) */
-    rc = ber_decode_OCTET_STRING(buf + offset, &priv_buf, &priv_len,
-                                 &field_len);
+    rc = ber_decode_OCTET_STRING(buf + offset, buf_len - offset,
+                                 &priv_buf, &priv_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
         goto cleanup;
@@ -2785,8 +2954,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
     if (buf_offset + offset < data_len) {
 
         /* Decode CHOICE */
-        rc = ber_decode_CHOICE(buf + offset, TRUE, &choice, &choice_len,
-                               &field_len, &option);
+        rc = ber_decode_CHOICE(buf + offset, buf_len - offset, TRUE,
+                               &choice, &choice_len, &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_CHOICE failed\n");
             goto cleanup;
@@ -2803,8 +2972,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
             break;
         case 1:
             /* publicKey  [1] BIT STRING OPTIONAL */
-            rc = ber_decode_BIT_STRING(buf + offset, &pub_buf, &pub_len,
-                                       &field_len);
+            rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset,
+                                       &pub_buf, &pub_len, &field_len);
             if (rc != CKR_OK) {
                 TRACE_DEVEL("ber_decode_BIT_STRING failed\n");
                 goto cleanup;
@@ -2887,7 +3056,8 @@ CK_RV ber_encode_ECPublicKey(CK_BBOOL length_only, CK_BYTE **data,
     CK_ULONG ecpoint_len, field_len;
 
     /* CKA_EC_POINT is an BER encoded OCTET STRING. Extract it. */
-    rc = ber_decode_OCTET_STRING((CK_BYTE *)point->pValue, &ecpoint,
+    rc = ber_decode_OCTET_STRING((CK_BYTE *)point->pValue, 
+                                 point->ulValueLen, &ecpoint,
                                  &ecpoint_len, &field_len);
     if (rc != CKR_OK || point->ulValueLen != field_len) {
         TRACE_DEVEL("%s ber_decode_OCTET_STRING failed\n", __func__);
@@ -3018,9 +3188,7 @@ CK_RV der_decode_ECPublicKey(CK_BYTE *data,
     CK_ULONG field_len, len;
     CK_RV rc;
 
-    UNUSED(data_len); // XXX can this parameter be removed ?
-
-    rc = ber_decode_SPKI(data, &algid, &algid_len, &param, &param_len,
+    rc = ber_decode_SPKI(data, data_len, &algid, &algid_len, &param, &param_len,
                          &point, &point_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
@@ -3032,8 +3200,9 @@ CK_RV der_decode_ECPublicKey(CK_BYTE *data,
      * Extract base alg-id of DER encoded EC byte string
      * and compare against the decoded alg-id from the inner sequence
      */
-    rc = ber_decode_SEQUENCE((CK_BYTE *)der_AlgIdECBase, &algid_ECBase, &len,
-                             &field_len);
+    rc = ber_decode_SEQUENCE((CK_BYTE *)der_AlgIdECBase, 
+                             der_AlgIdECBaseLen, &algid_ECBase, 
+                             &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
@@ -3251,10 +3420,11 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data,
     CK_BYTE *buf = NULL;
     CK_BYTE *dhkey = NULL;
     CK_BYTE *tmp = NULL;
-    CK_ULONG buf_len, field_len, len, offset;
+    CK_ULONG buf_len, field_len, len, dhkey_len, offset;
     CK_RV rc;
 
-    rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &len, &dhkey);
+    rc = ber_decode_PrivateKeyInfo(data, data_len, &alg, &len,
+                                   &dhkey, &dhkey_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
         return rc;
@@ -3267,7 +3437,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data,
     }
     // extract the parameter data into ATTRIBUTES
     //
-    rc = ber_decode_SEQUENCE(alg + ber_idDHLen, &buf, &buf_len, &field_len);
+    rc = ber_decode_SEQUENCE(alg + ber_idDHLen, len - ber_idDHLen,
+                             &buf, &buf_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
@@ -3275,7 +3446,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data,
     offset = 0;
 
     // prime
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset,
+                            &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -3283,7 +3455,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data,
     offset += field_len;
 
     // base
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset,
+                            &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -3299,7 +3472,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data,
     offset = 0;
 
     // prime
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset,
+                            &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -3313,7 +3487,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data,
     }
 
     // base
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset,
+                            &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -3327,7 +3502,7 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data,
     }
 
     // now get the private key
-    rc = ber_decode_INTEGER(dhkey, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(dhkey, dhkey_len, &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -3549,9 +3724,7 @@ CK_RV ber_decode_DHPublicKey(CK_BYTE *data,
     CK_ULONG field_len, offset;
     CK_RV rc;
 
-    UNUSED(data_len); // XXX can this parameter be removed ?
-
-    rc = ber_decode_SPKI(data, &algid, &algid_len, &param, &param_len,
+    rc = ber_decode_SPKI(data, data_len, &algid, &algid_len, &param, &param_len,
                          &val, &val_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
@@ -3566,20 +3739,21 @@ CK_RV ber_decode_DHPublicKey(CK_BYTE *data,
         return CKR_FUNCTION_FAILED;
     }
 
-    rc = ber_decode_SEQUENCE(param, &seq, &seq_len, &field_len);
+    rc = ber_decode_SEQUENCE(param, param_len, &seq, &seq_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
     }
 
-    rc = ber_decode_INTEGER(seq, &p, &p_len, &field_len);
+    rc = ber_decode_INTEGER(seq, seq_len, &p, &p_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
     }
 
     offset = field_len;
-    rc = ber_decode_INTEGER(seq + offset, &b, &b_len, &field_len);
+    rc = ber_decode_INTEGER(seq + offset, seq_len - offset, &b, &b_len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
@@ -3823,10 +3997,8 @@ static CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data,
     CK_ULONG field_len, offset, raw_spki_len;
     CK_RV rc;
 
-    UNUSED(data_len); // XXX can this parameter be removed ?
-
-    rc = ber_decode_SPKI(data, &algoid, &algoid_len, &param, &param_len,
-                         &val, &val_len);
+    rc = ber_decode_SPKI(data, data_len, &algoid, &algoid_len,
+                         &param, &param_len, &val, &val_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
        return rc;
@@ -3843,14 +4015,14 @@ static CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data,
      *       BIT STRING = rho
      *       BIT STRING = t1
      */
-    rc = ber_decode_SEQUENCE(val, &seq, &seq_len, &field_len);
+    rc = ber_decode_SEQUENCE(val, val_len, &seq, &seq_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
     }
 
     /* Decode rho */
-    rc = ber_decode_BIT_STRING(seq, &rho, &rho_len, &field_len);
+    rc = ber_decode_BIT_STRING(seq, seq_len, &rho, &rho_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
@@ -3860,7 +4032,8 @@ static CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data,
 
     /* Decode t1 */
     offset = field_len;
-    rc = ber_decode_BIT_STRING(seq + offset, &t1, &t1_len, &field_len);
+    rc = ber_decode_BIT_STRING(seq + offset, seq_len - offset, &t1, &t1_len,
+                               &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
@@ -3883,7 +4056,7 @@ static CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data,
     }
 
     /* Add raw SPKI as CKA_VALUE to public key (z/OS ICSF compatibility) */
-    rc = ber_decode_SEQUENCE(data, &val, &val_len, &raw_spki_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &val, &val_len, &raw_spki_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n", __func__, rc);
         goto cleanup;
@@ -4179,12 +4352,13 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     CK_BYTE *dilithium_priv_key = NULL;
     CK_BYTE *buf = NULL;
     CK_BYTE *tmp = NULL;
-    CK_ULONG offset, buf_len, field_len, len, option;
+    CK_ULONG offset, buf_len, field_len, len, dilithium_priv_key_len, option;
     CK_RV rc;
 
     /* Check if this is a Dilithium private key */
     rc = ber_decode_PrivateKeyInfo(data, data_len, &algoid, &len,
-                                   &dilithium_priv_key);
+                                   &dilithium_priv_key,
+                                   &dilithium_priv_key_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
         return rc;
@@ -4203,7 +4377,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     }
 
     /* Decode private Dilithium key */
-    rc = ber_decode_SEQUENCE(dilithium_priv_key, &buf, &buf_len, &field_len);
+    rc = ber_decode_SEQUENCE(dilithium_priv_key, dilithium_priv_key_len,
+                             &buf, &buf_len, &field_len);
     if (rc != CKR_OK)
         return rc;
 
@@ -4211,7 +4386,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     offset = 0;
 
     /* Skip the version */
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -4219,7 +4395,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     offset += field_len;
 
     /* rho */
-    rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                               &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_BIT_STRING of (rho) failed\n");
         goto cleanup;
@@ -4235,7 +4412,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     }
 
     /* seed */
-    rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                               &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_BIT_STRING of (seed) failed\n");
         goto cleanup;
@@ -4251,7 +4429,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     }
 
     /* tr */
-    rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                               &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_BIT_STRING of (tr) failed\n");
         goto cleanup;
@@ -4267,7 +4446,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     }
 
     /* s1 */
-    rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                               &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_BIT_STRING of (s1) failed\n");
         goto cleanup;
@@ -4283,7 +4463,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     }
 
     /* s2 */
-    rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                               &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_BIT_STRING of (s2) failed\n");
         goto cleanup;
@@ -4299,7 +4480,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     }
 
     /* t0 */
-    rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                               &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_BIT_STRING of (t0) failed\n");
         goto cleanup;
@@ -4316,8 +4498,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
 
     /* t1 (optional, within choice) */
     if (offset < buf_len) {
-        rc = ber_decode_CHOICE(buf + offset, TRUE, &tmp, &len, &field_len,
-                               &option);
+        rc = ber_decode_CHOICE(buf + offset, buf_len - offset, TRUE,
+                               &tmp, &len, &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n");
             goto cleanup;
@@ -4331,7 +4513,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
 
         offset += field_len - len;
 
-        rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+        rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                                   &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n");
             goto cleanup;
@@ -4355,7 +4538,7 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
     }
 
     /* Add private key as CKA_VALUE to public key (z/OS ICSF compatibility) */
-    rc = ber_decode_SEQUENCE(data, &tmp, &len, &field_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n", __func__, rc);
         goto cleanup;
@@ -4577,10 +4760,8 @@ static CK_RV ber_decode_IBM_KyberPublicKey(CK_BYTE *data,
     CK_ULONG field_len, raw_spki_len;
     CK_RV rc;
 
-    UNUSED(data_len); // XXX can this parameter be removed ?
-
-    rc = ber_decode_SPKI(data, &algoid, &algoid_len, &param, &param_len,
-                         &val, &val_len);
+    rc = ber_decode_SPKI(data, data_len, &algoid, &algoid_len,
+                         &param, &param_len, &val, &val_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
        return rc;
@@ -4596,14 +4777,14 @@ static CK_RV ber_decode_IBM_KyberPublicKey(CK_BYTE *data,
      *     SEQUENCE (1 elem)
      *       BIT STRING = pk
      */
-    rc = ber_decode_SEQUENCE(val, &seq, &seq_len, &field_len);
+    rc = ber_decode_SEQUENCE(val, val_len, &seq, &seq_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
     }
 
     /* Decode pk */
-    rc = ber_decode_BIT_STRING(seq, &pk, &pk_len, &field_len);
+    rc = ber_decode_BIT_STRING(seq, seq_len, &pk, &pk_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         return rc;
@@ -4619,7 +4800,7 @@ static CK_RV ber_decode_IBM_KyberPublicKey(CK_BYTE *data,
     }
 
     /* Add raw SPKI as CKA_VALUE to public key (z/OS ICSF compatibility) */
-    rc = ber_decode_SEQUENCE(data, &val, &val_len, &raw_spki_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &val, &val_len, &raw_spki_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n", __func__, rc);
         goto cleanup;
@@ -4845,12 +5026,12 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
     CK_BYTE *kyber_priv_key = NULL;
     CK_BYTE *buf = NULL;
     CK_BYTE *tmp = NULL;
-    CK_ULONG offset, buf_len, field_len, len, option;
+    CK_ULONG offset, buf_len, field_len, len, kyber_priv_key_len, option;
     CK_RV rc;
 
     /* Check if this is a Kyber private key */
     rc = ber_decode_PrivateKeyInfo(data, data_len, &algoid, &len,
-                                   &kyber_priv_key);
+                                   &kyber_priv_key, &kyber_priv_key_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
         return rc;
@@ -4869,7 +5050,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
     }
 
     /* Decode private Kyber key */
-    rc = ber_decode_SEQUENCE(kyber_priv_key, &buf, &buf_len, &field_len);
+    rc = ber_decode_SEQUENCE(kyber_priv_key, kyber_priv_key_len,
+                             &buf, &buf_len, &field_len);
     if (rc != CKR_OK)
         return rc;
 
@@ -4877,7 +5059,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
     offset = 0;
 
     /* Skip the version */
-    rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_INTEGER(buf + offset, buf_len - offset, &tmp, &len,
+                            &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_INTEGER failed\n");
         goto cleanup;
@@ -4885,7 +5068,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
     offset += field_len;
 
     /* sk */
-    rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+    rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                               &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_BIT_STRING of (sk) failed\n");
         goto cleanup;
@@ -4902,8 +5086,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
 
     /* pk (optional, within choice) */
     if (offset < buf_len) {
-        rc = ber_decode_CHOICE(buf + offset, TRUE, &tmp, &len, &field_len,
-                               &option);
+        rc = ber_decode_CHOICE(buf + offset, buf_len - offset, TRUE,
+                               &tmp, &len, &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n");
             goto cleanup;
@@ -4917,7 +5101,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
 
         offset += field_len - len;
 
-        rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
+        rc = ber_decode_BIT_STRING(buf + offset, buf_len - offset, &tmp, &len,
+                                   &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_BIT_STRING of (pk) failed\n");
             goto cleanup;
@@ -4944,7 +5129,7 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
     }
 
     /* Add private key as CKA_VALUE to public key (z/OS ICSF compatibility) */
-    rc = ber_decode_SEQUENCE(data, &tmp, &len, &field_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n", __func__, rc);
         goto cleanup;
@@ -5102,8 +5287,8 @@ CK_RV ber_decode_IBM_ML_DSA_PublicKey(CK_MECHANISM_TYPE mech,
      *    BIT STRING - public key (rho | t1)
      */
 
-    rc = ber_decode_SPKI(data, &algoid, &algoid_len, &param, &param_len,
-                         &pub, &pub_len);
+    rc = ber_decode_SPKI(data, data_len, &algoid, &algoid_len,
+                         &param, &param_len, &pub, &pub_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
        return rc;
@@ -5139,7 +5324,7 @@ CK_RV ber_decode_IBM_ML_DSA_PublicKey(CK_MECHANISM_TYPE mech,
     }
 
     /* Add raw SPKI as CKA_VALUE to public key (z/OS ICSF compatibility) */
-    rc = ber_decode_SEQUENCE(data, &pub, &pub_len, &raw_spki_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &pub, &pub_len, &raw_spki_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n",
                     __func__, rc);
@@ -5375,7 +5560,7 @@ CK_RV ber_decode_IBM_ML_DSA_PrivateKey(CK_MECHANISM_TYPE mech,
     CK_BYTE *algid = NULL, *priv = NULL, *both = NULL, *key = NULL;
     CK_BYTE *pseed = NULL, *tmp = NULL;
     CK_ULONG both_len, field_len, algid_len, key_len = 0, pseed_len = 0;
-    CK_ULONG ofs = 0, option, len;
+    CK_ULONG ofs = 0, option, len, priv_len;
     CK_RV rc;
 
     if (mech == CKM_IBM_DILITHIUM) {
@@ -5387,7 +5572,7 @@ CK_RV ber_decode_IBM_ML_DSA_PrivateKey(CK_MECHANISM_TYPE mech,
 
     /* Check if this is a ML-DSA private key */
     rc = ber_decode_PrivateKeyInfo(data, data_len, &algid, &algid_len,
-                                   &priv);
+                                   &priv, &priv_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
         return rc;
@@ -5413,35 +5598,37 @@ CK_RV ber_decode_IBM_ML_DSA_PrivateKey(CK_MECHANISM_TYPE mech,
      */
     switch (priv[0]) {
     case 0x30: /* SEQUENCE  - both format*/
-        rc = ber_decode_SEQUENCE(priv, &both, &both_len, &field_len);
+        rc = ber_decode_SEQUENCE(priv, priv_len, &both, &both_len, &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
             return rc;
         }
 
-        rc = ber_decode_OCTET_STRING(both, &pseed, &pseed_len, &field_len);
+        rc = ber_decode_OCTET_STRING(both, both_len, &pseed, &pseed_len,
+                                     &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
             return rc;
         }
 
-        rc = ber_decode_OCTET_STRING(both + field_len, &key, &key_len,
-                                     &field_len);
+        rc = ber_decode_OCTET_STRING(both + field_len, both_len - field_len,
+                                     &key, &key_len, &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
             return rc;
         }
         break;
     case 0x04: /* OCTET STRING - expanded key */
-        rc = ber_decode_OCTET_STRING(priv, &key, &key_len, &field_len);
+        rc = ber_decode_OCTET_STRING(priv, priv_len, &key, &key_len,
+                                     &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
             return rc;
         }
         break;
     case 0x80: /* CHOICE - private seed only */
-        rc = ber_decode_CHOICE(priv, FALSE, &pseed, &pseed_len, &field_len,
-                               &option);
+        rc = ber_decode_CHOICE(priv, priv_len, FALSE, &pseed, &pseed_len,
+                               &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_CHOICE failed\n");
             return rc;
@@ -5529,7 +5716,7 @@ CK_RV ber_decode_IBM_ML_DSA_PrivateKey(CK_MECHANISM_TYPE mech,
     }
 
     /* Add private key as CKA_VALUE to public key (z/OS ICSF compatibility) */
-    rc = ber_decode_SEQUENCE(data, &tmp, &len, &field_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n",
                     __func__, rc);
@@ -5689,8 +5876,8 @@ CK_RV ber_decode_IBM_ML_KEM_PublicKey(CK_MECHANISM_TYPE mech,
      *    BIT STRING - public key (pk)
      */
 
-    rc = ber_decode_SPKI(data, &algoid, &algoid_len, &param, &param_len,
-                         &pub, &pub_len);
+    rc = ber_decode_SPKI(data, data_len, &algoid, &algoid_len,
+                         &param, &param_len, &pub, &pub_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
        return rc;
@@ -5716,7 +5903,7 @@ CK_RV ber_decode_IBM_ML_KEM_PublicKey(CK_MECHANISM_TYPE mech,
     }
 
     /* Add raw SPKI as CKA_VALUE to public key (z/OS ICSF compatibility) */
-    rc = ber_decode_SEQUENCE(data, &pub, &pub_len, &raw_spki_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &pub, &pub_len, &raw_spki_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n",
                     __func__, rc);
@@ -5898,7 +6085,7 @@ CK_RV ber_decode_IBM_ML_KEM_PrivateKey(CK_MECHANISM_TYPE mech,
     CK_BYTE *algid = NULL, *priv = NULL, *both = NULL, *key = NULL;
     CK_BYTE *pseed = NULL, *tmp = NULL;
     CK_ULONG both_len, field_len, algid_len, key_len = 0, pseed_len = 0;
-    CK_ULONG option, len;
+    CK_ULONG option, len, priv_len;
     CK_RV rc;
 
     if (mech == CKM_IBM_KYBER) {
@@ -5909,7 +6096,7 @@ CK_RV ber_decode_IBM_ML_KEM_PrivateKey(CK_MECHANISM_TYPE mech,
 
     /* Check if this is a ML-KEM private key */
     rc = ber_decode_PrivateKeyInfo(data, data_len, &algid, &algid_len,
-                                   &priv);
+                                   &priv, &priv_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
         return rc;
@@ -5935,35 +6122,37 @@ CK_RV ber_decode_IBM_ML_KEM_PrivateKey(CK_MECHANISM_TYPE mech,
      */
     switch (priv[0]) {
     case 0x30: /* SEQUENCE  - both format*/
-        rc = ber_decode_SEQUENCE(priv, &both, &both_len, &field_len);
+        rc = ber_decode_SEQUENCE(priv, priv_len, &both, &both_len, &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
             return rc;
         }
 
-        rc = ber_decode_OCTET_STRING(both, &pseed, &pseed_len, &field_len);
+        rc = ber_decode_OCTET_STRING(both, both_len, &pseed, &pseed_len,
+                                     &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
             return rc;
         }
 
-        rc = ber_decode_OCTET_STRING(both + field_len, &key, &key_len,
-                                     &field_len);
+        rc = ber_decode_OCTET_STRING(both + field_len, both_len - field_len,
+                                     &key, &key_len, &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
             return rc;
         }
         break;
     case 0x04: /* OCTET STRING - expanded key */
-        rc = ber_decode_OCTET_STRING(priv, &key, &key_len, &field_len);
+        rc = ber_decode_OCTET_STRING(priv, priv_len, &key, &key_len,
+                                     &field_len);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
             return rc;
         }
         break;
     case 0x80: /* CHOICE - private seed only */
-        rc = ber_decode_CHOICE(priv, FALSE, &pseed, &pseed_len, &field_len,
-                               &option);
+        rc = ber_decode_CHOICE(priv, priv_len, FALSE, &pseed, &pseed_len,
+                               &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_CHOICE failed\n");
             return rc;
@@ -6006,7 +6195,7 @@ CK_RV ber_decode_IBM_ML_KEM_PrivateKey(CK_MECHANISM_TYPE mech,
     }
 
     /* Add private key as CKA_VALUE to public key (z/OS ICSF compatibility) */
-    rc = ber_decode_SEQUENCE(data, &tmp, &len, &field_len);
+    rc = ber_decode_SEQUENCE(data, data_len, &tmp, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n",
                     __func__, rc);
diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
index 884bc9ed3..c61969b6c 100644
--- a/usr/lib/common/h_extern.h
+++ b/usr/lib/common/h_extern.h
@@ -2923,7 +2923,7 @@ CK_ULONG ber_encode_INTEGER(CK_BBOOL length_only,
                             CK_ULONG *ber_int_len,
                             CK_BYTE *data, CK_ULONG data_len);
 
-CK_RV ber_decode_INTEGER(CK_BYTE *ber_int,
+CK_RV ber_decode_INTEGER(CK_BYTE *ber_int, CK_ULONG ber_int_len,
                          CK_BYTE **data,
                          CK_ULONG *data_len, CK_ULONG *field_len);
 
@@ -2933,7 +2933,7 @@ CK_ULONG ber_encode_BIT_STRING(CK_BBOOL length_only,
                                CK_ULONG data_len,
                                CK_BYTE unused_bits);
 
-CK_RV ber_decode_BIT_STRING(CK_BYTE *str,
+CK_RV ber_decode_BIT_STRING(CK_BYTE *str, CK_ULONG str_len,
                             CK_BYTE **data,
                             CK_ULONG *data_len, CK_ULONG *field_len);
 
@@ -2942,7 +2942,7 @@ CK_RV ber_encode_OCTET_STRING(CK_BBOOL length_only,
                               CK_ULONG *str_len,
                               CK_BYTE *data, CK_ULONG data_len);
 
-CK_RV ber_decode_OCTET_STRING(CK_BYTE *str,
+CK_RV ber_decode_OCTET_STRING(CK_BYTE *str, CK_ULONG str_len,
                               CK_BYTE **data,
                               CK_ULONG *data_len, CK_ULONG *field_len);
 
@@ -2951,7 +2951,7 @@ CK_RV ber_encode_SEQUENCE(CK_BBOOL length_only,
                           CK_ULONG *seq_len,
                           CK_BYTE *data, CK_ULONG data_len);
 
-CK_RV ber_decode_SEQUENCE(CK_BYTE *seq,
+CK_RV ber_decode_SEQUENCE(CK_BYTE *seq, CK_ULONG seq_len,
                           CK_BYTE **data,
                           CK_ULONG *data_len, CK_ULONG *field_len);
 
@@ -2961,7 +2961,8 @@ CK_RV ber_encode_CHOICE(CK_BBOOL length_only,
                         CK_ULONG *str_len, CK_BYTE *data, CK_ULONG data_len,
                         CK_BBOOL constructed);
 
-CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed,
+CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_ULONG choice_len,
+                        CK_BBOOL constructed,
                         CK_BYTE **data,
                         CK_ULONG *data_len, CK_ULONG *field_len,
                         CK_ULONG *option);
@@ -2973,12 +2974,12 @@ CK_RV ber_encode_PrivateKeyInfo(CK_BBOOL length_only,
                                 const CK_ULONG algorithm_id_len,
                                 CK_BYTE *priv_key, CK_ULONG priv_key_len);
 
-CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data,
-                                CK_ULONG data_len,
-                                CK_BYTE **algorithm_id,
-                                CK_ULONG *alg_len, CK_BYTE **priv_key);
+CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data, CK_ULONG data_len,
+                                CK_BYTE **algorithm_id, CK_ULONG *alg_len,
+                                CK_BYTE **priv_key, CK_ULONG *priv_key_len);
 
-CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_BYTE **alg_oid, CK_ULONG *alg_oid_len,
+CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_ULONG spki_len,
+                      CK_BYTE **alg_oid, CK_ULONG *alg_oid_len,
                       CK_BYTE **param, CK_ULONG *param_len,
                       CK_BYTE **key, CK_ULONG *key_len);
 
diff --git a/usr/lib/common/key_mgr.c b/usr/lib/common/key_mgr.c
index 08b38a806..4d1003070 100644
--- a/usr/lib/common/key_mgr.c
+++ b/usr/lib/common/key_mgr.c
@@ -1656,10 +1656,11 @@ CK_RV key_mgr_get_private_key_type(CK_BYTE *keydata,
 {
     CK_BYTE *alg = NULL;
     CK_BYTE *priv_key = NULL;
-    CK_ULONG alg_len, i;
+    CK_ULONG alg_len, priv_key_len, i;
     CK_RV rc;
 
-    rc = ber_decode_PrivateKeyInfo(keydata, keylen, &alg, &alg_len, &priv_key);
+    rc = ber_decode_PrivateKeyInfo(keydata, keylen, &alg, &alg_len,
+                                   &priv_key, &priv_key_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_PrivateKeyInfo failed.\n");
         return rc;
diff --git a/usr/lib/common/mech_ec.c b/usr/lib/common/mech_ec.c
index ce031ec0c..2b1609e4f 100644
--- a/usr/lib/common/mech_ec.c
+++ b/usr/lib/common/mech_ec.c
@@ -1511,7 +1511,7 @@ int ec_point_from_public_data(const CK_BYTE *data, CK_ULONG data_len,
 
 check_encoded:
     /* If we reach here, try to BER decode it as OCTET-STRING */
-    rc = ber_decode_OCTET_STRING((CK_BYTE *)data, &value, &value_len,
+    rc = ber_decode_OCTET_STRING((CK_BYTE *)data, data_len, &value, &value_len,
                                   &field_len);
     if (rc == CKR_OK && field_len == data_len && value_len <= data_len - 2) {
          /* Looks like a BER encoded EC Point */
@@ -1776,6 +1776,7 @@ CK_RV ecdh_aes_key_wrap(STDLL_TokData_t *tokdata, SESSION *sess,
     }
 
     rc = ber_decode_OCTET_STRING((CK_BYTE *)ec_point->pValue,
+                                  ec_point->ulValueLen,
                                   &pub_ec_point, &pub_ec_point_len, &field_len);
     if (rc != CKR_OK || field_len != ec_point->ulValueLen) {
         rc = CKR_FUNCTION_FAILED;
@@ -1796,6 +1797,7 @@ CK_RV ecdh_aes_key_wrap(STDLL_TokData_t *tokdata, SESSION *sess,
     }
 
     rc = ber_decode_OCTET_STRING((CK_BYTE *)ec_point->pValue,
+                                  ec_point->ulValueLen,
                                   &ecdh_params.pPublicData,
                                   &ecdh_params.ulPublicDataLen,
                                   &field_len);
diff --git a/usr/lib/common/pkey_utils.c b/usr/lib/common/pkey_utils.c
index 0a9f77e76..241629f81 100644
--- a/usr/lib/common/pkey_utils.c
+++ b/usr/lib/common/pkey_utils.c
@@ -1604,8 +1604,8 @@ struct {                          \
     }
 
     /* CKA_EC_POINT is an BER encoded OCTET STRING. Extract it. */
-    rc = ber_decode_OCTET_STRING(pub_attr->pValue, &ecpoint,
-                                 &ecpoint_len, &field_len);
+    rc = ber_decode_OCTET_STRING(pub_attr->pValue, pub_attr->ulValueLen,
+                                 &ecpoint, &ecpoint_len, &field_len);
     if (rc != CKR_OK || pub_attr->ulValueLen != field_len) {
         TRACE_ERROR("%s: ber_decode_OCTET_STRING failed\n", __func__);
         ret = CKR_ATTRIBUTE_VALUE_INVALID;
@@ -1752,8 +1752,8 @@ struct {                            \
     }
 
     /* CKA_EC_POINT is an BER encoded OCTET STRING. Extract it. */
-    rc = ber_decode_OCTET_STRING(pub_attr->pValue, &ecpoint,
-                                 &ecpoint_len, &field_len);
+    rc = ber_decode_OCTET_STRING(pub_attr->pValue, pub_attr->ulValueLen,
+                                 &ecpoint, &ecpoint_len, &field_len);
     if (rc != CKR_OK || pub_attr->ulValueLen != field_len) {
         TRACE_ERROR("%s: ber_decode_OCTET_STRING failed\n", __func__);
         ret = CKR_ATTRIBUTE_VALUE_INVALID;
diff --git a/usr/lib/ep11_stdll/ep11_login.c b/usr/lib/ep11_stdll/ep11_login.c
index 10f1366e3..e89e1b5ce 100644
--- a/usr/lib/ep11_stdll/ep11_login.c
+++ b/usr/lib/ep11_stdll/ep11_login.c
@@ -113,13 +113,14 @@ static CK_RV get_login_importer_key(target_t target,
      *             tcounter OCTET STRING  (16 bytes)
      */
 
-    rc = ber_decode_SEQUENCE(res, &data, &data_len, &field_len);
+    rc = ber_decode_SEQUENCE(res, reslen, &data, &data_len, &field_len);
     if (rc != CKR_OK || field_len > reslen) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed\n", __func__);
         return CKR_FUNCTION_FAILED;
     }
 
-    rc = ber_decode_OCTET_STRING(data, &ski_field, &ski_field_len, &field_len);
+    rc = ber_decode_OCTET_STRING(data, data_len, &ski_field, &ski_field_len,
+                                 &field_len);
     if (rc != CKR_OK || field_len > data_len) {
         TRACE_ERROR("%s ber_decode_OCTET_STRING (SKI) failed\n", __func__);
         return CKR_FUNCTION_FAILED;
@@ -128,7 +129,7 @@ static CK_RV get_login_importer_key(target_t target,
     data += field_len;
     data_len -= field_len;
 
-    rc = ber_decode_OCTET_STRING(data, &spki, &spki_len, &field_len);
+    rc = ber_decode_OCTET_STRING(data, data_len, &spki, &spki_len, &field_len);
     if (rc != CKR_OK || field_len > data_len) {
         TRACE_ERROR("%s ber_decode_OCTET_STRING (SPKI) failed\n", __func__);
         return CKR_FUNCTION_FAILED;
@@ -137,7 +138,7 @@ static CK_RV get_login_importer_key(target_t target,
     data += field_len;
     data_len -= field_len;
 
-    rc = ber_decode_OCTET_STRING(data, &cnt, &cnt_len, &field_len);
+    rc = ber_decode_OCTET_STRING(data, data_len, &cnt, &cnt_len, &field_len);
     if (rc != CKR_OK || field_len > data_len) {
         TRACE_ERROR("%s ber_decode_OCTET_STRING (COUNTER) failed\n", __func__);
         return CKR_FUNCTION_FAILED;
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
index cb474ebe9..df41be57d 100644
--- a/usr/lib/ep11_stdll/ep11_specific.c
+++ b/usr/lib/ep11_stdll/ep11_specific.c
@@ -1586,7 +1586,8 @@ CK_RV ep11tok_extract_blob_info(CK_BYTE *blob, CK_ULONG blob_len,
      * denoted by 0x30 followed by the DER encoded length of the SPKI.
      */
     if (blob_len > 5 && blob[0] == 0x30 &&
-        ber_decode_SEQUENCE(blob, &data, &data_len, &field_len) == CKR_OK) {
+        ber_decode_SEQUENCE(blob, blob_len, &data, &data_len,
+                            &field_len) == CKR_OK) {
         /* It is a SPKI, fields follow as OCTET STRINGs right after SPKI data */
         if (blob_len < field_len) {
             TRACE_ERROR("MACed SPKI is too small\n");
@@ -1617,7 +1618,8 @@ CK_RV ep11tok_extract_blob_info(CK_BYTE *blob, CK_ULONG blob_len,
                 return CKR_FUNCTION_FAILED;
             }
 
-            if (ber_decode_OCTET_STRING(blob + ofs, &data, &data_len,
+            if (ber_decode_OCTET_STRING(blob + ofs, blob_len - ofs,
+                                        &data, &data_len,
                                         &field_len) != CKR_OK) {
                 TRACE_ERROR("Failed to decode MACed SPKI field %s\n",
                             fields[i].field);
@@ -3671,7 +3673,8 @@ static CK_RV make_maced_spki(STDLL_TokData_t *tokdata, SESSION *sess,
     CK_RV rc;
 
     if (spki_len < 6 ||
-        ber_decode_SEQUENCE(spki, &tmp, &tmp_len, &seq_len) != CKR_OK) {
+        ber_decode_SEQUENCE(spki, spki_len, &tmp, &tmp_len,
+                            &seq_len) != CKR_OK) {
         TRACE_ERROR("%s Its not an SPKI\n", __func__);
         return CKR_FUNCTION_FAILED;
     }
@@ -3798,9 +3801,7 @@ static int get_curve_type_from_spki(CK_BYTE *spki, CK_ULONG spki_len)
     CK_ULONG field_len, len, i;
     CK_RV rc;
 
-    UNUSED(spki_len);
-
-    rc = ber_decode_SPKI(spki, &algid, &algid_len, &param, &param_len,
+    rc = ber_decode_SPKI(spki, spki_len, &algid, &algid_len, &param, &param_len,
                          &pubkey, &pubkey_len);
     if (rc != CKR_OK) {
        TRACE_DEVEL("ber_decode_SPKI failed\n");
@@ -3812,8 +3813,8 @@ static int get_curve_type_from_spki(CK_BYTE *spki, CK_ULONG spki_len)
      * Extract base alg-id of DER encoded EC byte string
      * and compare against the decoded alg-id from the inner sequence
      */
-    rc = ber_decode_SEQUENCE((CK_BYTE *)der_AlgIdECBase, &algid_ECBase, &len,
-                             &field_len);
+    rc = ber_decode_SEQUENCE((CK_BYTE *)der_AlgIdECBase, der_AlgIdECBaseLen,
+                             &algid_ECBase, &len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return -1;
@@ -4335,8 +4336,9 @@ static CK_RV import_EC_key(STDLL_TokData_t *tokdata, SESSION *sess,
         }
 
         /* CKA_EC_POINT is an BER encoded OCTET STRING. Extract it. */
-        rc = ber_decode_OCTET_STRING((CK_BYTE *)ec_point_attr->pValue, &ecpoint,
-                                     &ecpoint_len, &field_len);
+        rc = ber_decode_OCTET_STRING((CK_BYTE *)ec_point_attr->pValue, 
+                                     ec_point_attr->ulValueLen, 
+                                     &ecpoint, &ecpoint_len, &field_len);
         if (rc != CKR_OK || ec_point_attr->ulValueLen != field_len) {
             TRACE_DEVEL("%s ber_decode_OCTET_STRING failed\n", __func__);
             rc = CKR_ATTRIBUTE_VALUE_INVALID;
@@ -5295,7 +5297,7 @@ static CK_RV import_blob_private_public(STDLL_TokData_t *tokdata, SESSION *sess,
     }
 
     /* SPKI is a MACed SPKI, get length of SPKI part only */
-    rc = ber_decode_SEQUENCE(spki, &data, &data_len, &raw_spki_len);
+    rc = ber_decode_SEQUENCE(spki, spki_len, &data, &data_len, &raw_spki_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_SEQUENCE failed rc=0x%lx\n",
                     __func__, rc);
@@ -6189,7 +6191,7 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
 
     if (spkisize > 0 && (class == CKO_PRIVATE_KEY || class == CKO_PUBLIC_KEY)) {
         /* spki may be a MACed SPKI, get length of SPKI part only */
-        rc = ber_decode_SEQUENCE(spki, &temp, &temp_len, &spkisize);
+        rc = ber_decode_SEQUENCE(spki, spkisize, &temp, &temp_len, &spkisize);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s ber_decode_SEQUENCE failed rc=0x%lx\n",
                         __func__, rc);
@@ -8741,8 +8743,10 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t *tokdata, SESSION *session,
                 object_put(tokdata, base_key_obj, TRUE);
                 base_key_obj = NULL;
             } else {
-                rc = ber_decode_OCTET_STRING(ecdh1_parms->pPublicData, &ecpoint,
-                                             &ecpoint_len, &field_len);
+                rc = ber_decode_OCTET_STRING(ecdh1_parms->pPublicData,
+                                             ecdh1_parms->ulPublicDataLen,
+                                             &ecpoint, &ecpoint_len,
+                                             &field_len);
                 if (rc != CKR_OK || field_len != ecdh1_parms->ulPublicDataLen ||
                     ecpoint_len > ecdh1_parms->ulPublicDataLen - 2) {
                     /* no valid BER OCTET STRING encoding, assume raw */
@@ -9524,15 +9528,15 @@ static CK_RV dh_generate_keypair(STDLL_TokData_t *tokdata,
 #endif
 
     /* CKA_VALUE of the public key must hold 'y' */
-    rc = ber_decode_SPKI(publblob, &oid, &oid_len, &parm, &parm_len,
-                         &y_start, &bit_str_len);
+    rc = ber_decode_SPKI(publblob, publblobsize, &oid, &oid_len,
+                         &parm, &parm_len, &y_start, &bit_str_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode SKPI failed rc=0x%lx\n", __func__, rc);
         goto dh_generate_keypair_end;
     }
 
     /* DHPublicKey ::= INTEGER -- public key, y = g^x mod p */
-    rc = ber_decode_INTEGER(y_start, &data, &data_len, &field_len);
+    rc = ber_decode_INTEGER(y_start, bit_str_len, &data, &data_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s ber_decode_INTEGER failed rc=0x%lx\n", __func__, rc);
         goto dh_generate_keypair_end;
@@ -9933,15 +9937,15 @@ static CK_RV dsa_generate_keypair(STDLL_TokData_t *tokdata,
     }
 
     /* set CKA_VALUE of the public key, first get key from SPKI */
-    rc = ber_decode_SPKI(publblob, &oid, &oid_len, &parm, &parm_len,
-                         &key, &bit_str_len);
+    rc = ber_decode_SPKI(publblob, publblobsize, &oid, &oid_len,
+                         &parm, &parm_len, &key, &bit_str_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s reading DSA SPKI failed with rc=0x%lx\n", __func__, rc);
         goto dsa_generate_keypair_end;
     }
 
     /* key must be an integer */
-    rc = ber_decode_INTEGER(key, &data, &data_len, &field_len);
+    rc = ber_decode_INTEGER(key, bit_str_len, &data, &data_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s reading DSA public key failed with rc=0x%lx\n",
                     __func__, rc);
@@ -10214,7 +10218,7 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata,
         TRACE_DEBUG("%s ec_generate_keypair spki:\n", __func__);
         TRACE_DEBUG_DUMP("    ", spki, spki_len);
 #endif
-        rc = ber_decode_SPKI(spki, &oid, &oid_len, &parm, &parm_len,
+        rc = ber_decode_SPKI(spki, spki_len, &oid, &oid_len, &parm, &parm_len,
                              &key, &bit_str_len);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s read key from SPKI failed with rc=0x%lx\n",
@@ -10310,8 +10314,9 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata,
          * already built SPKI (in CKA_IBM_OPAQUE of the public key).
          */
         CK_BYTE *modulus, *publ_exp;
+        CK_ULONG modulus_len, publ_exp_len;
 
-        rc = ber_decode_SPKI(spki, &oid, &oid_len, &parm, &parm_len,
+        rc = ber_decode_SPKI(spki, spki_len, &oid, &oid_len, &parm, &parm_len,
                              &key, &bit_str_len);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s read key from SPKI failed with rc=0x%lx\n",
@@ -10322,7 +10327,8 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata,
         /* key must be a sequence holding two integers,
          * modulus and public exponent
          */
-        rc = ber_decode_SEQUENCE(key, &data, &data_len, &field_len);
+        rc = ber_decode_SEQUENCE(key, bit_str_len, &data, &data_len,
+                                 &field_len);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s read sequence failed with rc=0x%lx\n",
                         __func__, rc);
@@ -10330,7 +10336,9 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata,
         }
 
         modulus = key + field_len - data_len;
-        rc = ber_decode_INTEGER(modulus, &data, &data_len, &field_len);
+        modulus_len = bit_str_len - field_len + data_len;
+        rc = ber_decode_INTEGER(modulus, modulus_len, &data, &data_len,
+                                &field_len);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s read modulus failed with rc=0x%lx\n", __func__, rc);
             goto error;
@@ -10357,7 +10365,9 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata,
 
         /* read public exponent */
         publ_exp = modulus + field_len;
-        rc = ber_decode_INTEGER(publ_exp, &data, &data_len, &field_len);
+        publ_exp_len = bit_str_len - field_len;
+        rc = ber_decode_INTEGER(publ_exp, publ_exp_len, &data, &data_len,
+                                &field_len);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s read public exponent failed with rc=0x%lx\n",
                         __func__, rc);
@@ -13929,7 +13939,7 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session,
         }
 
         /* csum is a MACed SPKI, get length of SPKI part only */
-        rc = ber_decode_SEQUENCE(csum, &temp, &temp_len, &cslen);
+        rc = ber_decode_SEQUENCE(csum, cslen, &temp, &temp_len, &cslen);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s ber_decode_SEQUENCE failed rc=0x%lx\n",
                         __func__, rc);
diff --git a/usr/lib/ica_s390_stdll/ica_specific.c b/usr/lib/ica_s390_stdll/ica_specific.c
index 005b3c19c..192b1ea55 100644
--- a/usr/lib/ica_s390_stdll/ica_specific.c
+++ b/usr/lib/ica_s390_stdll/ica_specific.c
@@ -6244,8 +6244,8 @@ static CK_RV ica_build_ec_pub_key(OBJECT *key_obj, ICA_EC_KEY **eckey,
     }
 
     /* CKA_EC_POINT contains the EC point as OCTET STRING */
-    ret = ber_decode_OCTET_STRING(attr->pValue, &ecpoint, &ecpoint_len,
-                                  &field_len);
+    ret = ber_decode_OCTET_STRING(attr->pValue, attr->ulValueLen,
+                                  &ecpoint, &ecpoint_len, &field_len);
     if (ret != CKR_OK || field_len != attr->ulValueLen) {
         TRACE_DEVEL("ber_decode_OCTET_STRING failed\n");
         ret = CKR_ATTRIBUTE_VALUE_INVALID;
