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, ¶m, ¶m_len,
++ rc = ber_decode_SPKI(data, data_len, &algid, &algid_len, ¶m,
¶m_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, ¶m, ¶m_len,
++ rc = ber_decode_SPKI(data, data_len, &algid, &algid_len, ¶m,
¶m_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, ¶m, ¶m_len,
++ rc = ber_decode_SPKI(data, data_len, &algid, &algid_len, ¶m,
¶m_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, ¶m, ¶m_len,
++ rc = ber_decode_SPKI(data, data_len, &algid, &algid_len, ¶m,
¶m_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, ¶m, ¶m_len,
+- &val, &val_len);
++ rc = ber_decode_SPKI(data, data_len, &algoid, &algoid_len,
++ ¶m, ¶m_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, ¶m, ¶m_len,
+- &val, &val_len);
++ rc = ber_decode_SPKI(data, data_len, &algoid, &algoid_len,
++ ¶m, ¶m_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