From f1139483b1fb12e4bb99bbf1ffbb7d977ec74e54 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                 | 472 ++++++++++++++++++--------
 usr/lib/common/h_extern.h             |  18 +-
 usr/lib/common/key_mgr.c              |   5 +-
 usr/lib/common/mech_ec.c              |   2 +-
 usr/lib/common/pkey_utils.c           |   8 +-
 usr/lib/ep11_stdll/ep11_login.c       |   9 +-
 usr/lib/ep11_stdll/ep11_mkchange.c    |   7 +-
 usr/lib/ep11_stdll/ep11_specific.c    |  53 +--
 usr/lib/ica_s390_stdll/ica_specific.c |   4 +-
 10 files changed, 391 insertions(+), 191 deletions(-)

diff --git a/usr/lib/cca_stdll/cca_specific.c b/usr/lib/cca_stdll/cca_specific.c
index eeb40ccc1..0ff376dd0 100644
--- a/usr/lib/cca_stdll/cca_specific.c
+++ b/usr/lib/cca_stdll/cca_specific.c
@@ -8706,8 +8706,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 631978edf..7a84d3152 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;
@@ -840,7 +940,7 @@ CK_RV ber_encode_CHOICE(CK_BBOOL length_only,
 //    attributes
 // }
 //
-CK_RV ber_decode_CHOICE(CK_BYTE *choice,
+CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_ULONG choice_len,
                         CK_BYTE **data,
                         CK_ULONG *data_len, CK_ULONG *field_len,
                         CK_ULONG *option)
@@ -848,7 +948,7 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice,
     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;
     }
@@ -864,6 +964,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice,
     //
     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;
@@ -871,9 +975,17 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice,
     }
 
     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;
@@ -884,6 +996,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice,
         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;
@@ -896,6 +1012,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice,
         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;
@@ -1006,10 +1126,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;
@@ -1021,7 +1140,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;
@@ -1029,7 +1148,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;
@@ -1038,15 +1158,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");
 
@@ -1064,13 +1187,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;
 
@@ -1078,7 +1202,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);
@@ -1086,23 +1212,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);
@@ -1369,10 +1507,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;
@@ -1384,7 +1523,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;
 
