From ed378f463ef73364c89feb0fc923f4dc867332a3 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>
---

diff -Naur a/usr/lib/cca_stdll/cca_specific.c b/usr/lib/cca_stdll/cca_specific.c
--- a/usr/lib/cca_stdll/cca_specific.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/cca_stdll/cca_specific.c	2026-04-22 09:00:12.288732159 +0200
@@ -8706,8 +8706,8 @@
             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 -Naur a/usr/lib/common/asn1.c b/usr/lib/common/asn1.c
--- a/usr/lib/common/asn1.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/common/asn1.c	2026-04-22 13:58:55.008434064 +0200
@@ -155,13 +155,13 @@
 
 //
 //
-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 @@
     //
     if ((ber_int[1] & 0x80) == 0) {
         len = ber_int[1] & 0x7F;
-        *data = &ber_int[2];
+        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 @@
     }
 
     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];
-        *data = &ber_int[3];
+        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 @@
         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 @@
         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_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 @@
     // 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 @@
     //
     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 @@
     }
 
     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 @@
         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 @@
         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 @@
  * 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 @@
 
     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 @@
     }
 
     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 @@
         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 @@
         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_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 @@
     //
     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 @@
     }
 
     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 @@
         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 @@
         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,8 @@
 //    attributes
 // }
 //
-CK_RV ber_decode_CHOICE(CK_BYTE *choice,
+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)
@@ -848,7 +949,7 @@
     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 +965,10 @@
     //
     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,10 +976,18 @@
     }
 
     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];
-        *data = &choice[3];
+        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;
         return CKR_OK;
@@ -884,6 +997,10 @@
         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,7 +1013,11 @@
         len |= choice[3];
         len = len << 8;
         len |= choice[4];
-        *data = &choice[5];
+        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;
         return CKR_OK;
@@ -1006,10 +1127,9 @@
 
 //
 //
