Version in base suite: 3.23.0+dfsg-0.3 Base version: opencryptoki_3.23.0+dfsg-0.3 Target version: opencryptoki_3.23.0+dfsg-0.3+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/o/opencryptoki/opencryptoki_3.23.0+dfsg-0.3.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/o/opencryptoki/opencryptoki_3.23.0+dfsg-0.3+deb13u1.dsc changelog | 7 patches/CVE-2026-23893_CVE-2026-40253.patch | 2135 ++++++++++++++++++++++++++++ patches/series | 1 3 files changed, 2143 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpev52r2g4/opencryptoki_3.23.0+dfsg-0.3.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpev52r2g4/opencryptoki_3.23.0+dfsg-0.3+deb13u1.dsc: no acceptable signature found 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 12:53:37.000000000 +0000 +++ opencryptoki-3.23.0+dfsg/debian/changelog 2026-08-30 17:51:44.000000000 +0000 @@ -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 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 00:00:00.000000000 +0000 +++ opencryptoki-3.23.0+dfsg/debian/patches/CVE-2026-23893_CVE-2026-40253.patch 2026-08-30 17:50:57.000000000 +0000 @@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * 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 20:36:31.000000000 +0000 +++ opencryptoki-3.23.0+dfsg/debian/patches/series 2026-08-30 17:48:48.000000000 +0000 @@ -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