Bug#1146260: trixie-pu: package opencryptoki/3.23.0+dfsg-0.3+deb13u1

Moritz Muehlenhoff <[email protected]>
Newsgroups gmane.linux.debian.devel.release
Message-ID <178812283976.13286.1793626712382723908.reportbug__40568.4748593316$1788122989$gmane$org@soju.westfalen.local>
Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:opencryptoki
User: [email protected]
Usertags: pu

Fixes two minor security issues in opencryptoki, tests in debusine
look all fine. Debdiff below.

Cheers,
        Moritz

diff -Nru opencryptoki-3.23.0+dfsg/debian/changelog opencryptoki-3.23.0+dfsg/debian/changelog
--- opencryptoki-3.23.0+dfsg/debian/changelog	2024-07-19 14:53:37.000000000 +0200
+++ opencryptoki-3.23.0+dfsg/debian/changelog	2026-08-30 19:51:44.000000000 +0200
@@ -1,3 +1,10 @@
+opencryptoki (3.23.0+dfsg-0.3+deb13u1) trixie; urgency=medium
+
+  * CVE-2026-40253 (Closes: #1136019)
+  * CVE-2026-23893 (Closes: #1126268)
+
+ -- Moritz Mühlenhoff <[email protected]>  Sun, 30 Aug 2026 19:51:44 +0200
+
 opencryptoki (3.23.0+dfsg-0.3) unstable; urgency=medium
 
   * Non-maintainer upload.
diff -Nru opencryptoki-3.23.0+dfsg/debian/patches/CVE-2026-23893_CVE-2026-40253.patch opencryptoki-3.23.0+dfsg/debian/patches/CVE-2026-23893_CVE-2026-40253.patch
--- opencryptoki-3.23.0+dfsg/debian/patches/CVE-2026-23893_CVE-2026-40253.patch	1970-01-01 01:00:00.000000000 +0100
+++ opencryptoki-3.23.0+dfsg/debian/patches/CVE-2026-23893_CVE-2026-40253.patch	2026-08-30 19:50:57.000000000 +0200
@@ -0,0 +1,2135 @@
+Combined backport of 
+https://github.com/opencryptoki/opencryptoki/commit/2596e37d6b7a64fc24b92fc308a671ca7a215f89
+https://github.com/opencryptoki/opencryptoki/commit/f1139483b1fb12e4bb99bbf1ffbb7d977ec74e54
+https://github.com/opencryptoki/opencryptoki/commit/26387bafd9894c18ee0254acf9a82e8f2c06d40f
+by Frank Heimes
+
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/cca_stdll/cca_specific.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/cca_stdll/cca_specific.c
+@@ -751,7 +751,6 @@ static CK_RV cca_get_version(STDLL_TokDa
+     long return_code, reason_code;
+     long version_data_length;
+     long exit_data_len = 0;
+-    char date[20];
+ 
+     /* Get CCA host library version */
+     version_data_length = sizeof(version_data);
+@@ -767,10 +766,10 @@ static CK_RV cca_get_version(STDLL_TokDa
+     version_data[sizeof(version_data) - 1] = '\0';
+     TRACE_DEVEL("CCA Version string: %s\n", version_data);
+ 
+-    if (sscanf((char *)version_data, "%u.%u.%uz%s",
++    if (sscanf((char *)version_data, "%u.%u.%u",
+                &cca_private->cca_lib_version.ver,
+                &cca_private->cca_lib_version.rel,
+-               &cca_private->cca_lib_version.mod, date) != 4) {
++               &cca_private->cca_lib_version.mod) != 3) {
+         TRACE_ERROR("CCA library version is invalid: %s\n", version_data);
+         return CKR_FUNCTION_FAILED;
+     }
+@@ -3468,8 +3467,8 @@ static CK_RV cca_get_adapter_version(cca
+     memcpy(ccaversion, &rule_array[CCA_STATCCA_CCA_VERSION_OFFSET],
+            CCA_STATCCA_CCA_VERSION_LENGTH);
+ 
+-    if (sscanf(ccaversion, "%d.%d.%02d*", (int *)&adapter_version.ver,
+-               (int *)&adapter_version.rel, (int *)&adapter_version.mod) != 3) {
++    if (sscanf(ccaversion, "%u.%u.%u", &adapter_version.ver,
++               &adapter_version.rel, &adapter_version.mod) != 3) {
+         TRACE_ERROR("sscanf of string %s failed, cannot determine CCA card version\n",
+                     ccaversion);
+         return CKR_FUNCTION_FAILED;
+@@ -8706,8 +8705,8 @@ static CK_RV import_ec_pubkey(STDLL_TokD
+             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;
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/common/asn1.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/common/asn1.c
+@@ -155,13 +155,13 @@ CK_ULONG ber_encode_INTEGER(CK_BBOOL 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_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_in
+     //
+     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_in
+     }
+ 
+     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_in
+         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_in
+         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 l
+ 
+ //
+ //
+-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 *s
+     // 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 *s
+     //
+     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 *s
+     }
+ 
+     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 *s
+         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 *s
+         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
+  * 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 lengt
+ 
+ //
+ //
+-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_
+ //    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 @@ error:
+ 
+ //
+ //
+-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
+         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
+     // 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
+ 
+     // '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
+  *     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_
+     *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_
+     }
+ 
+     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 *
+     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 *
+         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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *d
+     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 *d
+     /*
+      * 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 *d
+         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 *
+     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 *
+     }
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *
+ 
+     // 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 *d
+     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 *d
+         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 l
+     }
+     // 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 l
+ 
+     /* 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 *d
+     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 *d
+      * 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 *d
+     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 *d
+     }
+ 
+     /* 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 *d
+     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 *d
+     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 *d
+     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 *d
+             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 le
+     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 *da
+     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 *da
+      * 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 *d
+     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 *d
+     }
+     // 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 *d
+     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 *d
+     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 *d
+     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 *d
+     }
+ 
+     // 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 *d
+     }
+ 
+     // 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 *da
+     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 *da
+         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_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(
+      *       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(
+ 
+     /* 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(
+     }
+ 
+     /* 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 *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
+     }
+ 
+     /* 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
+     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
+     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
+     }
+ 
+     /* 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
+     }
+ 
+     /* 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
+     }
+ 
+     /* 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
+     }
+ 
+     /* 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
+     }
+ 
+     /* 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
+ 
+     /* 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
+ 
+         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
+     }
+ 
+     /* 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_B
+     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_B
+      *     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_B
+     }
+ 
+     /* 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_
+     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_
+     }
+ 
+     /* 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_
+     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_
+     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_
+ 
+     /* 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_
+ 
+         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_
+     }
+ 
+     /* 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;
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/common/h_extern.h
++++ opencryptoki-3.23.0+dfsg/usr/lib/common/h_extern.h
+@@ -2763,11 +2763,11 @@ CK_ULONG ber_encode_INTEGER(CK_BBOOL len
+                             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 l
+                               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 lengt
+                           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
+                                 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);
+ 
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/common/key_mgr.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/common/key_mgr.c
+@@ -1373,10 +1373,11 @@ CK_RV key_mgr_get_private_key_type(CK_BY
+ {
+     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;
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/common/loadsave.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/common/loadsave.c
+@@ -42,6 +42,7 @@
+ #include "trace.h"
+ #include "ock_syslog.h"
+ #include "slotmgr.h" // for ock_snprintf
++#include "platform.h"
+ 
+ extern void set_perm(int);
+ 
+@@ -67,9 +68,17 @@ static FILE *open_token_object_path(char
+                                     STDLL_TokData_t *tokdata, char *path,
+                                     char *mode)
+ {
++    FILE *fp;
++
+     if (get_token_object_path(buf, buflen, tokdata, path) < 0)
+         return NULL;
+-    return fopen(buf, mode);
++
++    /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
++    fp = fopen_nofollow(buf, mode);
++    if (fp == NULL && errno == ELOOP)
++        TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
++
++    return fp;
+ }
+ 
+ static int get_token_data_store_path(char *buf, size_t buflen,
+@@ -86,9 +95,17 @@ static FILE *open_token_data_store_path(
+                                         STDLL_TokData_t *tokdata, char *path,
+                                         char *mode)
+ {
++    FILE *fp;
++
+     if (get_token_data_store_path(buf, buflen, tokdata, path) < 0)
+         return NULL;
+-    return fopen(buf, mode);
++
++    /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
++    fp = fopen_nofollow(buf, mode);
++    if (fp == NULL && errno == ELOOP)
++        TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
++
++    return fp;
+ }
+ 
+ static FILE *open_token_object_index(char *buf, size_t buflen,
+@@ -100,11 +117,19 @@ static FILE *open_token_object_index(cha
+ static FILE *open_token_nvdat(char *buf, size_t buflen,
+                               STDLL_TokData_t *tokdata, char *mode)
+ {
++    FILE *fp;
++
+     if (ock_snprintf(buf, buflen, "%s/" PK_LITE_NV, tokdata->data_store)) {
+         TRACE_ERROR("NVDAT.TOK file name buffer overflow\n");
+         return NULL;
+     }
+-    return fopen(buf, mode);
++
++    /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
++    fp = fopen_nofollow(buf, mode);
++    if (fp == NULL && errno == ELOOP)
++        TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
++
++    return fp;
+ }
+ 
+ char *get_pk_dir(STDLL_TokData_t *tokdata, char *fname, size_t len)
+@@ -185,9 +210,12 @@ CK_RV save_token_object(STDLL_TokData_t
+     // we didn't find it...either the index file doesn't exist or this
+     // is a new object...
+     //
+-    fp = fopen(fname, "a");
++    fp = fopen_nofollow(fname, "a");
+     if (!fp) {
+-        TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
++        if (errno == ELOOP)
++            TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
++        else
++            TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
+         return CKR_FUNCTION_FAILED;
+     }
+ 
+@@ -526,11 +554,14 @@ CK_RV load_token_data_old(STDLL_TokData_
+         if (errno == ENOENT) {
+             init_token_data(tokdata, slot_id);
+ 
+-            fp = fopen(fname, "r");
++            fp = fopen_nofollow(fname, "r");
+             if (!fp) {
+                 // were really hosed here since the created
+                 // did not occur
+-                TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
++                if (errno == ELOOP)
++                    TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
++                else
++                    TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
+                 rc = CKR_FUNCTION_FAILED;
+                 goto out_unlock;
+             }
+@@ -2179,11 +2210,14 @@ CK_RV load_token_data(STDLL_TokData_t *t
+         if (errno == ENOENT) {
+             init_token_data(tokdata, slot_id);
+ 
+-            fp = fopen(fname, "r");
++            fp = fopen_nofollow(fname, "r");
+             if (!fp) {
+                 // were really hosed here since the created
+                 // did not occur
+-                TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
++                if (errno == ELOOP)
++                    TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
++                else
++                    TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
+                 rc = CKR_FUNCTION_FAILED;
+                 goto out_unlock;
+             }
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/common/mech_ec.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/common/mech_ec.c
+@@ -1453,7 +1453,7 @@ int ec_point_from_public_data(const CK_B
+ 
+ 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 */
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/common/pkey_utils.c
++++ opencryptoki-3.23.0+dfsg/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;
+--- /dev/null
++++ opencryptoki-3.23.0+dfsg/usr/lib/common/platform.h
+@@ -0,0 +1,91 @@
++/*
++ * COPYRIGHT (c) International Business Machines Corp. 2024
++ *
++ * This program is provided under the terms of the Common Public License,
++ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
++ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
++ * found in the file LICENSE file or at
++ * https://opensource.org/licenses/cpl1.0.php
++ */
++#ifndef PLATFORM_H
++#define PLATFORM_H
++
++#include <dlfcn.h>
++#include <stdio.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <string.h>
++#include <errno.h>
++#include <sys/stat.h>
++
++/*
++ * Check for O_NOFOLLOW support at compile time.
++ * If not available, fall back to lstat() + fopen() (has TOCTOU race).
++ */
++#ifndef O_NOFOLLOW
++#define OCK_NO_O_NOFOLLOW 1
++#warning "O_NOFOLLOW not supported, symlink protection uses racy lstat() fallback!"
++#endif
++
++/*
++ * CWE-59 fix: Open file without following symlinks.
++ *
++ * On platforms with O_NOFOLLOW support:
++ *   Uses open(O_NOFOLLOW) + fdopen() for atomic symlink rejection.
++ *
++ * On platforms without O_NOFOLLOW (e.g., older AIX):
++ *   Falls back to lstat() + fopen(). This has a TOCTOU race condition,
++ *   but still catches pre-planted symlinks which is the common attack
++ *   scenario. Better than no protection at all.
++ *
++ * Returns NULL with errno=ELOOP if path is a symlink.
++ */
++static inline FILE *fopen_nofollow(const char *path, const char *mode)
++{
++#ifdef OCK_NO_O_NOFOLLOW
++    /*
++     * Fallback for platforms without O_NOFOLLOW: use lstat() check.
++     * This has a TOCTOU race but catches pre-planted symlinks.
++     */
++    struct stat sb;
++
++    if (lstat(path, &sb) == 0) {
++        if (S_ISLNK(sb.st_mode)) {
++            errno = ELOOP;
++            return NULL;
++        }
++    }
++    /* Note: if lstat fails (e.g., file doesn't exist for "w" mode),
++     * we proceed with fopen() which will handle the error appropriately */
++    return fopen(path, mode);
++#else
++    /* Preferred: atomic symlink rejection via O_NOFOLLOW */
++    int flags = O_NOFOLLOW;
++    int fd;
++    FILE *fp;
++
++    /* Determine flags based on mode */
++    if (mode[0] == 'r') {
++        flags |= (mode[1] == '+') ? O_RDWR : O_RDONLY;
++    } else if (mode[0] == 'w') {
++        flags |= O_CREAT | O_TRUNC | ((mode[1] == '+') ? O_RDWR : O_WRONLY);
++    } else if (mode[0] == 'a') {
++        flags |= O_CREAT | O_APPEND | ((mode[1] == '+') ? O_RDWR : O_WRONLY);
++    } else {
++        return NULL;
++    }
++
++    fd = open(path, flags, 0600);
++    if (fd < 0)
++        return NULL;
++
++    fp = fdopen(fd, mode);
++    if (fp == NULL) {
++        close(fd);
++        return NULL;
++    }
++    return fp;
++#endif
++}
++
++#endif /* PLATFORM_H */
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/ep11_stdll/ep11_login.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/ep11_stdll/ep11_login.c
+@@ -114,13 +114,14 @@ static CK_RV get_login_importer_key(targ
+      *             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(targ
+     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(targ
+     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;
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/ep11_stdll/ep11_mkchange.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/ep11_stdll/ep11_mkchange.c
+@@ -45,15 +45,16 @@ CK_BBOOL ep11tok_is_blob_new_wkid(STDLL_
+      * 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;
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/ep11_stdll/ep11_specific.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/ep11_stdll/ep11_specific.c
+@@ -362,15 +362,16 @@ static CK_RV check_expected_mkvp(STDLL_T
+      * 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_TokDa
+     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
+         }
+ 
+         /* 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_To
+ 
+     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
+                 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_T
+ #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_
+     }
+ 
+     /* 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(STD
+         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(STD
+          * 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(STD
+         /* 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(STD
+         }
+ 
+         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(STD
+ 
+         /* 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
+         }
+ 
+         /* 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);
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/hsm_mk_change/hsm_mk_change.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/hsm_mk_change/hsm_mk_change.c
+@@ -29,6 +29,7 @@
+ #endif
+ #include "hsm_mk_change.h"
+ #include "pkcs32.h"
++#include "platform.h"
+ 
+ struct hsm_mk_change_op_hdr {
+     char id[6];
+@@ -611,9 +612,13 @@ static FILE* hsm_mk_change_op_open(const
+ 
+     TRACE_DEVEL("file to open: %s mode: %s\n", hsm_mk_change_file, mode);
+ 
+-    fp = fopen(hsm_mk_change_file, mode);
++    /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
++    fp = fopen_nofollow(hsm_mk_change_file, mode);
+     if (fp == NULL) {
+-        TRACE_ERROR("%s fopen(%s, %s): %s\n", __func__,
++        if (errno == ELOOP)
++            TRACE_ERROR("Refusing to follow symlink: %s\n", hsm_mk_change_file);
++        else
++            TRACE_ERROR("%s fopen(%s, %s): %s\n", __func__,
+                         hsm_mk_change_file, mode, strerror(errno));
+     }
+ 
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/ica_s390_stdll/ica_specific.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/ica_s390_stdll/ica_specific.c
+@@ -5421,8 +5421,8 @@ static CK_RV ica_build_ec_pub_key(OBJECT
+     }
+ 
+     /* 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;
+--- opencryptoki-3.23.0+dfsg.orig/usr/lib/icsf_stdll/pbkdf.c
++++ opencryptoki-3.23.0+dfsg/usr/lib/icsf_stdll/pbkdf.c
+@@ -27,6 +27,7 @@
+ #include "h_extern.h"
+ #include "pbkdf.h"
+ #include "trace.h"
++#include "platform.h"
+ 
+ 
+ CK_RV get_randombytes(unsigned char *output, int bytes)
+@@ -527,9 +528,13 @@ CK_RV secure_racf(STDLL_TokData_t *tokda
+     /* get the total length */
+     totallen = outputlen + AES_INIT_VECTOR_SIZE;
+ 
+-    fp = fopen(RACFFILE, "w");
++    /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
++    fp = fopen_nofollow(RACFFILE, "w");
+     if (!fp) {
+-        TRACE_ERROR("fopen failed: %s\n", strerror(errno));
++        if (errno == ELOOP)
++            TRACE_ERROR("Refusing to follow symlink: %s\n", RACFFILE);
++        else
++            TRACE_ERROR("fopen failed: %s\n", strerror(errno));
+         return CKR_FUNCTION_FAILED;
+     }
+ 
+@@ -600,9 +605,13 @@ CK_RV secure_masterkey(STDLL_TokData_t *
+     /* get the total length */
+     totallen = outputlen + SALTSIZE;
+ 
+-    fp = fopen(fname, "w");
++    /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
++    fp = fopen_nofollow(fname, "w");
+     if (!fp) {
+-        TRACE_ERROR("fopen failed: %s\n", strerror(errno));
++        if (errno == ELOOP)
++            TRACE_ERROR("Refusing to follow symlink: %s\n", fname);
++        else
++            TRACE_ERROR("fopen failed: %s\n", strerror(errno));
+         return CKR_FUNCTION_FAILED;
+     }
+ 
+--- opencryptoki-3.23.0+dfsg.orig/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
++++ opencryptoki-3.23.0+dfsg/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
+@@ -41,6 +41,7 @@
+ #include "local_types.h"
+ #include "h_extern.h"
+ #include "slotmgr.h" // for ock_snprintf
++#include "platform.h"
+ 
+ #define OCK_TOOL
+ #include "pkcs_utils.h"
+@@ -70,9 +71,14 @@ static FILE *open_datastore_file(char *b
+         TRACE_ERROR("Path overflow for datastore file %s\n", file);
+         return NULL;
+     }
+-    res = fopen(buf, mode);
+-    if (!res)
+-        TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
++    /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
++    res = fopen_nofollow(buf, mode);
++    if (!res) {
++        if (errno == ELOOP)
++            TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
++        else
++            TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
++    }
+     return res;
+ }
+ 
+@@ -87,9 +93,14 @@ static FILE *open_tokenobject(char *buf,
+                     file, tokenobj);
+         return NULL;
+     }
+-    res = fopen(buf, mode);
+-    if (!res)
+-        TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
++    /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */
++    res = fopen_nofollow(buf, mode);
++    if (!res) {
++        if (errno == ELOOP)
++            TRACE_ERROR("Refusing to follow symlink: %s\n", buf);
++        else
++            TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
++    }
+     return res;
+ }
+ 
diff -Nru opencryptoki-3.23.0+dfsg/debian/patches/series opencryptoki-3.23.0+dfsg/debian/patches/series
--- opencryptoki-3.23.0+dfsg/debian/patches/series	2024-06-19 22:36:31.000000000 +0200
+++ opencryptoki-3.23.0+dfsg/debian/patches/series	2026-08-30 19:48:48.000000000 +0200
@@ -3,3 +3,4 @@
 04-pkcsslotd-cmdline-args.patch
 
 lp-1982842-move-pkcs11-group-assigment-from-makefile-to-postinst.patch
+CVE-2026-23893_CVE-2026-40253.patch
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.