@@ -1394,7 +1534,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;
@@ -1403,7 +1544,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;
@@ -1412,7 +1554,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;
@@ -1421,7 +1564,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;
@@ -1430,7 +1574,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;
@@ -1439,7 +1584,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;
@@ -1448,7 +1594,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;
@@ -1457,7 +1604,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;
@@ -1466,7 +1614,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;
@@ -1486,7 +1635,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;
@@ -1495,7 +1645,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;
@@ -1510,7 +1661,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;
@@ -1525,7 +1677,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;
@@ -1540,7 +1693,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;
@@ -1555,7 +1709,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;
@@ -1570,7 +1725,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;
@@ -1585,7 +1741,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;
@@ -1600,7 +1757,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;
@@ -1788,9 +1946,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");
@@ -1800,7 +1956,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");
@@ -1812,20 +1969,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;
@@ -2059,11 +2217,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;
@@ -2077,7 +2236,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;
@@ -2086,7 +2246,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;
@@ -2095,7 +2256,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;
@@ -2104,7 +2266,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;
@@ -2123,7 +2286,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;
@@ -2138,7 +2302,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;
@@ -2153,7 +2318,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;
@@ -2168,7 +2334,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;
@@ -2411,9 +2577,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");
@@ -2428,27 +2592,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;
@@ -2547,8 +2713,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;
@@ -2630,8 +2796,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;
@@ -2723,7 +2889,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;
@@ -2737,7 +2903,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;
@@ -2749,7 +2915,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;
@@ -2762,7 +2929,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;
@@ -2770,7 +2937,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;
@@ -2778,8 +2946,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;
@@ -2791,8 +2959,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data,
     if (buf_offset + offset < data_len) {
 
         /* Decode CHOICE */
-        rc = ber_decode_CHOICE(buf + offset, &choice, &choice_len, &field_len,
-                               &option);
+        rc = ber_decode_CHOICE(buf + offset, buf_len - offset,
+                               &choice, &choice_len, &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_CHOICE failed\n");
             goto cleanup;
@@ -2809,8 +2977,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;
@@ -2893,7 +3061,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__);
@@ -3024,9 +3193,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");
@@ -3038,8 +3205,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;
@@ -3257,10 +3425,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;
@@ -3273,7 +3442,8 @@ CK_RV ber_decode_DHPrivateKey(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_idDHLen, len - ber_idDHLen,
+                             &buf, &buf_len, &field_len);
     if (rc != CKR_OK) {
         TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
         return rc;
@@ -3281,7 +3451,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;
@@ -3289,7 +3460,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;
@@ -3305,7 +3477,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;
@@ -3319,7 +3492,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;
@@ -3333,7 +3507,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;
@@ -3555,9 +3729,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");
@@ -3572,20 +3744,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;
@@ -3826,10 +3999,8 @@ 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;
@@ -3846,14 +4017,14 @@ 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;
@@ -3863,7 +4034,8 @@ 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;
@@ -3886,7 +4058,7 @@ 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;
@@ -4182,12 +4354,13 @@ 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;
@@ -4206,7 +4379,8 @@ 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;
 
@@ -4214,7 +4388,8 @@ 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;
@@ -4222,7 +4397,8 @@ 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;
@@ -4238,7 +4414,8 @@ 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;
@@ -4254,7 +4431,8 @@ 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;
@@ -4270,7 +4448,8 @@ 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;
@@ -4286,7 +4465,8 @@ 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;
@@ -4302,7 +4482,8 @@ 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;
@@ -4319,7 +4500,8 @@ CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
 
     /* t1 (optional, within choice) */
     if (offset < buf_len) {
-        rc = ber_decode_CHOICE(buf + offset, &tmp, &len, &field_len, &option);
+        rc = ber_decode_CHOICE(buf + offset, buf_len - offset, 
+                               &tmp, &len, &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n");
             goto cleanup;
@@ -4333,7 +4515,8 @@ 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;
@@ -4357,7 +4540,7 @@ 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;
@@ -4579,10 +4762,8 @@ 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;
@@ -4598,14 +4779,14 @@ 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;
@@ -4621,7 +4802,7 @@ 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;
@@ -4837,12 +5018,12 @@ 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;
@@ -4861,7 +5042,8 @@ 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;
 
@@ -4869,7 +5051,8 @@ 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;
@@ -4877,7 +5060,8 @@ 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;
@@ -4894,7 +5078,8 @@ CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
 
     /* pk (optional, within choice) */
     if (offset < buf_len) {
-        rc = ber_decode_CHOICE(buf + offset, &tmp, &len, &field_len, &option);
+        rc = ber_decode_CHOICE(buf + offset, buf_len - offset,
+                               &tmp, &len, &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n");
             goto cleanup;
@@ -4908,7 +5093,8 @@ 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;
@@ -4935,7 +5121,7 @@ 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;
diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
index b2087f41b..58cf4d4b2 100644
--- a/usr/lib/common/h_extern.h
+++ b/usr/lib/common/h_extern.h
@@ -2763,11 +2763,11 @@ 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);
 
-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);
 
@@ -2776,7 +2776,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);
 
@@ -2785,7 +2785,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);
 
@@ -2796,12 +2796,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 ed54df4e2..341a3ba58 100644
--- a/usr/lib/common/key_mgr.c
+++ b/usr/lib/common/key_mgr.c
@@ -1373,10 +1373,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 1f116dfc8..d86af6d14 100644
--- a/usr/lib/common/mech_ec.c
+++ b/usr/lib/common/mech_ec.c
@@ -1453,7 +1453,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 */
diff --git a/usr/lib/common/pkey_utils.c b/usr/lib/common/pkey_utils.c
index bd381ca48..3eaca7742 100644
--- a/usr/lib/common/pkey_utils.c
+++ b/usr/lib/common/pkey_utils.c
@@ -1299,8 +1299,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;
@@ -1417,8 +1417,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 5858e0f52..60cb5c612 100644
--- a/usr/lib/ep11_stdll/ep11_login.c
+++ b/usr/lib/ep11_stdll/ep11_login.c
@@ -114,13 +114,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;
@@ -129,7 +130,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;
@@ -138,7 +139,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_mkchange.c b/usr/lib/ep11_stdll/ep11_mkchange.c
index 68ed17776..1819caf79 100644
--- a/usr/lib/ep11_stdll/ep11_mkchange.c
+++ b/usr/lib/ep11_stdll/ep11_mkchange.c
@@ -45,15 +45,16 @@ CK_BBOOL ep11tok_is_blob_new_wkid(STDLL_TokData_t *tokdata,
      * 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, &spki_len) == CKR_OK) {
+        ber_decode_SEQUENCE(blob, blob_len, &data, &data_len, &spki_len) ==
+                                                                    CKR_OK) {
         /* Its a SPKI, WKID follows as OCTET STRING right after SPKI data */
         if (blob_len < spki_len + 2 + XCP_WKID_BYTES) {
             TRACE_ERROR("MACed SPKI is too small\n");
             return CK_FALSE;
         }
 
-        rc = ber_decode_OCTET_STRING(blob + spki_len, &data, &data_len,
-                                     &wkid_len);
+        rc = ber_decode_OCTET_STRING(blob + spki_len, blob_len - spki_len,
+                                     &data, &data_len, &wkid_len);
         if (rc != CKR_OK || data_len != XCP_WKID_BYTES) {
             TRACE_ERROR("Invalid MACed SPKI encoding\n");
             return CK_FALSE;
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
index d5964a9cf..1517e48ad 100644
--- a/usr/lib/ep11_stdll/ep11_specific.c
+++ b/usr/lib/ep11_stdll/ep11_specific.c
@@ -362,15 +362,16 @@ static CK_RV check_expected_mkvp(STDLL_TokData_t *tokdata, CK_BYTE *blob,
      * denoted by 0x30 followed by the DER encoded length of the SPKI.
      */
     if (blobsize > 5 && blob[0] == 0x30 &&
-        ber_decode_SEQUENCE(blob, &data, &data_len, &spki_len) == CKR_OK) {
+        ber_decode_SEQUENCE(blob, blobsize, &data, &data_len, &spki_len) ==
+                                                                     CKR_OK) {
         /* It is a SPKI, WKID follows as OCTET STRING right after SPKI data */
         if (blobsize < spki_len + 2 + XCP_WKID_BYTES) {
             TRACE_ERROR("MACed SPKI is too small\n");
             return CKR_FUNCTION_FAILED;
         }
 
-        rc = ber_decode_OCTET_STRING(blob + spki_len, &wkid, &wkid_len,
-                                     &data_len);
+        rc = ber_decode_OCTET_STRING(blob + spki_len, blobsize - spki_len,
+                                     &wkid, &wkid_len, &data_len);
         if (rc != CKR_OK || wkid_len != XCP_WKID_BYTES) {
             TRACE_ERROR("Invalid MACed SPKI encoding\n");
             return CKR_FUNCTION_FAILED;
@@ -2930,7 +2931,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;
     }
@@ -3542,8 +3544,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;
@@ -4632,7 +4635,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);
@@ -6562,8 +6565,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 */
@@ -7266,15 +7271,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;
@@ -7675,15 +7680,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);
@@ -7956,7 +7961,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",
@@ -8052,8 +8057,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",
@@ -8064,7 +8070,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);
@@ -8072,7 +8079,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;
@@ -8099,7 +8108,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);
@@ -11271,7 +11282,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 fddbf685c..83b865d70 100644
--- a/usr/lib/ica_s390_stdll/ica_specific.c
+++ b/usr/lib/ica_s390_stdll/ica_specific.c
@@ -5421,8 +5421,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;