-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 +1141,7 @@
         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 +1149,8 @@
     // 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 +1159,18 @@
 
     // '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 +1188,14 @@
  *     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 +1203,9 @@
     *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 +1213,35 @@
     }
 
     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 +1508,11 @@
     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 +1524,8 @@
         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 +1535,8 @@
 
     // 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 +1545,8 @@
 
     // 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 +1555,8 @@
 
     // 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 +1565,8 @@
 
     // 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 +1575,8 @@
 
     // 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 +1585,8 @@
 
     // 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 +1595,8 @@
 
     // 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 +1605,8 @@
 
     // 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 +1615,8 @@
 
     // 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 +1636,8 @@
 
     // 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 +1646,8 @@
 
     // 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 +1662,8 @@
 
     // 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 +1678,8 @@
 
     // 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 +1694,8 @@
 
     // 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 +1710,8 @@
 
     // 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 +1726,8 @@
 
     // 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 +1742,8 @@
 
     // 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 +1758,8 @@
 
     // 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 +1947,7 @@
     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 +1957,8 @@
     /*
      * 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 +1970,21 @@
         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 +2218,12 @@
     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 +2237,8 @@
     }
     // 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 +2247,8 @@
 
     // 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 +2257,8 @@
 
     // 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 +2267,8 @@
 
     // 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 +2287,8 @@
 
     // 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 +2303,8 @@
 
     // 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 +2319,8 @@
 
     // 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 +2335,7 @@
 
     // 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 +2578,7 @@
     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 +2593,29 @@
         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,9 +2714,9 @@
     }
     // public key bit string
     if (pubkey && pubkey->pValue) {
-        rc = ber_decode_OCTET_STRING(pubkey->pValue, &ecpoint, &ecpoint_len,
-                                     &field_len);
-        if (rc != CKR_OK || pubkey->ulValueLen != 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,9 +2797,9 @@
 
     /* generate optional bit-string of public key */
     if (pubkey && pubkey->pValue) {
-        rc = ber_decode_OCTET_STRING(pubkey->pValue, &ecpoint, &ecpoint_len,
-                                     &field_len);
-        if (rc != CKR_OK || pubkey->ulValueLen != 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;
             goto error;
@@ -2723,7 +2890,7 @@
     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 +2904,7 @@
      * 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 +2916,8 @@
     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 +2930,7 @@
     }
 
     /* 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 +2938,8 @@
     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 +2947,8 @@
     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,9 +2960,9 @@
     if (buf_offset + offset < data_len) {
 
         /* Decode CHOICE */
-        rc = ber_decode_CHOICE(buf + offset, &choice, &choice_len, &field_len,
-                               &option);
-        if (rc != CKR_OK) {
+        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;
         }
@@ -2809,9 +2978,10 @@
             break;
         case 1:
             /* publicKey  [1] BIT STRING OPTIONAL */
-            rc = ber_decode_BIT_STRING(buf + offset, &pub_buf, &pub_len,
-                                       &field_len);
-            if (rc != CKR_OK) {
+            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 +3063,8 @@
     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 +3195,7 @@
     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 +3207,12 @@
      * 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 +3430,11 @@
     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 +3447,8 @@
     }
     // 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;
@@ -3281,7 +3456,8 @@
     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 +3465,8 @@
     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 +3482,8 @@
     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 +3497,8 @@
     }
 
     // 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 +3512,7 @@
     }
 
     // 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 +3734,7 @@
     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 +3749,21 @@
         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 +4004,9 @@
     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 +4023,14 @@
      *       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 +4040,8 @@
 
     /* 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 +4064,7 @@
     }
 
     /* 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 +4360,13 @@
     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 +4385,8 @@
     }
 
     /* 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 +4394,8 @@
     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 +4403,8 @@
     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 +4420,8 @@
     }
 
     /* 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 +4437,8 @@
     }
 
     /* 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 +4454,8 @@
     }
 
     /* 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 +4471,8 @@
     }
 
     /* 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 +4488,8 @@
     }
 
     /* 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 +4506,8 @@
 
     /* 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, TRUE,
+                               &tmp, &len, &field_len, &option);	
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n");
             goto cleanup;
@@ -4333,7 +4521,8 @@
 
         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 +4546,8 @@
     }
 
     /* 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 +4769,9 @@
     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 +4787,14 @@
      *     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 +4810,8 @@
     }
 
     /* 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 +5027,12 @@
     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 +5051,8 @@
     }
 
     /* 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 +5060,9 @@
     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 +5070,8 @@
     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 +5088,8 @@
 
     /* 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, TRUE,
+                               &tmp, &len, &field_len, &option);
         if (rc != CKR_OK) {
             TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n");
             goto cleanup;
@@ -4908,7 +5103,8 @@
 
         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 +5131,7 @@
     }
 
     /* 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 -Naur a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
--- a/usr/lib/common/h_extern.h	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/common/h_extern.h	2026-04-22 13:37:47.468427928 +0200
@@ -2763,12 +2763,12 @@
                             CK_ULONG *ber_int_len,
                             CK_BYTE *data, CK_ULONG data_len);
 
-CK_RV ber_decode_INTEGER(CK_BYTE *ber_int,
-                         CK_BYTE **data,
+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_BYTE **data,
+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_RV ber_encode_OCTET_STRING(CK_BBOOL length_only,
@@ -2776,7 +2776,7 @@
                               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_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,13 @@
                                 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 -Naur a/usr/lib/common/key_mgr.c b/usr/lib/common/key_mgr.c
--- a/usr/lib/common/key_mgr.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/common/key_mgr.c	2026-04-22 09:03:33.558704224 +0200
@@ -1373,10 +1373,12 @@
 {
     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 -Naur a/usr/lib/common/mech_ec.c b/usr/lib/common/mech_ec.c
--- a/usr/lib/common/mech_ec.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/common/mech_ec.c	2026-04-22 09:06:28.768679907 +0200
@@ -1453,7 +1453,7 @@
 
 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 -Naur a/usr/lib/common/pkey_utils.c b/usr/lib/common/pkey_utils.c
--- a/usr/lib/common/pkey_utils.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/common/pkey_utils.c	2026-04-22 09:09:16.408656715 +0200
@@ -1299,8 +1299,9 @@
     }
 
     /* 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 +1418,9 @@
     }
 
     /* 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 -Naur a/usr/lib/ep11_stdll/ep11_login.c b/usr/lib/ep11_stdll/ep11_login.c
--- a/usr/lib/ep11_stdll/ep11_login.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/ep11_stdll/ep11_login.c	2026-04-22 09:15:08.858607877 +0200
@@ -114,13 +114,14 @@
      *             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,8 @@
     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 +140,7 @@
     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 -Naur a/usr/lib/ep11_stdll/ep11_mkchange.c b/usr/lib/ep11_stdll/ep11_mkchange.c
--- a/usr/lib/ep11_stdll/ep11_mkchange.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/ep11_stdll/ep11_mkchange.c	2026-04-22 14:18:39.568371334 +0200
@@ -45,14 +45,14 @@
      * 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) {
-        /* Its a SPKI, WKID follows as OCTET STRING right after SPKI data */
+        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,
+        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");
diff -Naur a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
--- a/usr/lib/ep11_stdll/ep11_specific.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/ep11_stdll/ep11_specific.c	2026-04-22 14:59:42.338353999 +0200
@@ -362,16 +362,17 @@
      * 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) {
-        /* It is a SPKI, WKID follows as OCTET STRING right after SPKI data */
+        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);
-        if (rc != CKR_OK || wkid_len != XCP_WKID_BYTES) {
+	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 @@
     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,8 @@
         }
 
         /* 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 +4634,7 @@
 
     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 +6564,10 @@
                 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 +7270,15 @@
 #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 +7679,15 @@
     }
 
     /* 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 +7960,7 @@
         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 +8056,9 @@
          * 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 +8069,9 @@
         /* 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,10 @@
         }
 
         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 +8109,9 @@
 
         /* 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 +11283,7 @@
         }
 
         /* 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 -Naur a/usr/lib/ica_s390_stdll/ica_specific.c b/usr/lib/ica_s390_stdll/ica_specific.c
--- a/usr/lib/ica_s390_stdll/ica_specific.c	2024-02-06 11:02:00.000000000 +0100
+++ b/usr/lib/ica_s390_stdll/ica_specific.c	2026-04-22 09:41:27.288287491 +0200
@@ -5421,8 +5421,8 @@
     }
 
     /* 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;
