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

Reply via email to