From 40f91e506fbcd75e5a61e9685d4639df87ce2a3d Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Fri, 26 Jun 2026 07:30:00 -0400 Subject: [PATCH] import Oracle_OSS opencryptoki-3.26.0-2.el9_8.2 --- .gitignore | 2 +- .opencryptoki.metadata | 2 +- ...opencryptoki-3.25.0-covscan-findings.patch | 43 - ...0-fix-private-secure-key-blob-import.patch | 116 - ...x-unwrapping-attribute-bound-EC-keys.patch | 50 - ...3.25.0-reject-using-md5-in-fips-mode.patch | 176 -- ...pencryptoki-3.26.0-CVE-3-2026-23893.patch} | 228 +- ...message-printing-about-different-CPs.patch | 36 + SOURCES/opencryptoki-openssl-3.5.x.patch | 48 - ...ryptoki-v3.26.0-CVE-2026-40253-part1.patch | 110 + ...ryptoki-v3.26.0-CVE-2026-40253-part2.patch | 2031 +++++++++++++++++ SPECS/opencryptoki.spec | 48 +- 12 files changed, 2282 insertions(+), 608 deletions(-) delete mode 100644 SOURCES/opencryptoki-3.25.0-covscan-findings.patch delete mode 100644 SOURCES/opencryptoki-3.25.0-fix-private-secure-key-blob-import.patch delete mode 100644 SOURCES/opencryptoki-3.25.0-fix-unwrapping-attribute-bound-EC-keys.patch delete mode 100644 SOURCES/opencryptoki-3.25.0-reject-using-md5-in-fips-mode.patch rename SOURCES/{opencryptoki-3.25.0-CVE-2026-23893.patch => opencryptoki-3.26.0-CVE-3-2026-23893.patch} (70%) create mode 100644 SOURCES/opencryptoki-3.26.0-Fix-syslog-message-printing-about-different-CPs.patch delete mode 100644 SOURCES/opencryptoki-openssl-3.5.x.patch create mode 100644 SOURCES/opencryptoki-v3.26.0-CVE-2026-40253-part1.patch create mode 100644 SOURCES/opencryptoki-v3.26.0-CVE-2026-40253-part2.patch diff --git a/.gitignore b/.gitignore index 6694472..351d50a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/opencryptoki-3.25.0.tar.gz +SOURCES/opencryptoki-3.26.0.tar.gz diff --git a/.opencryptoki.metadata b/.opencryptoki.metadata index f27e9b1..bf54d0e 100644 --- a/.opencryptoki.metadata +++ b/.opencryptoki.metadata @@ -1 +1 @@ -a52c4873734e8e68ae8d599e08d5a55c0b3459ad SOURCES/opencryptoki-3.25.0.tar.gz +c2e2f0fc220d106ece01dd4b4fd8091704cb8fac SOURCES/opencryptoki-3.26.0.tar.gz diff --git a/SOURCES/opencryptoki-3.25.0-covscan-findings.patch b/SOURCES/opencryptoki-3.25.0-covscan-findings.patch deleted file mode 100644 index 6a2e866..0000000 --- a/SOURCES/opencryptoki-3.25.0-covscan-findings.patch +++ /dev/null @@ -1,43 +0,0 @@ -commit 003d658322df316a352af591a3d059ca22fc40a3 -Author: Ingo Franzki -Date: Mon Jul 21 11:02:42 2025 +0200 - - Fix covscan findings - - Closes: https://github.com/opencryptoki/opencryptoki/issues/879 - - Reported-by: Than Ngo - Signed-off-by: Ingo Franzki - -diff --git a/usr/lib/common/mech_aes.c b/usr/lib/common/mech_aes.c -index 9195ff3c..383fb775 100644 ---- a/usr/lib/common/mech_aes.c -+++ b/usr/lib/common/mech_aes.c -@@ -4561,6 +4561,11 @@ static CK_RV aeskw_wrap_pad(STDLL_TokData_t *tokdata, SESSION *sess, - * contains exactly eight octets, then prepend the AIV and encrypt - * the resulting 128-bit block using AES in ECB mode. - */ -+ if (in_data_len > AES_KEY_WRAP_BLOCK_SIZE) { -+ TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE)); -+ return CKR_DATA_LEN_RANGE; -+ } -+ - memmove(buff + AES_KEY_WRAP_BLOCK_SIZE, in_data, in_data_len); - memcpy(buff, aiv, AES_KEY_WRAP_IV_SIZE); - memset(buff + AES_KEY_WRAP_IV_SIZE + in_data_len, 0, padding_len); -diff --git a/usr/sbin/p11sak/p11tool.c b/usr/sbin/p11sak/p11tool.c -index da684f79..5b72b93b 100644 ---- a/usr/sbin/p11sak/p11tool.c -+++ b/usr/sbin/p11sak/p11tool.c -@@ -567,6 +567,11 @@ static void p11tool_print_options_help(const struct p11tool_opt *opts, - else - len = snprintf(tmp, sizeof(tmp),"-%c", opt->short_opt); - -+ if (len >= (int)sizeof(tmp) || len < 0) { -+ warnx("Error formatting option string. Skipping.\n"); -+ continue; -+ } -+ - if (opt->arg.type != ARG_TYPE_PLAIN) { - if (opt->arg.required) - snprintf(&tmp[len], sizeof(tmp) - len, " %s", opt->arg.name); diff --git a/SOURCES/opencryptoki-3.25.0-fix-private-secure-key-blob-import.patch b/SOURCES/opencryptoki-3.25.0-fix-private-secure-key-blob-import.patch deleted file mode 100644 index ccc3238..0000000 --- a/SOURCES/opencryptoki-3.25.0-fix-private-secure-key-blob-import.patch +++ /dev/null @@ -1,116 +0,0 @@ -commit ab740fd0d596914919719ecbee90b0ad5fbb7112 -Author: Ingo Franzki -Date: Mon Nov 10 08:54:23 2025 +0100 - - EP11: Fix private secure key blob import - - Newer EP11 firmware versions do not allow to get attribute CKA_VALUE_LEN - for private keys, because CKA_VALUE_LEN is not defined for these - key types. This now causes error CKR_ATTRIBUTE_TYPE_INVALID. - Older firmware versions ignored that and did not fail if CKA_VALUE_LEN - was attempted to be retrieved. - - Use separate templates for getting the attributes of public, private or - secret keys, and get CKA_VALUE_LEN only for secret keys. - - Fixes: 169ab762c283ca341350580c2c080720e62967e8 - - Signed-off-by: Ingo Franzki - -diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c -index 4e6944e6..b6a9c014 100644 ---- a/usr/lib/ep11_stdll/ep11_specific.c -+++ b/usr/lib/ep11_stdll/ep11_specific.c -@@ -5386,13 +5386,24 @@ static CK_RV import_blob(STDLL_TokData_t *tokdata, SESSION *sess, OBJECT *obj, - CK_KEY_TYPE blob_type2 = CK_UNAVAILABLE_INFORMATION; - CK_ULONG value_len, value_len2, stdcomp, stdcomp2; - CK_BYTE buf[MAX_BLOBSIZE]; -- CK_ATTRIBUTE get_attr[] = { -- { CKA_KEY_TYPE, &blob_type, sizeof(blob_type) }, /* must be first */ -+ CK_ATTRIBUTE get_attr_pub[] = { -+ { CKA_KEY_TYPE, &blob_type, sizeof(blob_type) }, -+ }; -+ CK_ULONG get_attr_pub_num = sizeof(get_attr_pub) / sizeof(CK_ATTRIBUTE); -+ CK_ATTRIBUTE get_attr_priv[] = { -+ { CKA_KEY_TYPE, &blob_type, sizeof(blob_type) }, -+ { CKA_IBM_STD_COMPLIANCE1, &stdcomp, sizeof(stdcomp) }, -+ { CKA_PUBLIC_KEY_INFO, &buf, sizeof(buf) }, -+ }; -+ CK_ULONG get_attr_priv_num = sizeof(get_attr_priv) / sizeof(CK_ATTRIBUTE); -+ CK_ATTRIBUTE get_attr_sec[] = { -+ { CKA_KEY_TYPE, &blob_type, sizeof(blob_type) }, - { CKA_VALUE_LEN, &value_len, sizeof(value_len) }, - { CKA_IBM_STD_COMPLIANCE1, &stdcomp, sizeof(stdcomp) }, -- { CKA_PUBLIC_KEY_INFO, &buf, sizeof(buf) } /* SPKI must be last */ - }; -- CK_ULONG get_attr_num = sizeof(get_attr) / sizeof(CK_ATTRIBUTE); -+ CK_ULONG get_attr_sec_num = sizeof(get_attr_sec) / sizeof(CK_ATTRIBUTE); -+ CK_ATTRIBUTE *get_attr = NULL; -+ CK_ULONG get_attr_num = 0; - CK_ATTRIBUTE get_attr2[] = { - { CKA_KEY_TYPE, &blob_type2, sizeof(blob_type2) }, - { CKA_VALUE_LEN, &value_len2, sizeof(value_len2) }, -@@ -5629,10 +5640,22 @@ static CK_RV import_blob(STDLL_TokData_t *tokdata, SESSION *sess, OBJECT *obj, - } - } - -- if (class == CKO_PUBLIC_KEY) -- get_attr_num = 1; /* get only key type for public key */ -- if (class == CKO_SECRET_KEY) -- get_attr_num--; /* don't get SPKI for secret key */ -+ switch (class) { -+ case CKO_PUBLIC_KEY: -+ get_attr = get_attr_pub; -+ get_attr_num = get_attr_pub_num; -+ break; -+ case CKO_PRIVATE_KEY: -+ get_attr = get_attr_priv; -+ get_attr_num = get_attr_priv_num; -+ break; -+ case CKO_SECRET_KEY: -+ get_attr = get_attr_sec; -+ get_attr_num = get_attr_sec_num; -+ break; -+ default: -+ return CKR_KEY_TYPE_INCONSISTENT; -+ } - - /* Get Key type and SPKI for private keys */ - blob1_len = keytype == CKK_AES_XTS ? blob_len / 2 : blob_len; -@@ -5713,8 +5736,8 @@ static CK_RV import_blob(STDLL_TokData_t *tokdata, SESSION *sess, OBJECT *obj, - - case CKO_PRIVATE_KEY: - rc = import_blob_private_public(tokdata, sess, obj, keytype, -- get_attr[get_attr_num - 1].pValue, -- get_attr[get_attr_num - 1].ulValueLen, -+ get_attr_priv[get_attr_priv_num - 1].pValue, -+ get_attr_priv[get_attr_priv_num - 1].ulValueLen, - FALSE); - if (rc != CKR_OK) { - TRACE_ERROR("%s import_blob_public failed rc=0x%lx\n", -@@ -5733,15 +5756,17 @@ static CK_RV import_blob(STDLL_TokData_t *tokdata, SESSION *sess, OBJECT *obj, - break; - } - -- rc = template_build_update_attribute(obj->template, CKA_IBM_STD_COMPLIANCE1, -- (CK_BYTE *)&stdcomp, sizeof(stdcomp)); -- if (rc != CKR_OK) { -- TRACE_ERROR("%s template_build_update_attribute failed rc=0x%lx\n", -- __func__, rc); -- return rc; -- } -- - if (class != CKO_PUBLIC_KEY) { -+ rc = template_build_update_attribute(obj->template, -+ CKA_IBM_STD_COMPLIANCE1, -+ (CK_BYTE *)&stdcomp, -+ sizeof(stdcomp)); -+ if (rc != CKR_OK) { -+ TRACE_ERROR("%s template_build_update_attribute failed rc=0x%lx\n", -+ __func__, rc); -+ return rc; -+ } -+ - /* Set CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE */ - rc = key_mgr_apply_always_sensitive_never_extractable_attrs(tokdata, - obj); diff --git a/SOURCES/opencryptoki-3.25.0-fix-unwrapping-attribute-bound-EC-keys.patch b/SOURCES/opencryptoki-3.25.0-fix-unwrapping-attribute-bound-EC-keys.patch deleted file mode 100644 index 7d32afb..0000000 --- a/SOURCES/opencryptoki-3.25.0-fix-unwrapping-attribute-bound-EC-keys.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit d3dc88c720fdbf56a64f3990148387649f366aeb -Author: Ingo Franzki -Date: Thu Nov 6 15:27:36 2025 +0100 - - EP11: Fix unwrapping of attribute bound EC keys - - Newer EP11 firmware versions do not allow to get attribute CKA_VALUE_LEN - for non-symmetric keys, because CKA_VALUE_LEN is not defined for these - key types. This now causes error CKR_ATTRIBUTE_TYPE_INVALID. - Older firmware versions ignored that and did not fail if CKA_VALUE_LEN - was attempted to be retrieved. - - Fix this by only attempting to obtain CKA_VALUE_LEN for keys that support - this attribute. - - Signed-off-by: Ingo Franzki - -diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c -index 1baa5443..4e6944e6 100644 ---- a/usr/lib/ep11_stdll/ep11_specific.c -+++ b/usr/lib/ep11_stdll/ep11_specific.c -@@ -2222,17 +2222,26 @@ static CK_RV ab_unwrap_update_template(STDLL_TokData_t * tokdata, - {CKA_KEY_TYPE, &template_keytype, sizeof(template_keytype)}, - {CKA_VALUE_LEN, &valuelen, sizeof(valuelen)}, - }; -+ CK_ULONG num_attrs = sizeof(attrs) / sizeof(CK_ATTRIBUTE); - CK_ULONG i; - CK_ATTRIBUTE *attr; - CK_BBOOL cktrue = TRUE; - CK_BYTE *useblob; - size_t useblob_len; - -+ switch (keytype) { -+ case CKK_GENERIC_SECRET: -+ case CKK_AES: -+ break; -+ default: -+ num_attrs -= 1; /* No CKA_VALUE_LEN attribute */ -+ break; -+ } -+ - RETRY_SESSION_SINGLE_APQN_START(rc, tokdata) - RETRY_REENC_BLOB_START(tokdata, target_info, obj, blob, blob_len, - useblob, useblob_len, rc) -- rc = dll_m_GetAttributeValue(useblob, useblob_len, attrs, -- sizeof(attrs) / sizeof(CK_ATTRIBUTE), -+ rc = dll_m_GetAttributeValue(useblob, useblob_len, attrs, num_attrs, - target_info->target); - RETRY_REENC_BLOB_END(tokdata, target_info, useblob, useblob_len, rc) - RETRY_SESSION_SINGLE_APQN_END(rc, tokdata, session) diff --git a/SOURCES/opencryptoki-3.25.0-reject-using-md5-in-fips-mode.patch b/SOURCES/opencryptoki-3.25.0-reject-using-md5-in-fips-mode.patch deleted file mode 100644 index 29b29ca..0000000 --- a/SOURCES/opencryptoki-3.25.0-reject-using-md5-in-fips-mode.patch +++ /dev/null @@ -1,176 +0,0 @@ -commit 144456ede9897662eed35ac8415d0ecb1c5907e3 -Author: Ingo Franzki -Date: Wed Aug 13 13:50:24 2025 +0200 - - PKCSSLOTD: Remove the use of MD5 - - The pkcsslotd uses MD5 to calculate kind of a checksum of the token directory - path, for easy checking if the same token directory has already been used by - other tokens. - - The use of MD5 for this is just historical, and has no security relevance at - all. Still, OpenSSL running in FIPS mode might reject the use of MD5, so - pkcsslotd will fail to start. - - Change the code to use SHA256 instead. - - Signed-off-by: Ingo Franzki - -diff --git a/usr/sbin/pkcsslotd/pkcsslotd.h b/usr/sbin/pkcsslotd/pkcsslotd.h -index ec6a489a..fa0db30f 100644 ---- a/usr/sbin/pkcsslotd/pkcsslotd.h -+++ b/usr/sbin/pkcsslotd/pkcsslotd.h -@@ -42,11 +42,7 @@ - - #endif /* DEV */ - --#define HASH_SHA1 1 --#define HASH_MD5 2 --#define compute_md5(a,b,c) compute_hash(HASH_MD5,b,a,c) -- --int compute_hash(int hash_type, int buf_size, char *buf, char *digest); -+int compute_sha256(char *buf, int buf_size, char *digest); - - /******************** - * Global Variables * -diff --git a/usr/sbin/pkcsslotd/slotmgr.c b/usr/sbin/pkcsslotd/slotmgr.c -index 0c1a5586..d0d85a85 100644 ---- a/usr/sbin/pkcsslotd/slotmgr.c -+++ b/usr/sbin/pkcsslotd/slotmgr.c -@@ -27,7 +27,7 @@ - #include "configuration.h" - - #define OBJ_DIR "TOK_OBJ" --#define MD5_HASH_SIZE 16 -+#define SHA256_HASH_SIZE 32 - - #define DEF_MANUFID "IBM" - -@@ -44,8 +44,8 @@ - #define DEF_SLOTDESC "Linux" - #endif - --typedef char md5_hash_entry[MD5_HASH_SIZE]; --md5_hash_entry tokname_hash_table[NUMBER_SLOTS_MANAGED]; -+typedef char sha256_hash_entry[SHA256_HASH_SIZE]; -+sha256_hash_entry tokname_hash_table[NUMBER_SLOTS_MANAGED]; - - Slot_Mgr_Shr_t *shmp; // pointer to the shared memory region. - int shmid; -@@ -86,27 +86,19 @@ void DumpSharedMemory(void) - } - } - --int compute_hash(int hash_type, int buf_size, char *buf, char *digest) -+int compute_sha256(char *buf, int buf_size, char *digest) - { - EVP_MD_CTX *md_ctx = NULL; - unsigned int result_size; - int rc; - - md_ctx = EVP_MD_CTX_create(); -- -- switch (hash_type) { -- case HASH_SHA1: -- rc = EVP_DigestInit(md_ctx, EVP_sha1()); -- break; -- case HASH_MD5: -- rc = EVP_DigestInit(md_ctx, EVP_md5()); -- break; -- default: -- EVP_MD_CTX_destroy(md_ctx); -+ if (md_ctx == NULL) { -+ fprintf(stderr, "EVP_MD_CTX_create() failed\n"); - return -1; -- break; - } - -+ rc = EVP_DigestInit(md_ctx, EVP_sha256()); - if (rc != 1) { - fprintf(stderr, "EVP_DigestInit() failed: rc = %d\n", rc); - return -1; -@@ -374,12 +366,12 @@ void run_sanity_checks(void) - } - } - --int is_duplicate(md5_hash_entry hash, md5_hash_entry *hash_table) -+int is_duplicate(sha256_hash_entry hash, sha256_hash_entry *hash_table) - { - int i; - - for (i = 0; i < NUMBER_SLOTS_MANAGED; i++) { -- if (memcmp(hash_table[i], hash, sizeof(md5_hash_entry)) == 0) -+ if (memcmp(hash_table[i], hash, sizeof(sha256_hash_entry)) == 0) - return 1; - } - -@@ -483,7 +475,7 @@ int chk_create_tokdir(Slot_Info_t_64 *psinfo) - mode_t proc_umask; - char *tokdir = psinfo->tokname; - char *tokgroup = psinfo->usergroup; -- char token_md5_hash[MD5_HASH_SIZE]; -+ char token_sha256_hash[SHA256_HASH_SIZE]; - - if (psinfo->present == FALSE) - return 0; -@@ -517,26 +509,26 @@ int chk_create_tokdir(Slot_Info_t_64 *psinfo) - */ - if (!tokdir || strlen(tokdir) == 0) { - /* -- * Build the md5 hash from the dll name prefixed with 'dll:' to -+ * Build the SHA256 hash from the dll name prefixed with 'dll:' to - * check for duplicate tokens with no 'tokname'. - */ - snprintf(tokendir, sizeof(tokendir), "dll:%s", psinfo->dll_location); -- rc = compute_md5(tokendir, strlen(tokendir), token_md5_hash); -+ rc = compute_sha256(tokendir, strlen(tokendir), token_sha256_hash); - if (rc) { -- fprintf(stderr, "Error calculating MD5 of token name!\n"); -+ fprintf(stderr, "Error calculating SHA256 of token name!\n"); - return -1; - } - - /* check for duplicate token names */ -- if (is_duplicate(token_md5_hash, tokname_hash_table)) { -+ if (is_duplicate(token_sha256_hash, tokname_hash_table)) { - fprintf(stderr, "Duplicate token in slot %llu!\n", - psinfo->slot_number); - return -1; - } - - /* add entry into hash table */ -- memcpy(tokname_hash_table[psinfo->slot_number], token_md5_hash, -- MD5_HASH_SIZE); -+ memcpy(tokname_hash_table[psinfo->slot_number], token_sha256_hash, -+ SHA256_HASH_SIZE); - - return 0; - } -@@ -549,21 +541,21 @@ int chk_create_tokdir(Slot_Info_t_64 *psinfo) - return -1; - } - -- /* calculate md5 hash from token name */ -- rc = compute_md5(tokdir, strlen(tokdir), token_md5_hash); -+ /* calculate SHA256 hash from token name */ -+ rc = compute_sha256(tokdir, strlen(tokdir), token_sha256_hash); - if (rc) { -- fprintf(stderr, "Error calculating MD5 of token name!\n"); -+ fprintf(stderr, "Error calculating SHA256 of token name!\n"); - return -1; - } - /* check for duplicate token names */ -- if (is_duplicate(token_md5_hash, tokname_hash_table)) { -+ if (is_duplicate(token_sha256_hash, tokname_hash_table)) { - fprintf(stderr, "Duplicate token name '%s'!\n", tokdir); - return -1; - } - - /* add entry into hash table */ -- memcpy(tokname_hash_table[psinfo->slot_number], token_md5_hash, -- MD5_HASH_SIZE); -+ memcpy(tokname_hash_table[psinfo->slot_number], token_sha256_hash, -+ SHA256_HASH_SIZE); - - /* Create token specific directory */ - /* sprintf checked above */ diff --git a/SOURCES/opencryptoki-3.25.0-CVE-2026-23893.patch b/SOURCES/opencryptoki-3.26.0-CVE-3-2026-23893.patch similarity index 70% rename from SOURCES/opencryptoki-3.25.0-CVE-2026-23893.patch rename to SOURCES/opencryptoki-3.26.0-CVE-3-2026-23893.patch index 56f403d..85bb2fd 100644 --- a/SOURCES/opencryptoki-3.25.0-CVE-2026-23893.patch +++ b/SOURCES/opencryptoki-3.26.0-CVE-3-2026-23893.patch @@ -1,4 +1,4 @@ -commit 66e5bbdc0019fdf547409152df6b7668639f65e7 +commit a1aaf9f9080202f48570d3a207d0595db159f99c Author: Pavel Kohout Date: Tue Jan 13 00:00:00 2026 +0000 @@ -35,16 +35,16 @@ Date: Tue Jan 13 00:00:00 2026 +0000 Signed-off-by: Ingo Franzki diff --git a/usr/lib/common/loadsave.c b/usr/lib/common/loadsave.c -index 3b919709..e416c2b2 100644 +index 18b8aa04..f9c0cc7f 100644 --- a/usr/lib/common/loadsave.c +++ b/usr/lib/common/loadsave.c -@@ -66,9 +66,17 @@ static FILE *open_token_object_path(char *buf, size_t buflen, - STDLL_TokData_t *tokdata, char *path, - char *mode) +@@ -68,9 +68,17 @@ static FILE *open_token_object_path(char *buf, size_t buflen, + STDLL_TokData_t *tokdata, const char *path, + const char *mode) { + FILE *fp; + - if (get_token_object_path(buf, buflen, tokdata, path) < 0) + if (get_token_object_path(buf, buflen, tokdata, path, NULL) < 0) return NULL; - return fopen(buf, mode); + @@ -56,14 +56,35 @@ index 3b919709..e416c2b2 100644 + return fp; } + static FILE *open_token_object_path_new(char *newbuf, size_t newbuflen, +@@ -78,11 +86,19 @@ static FILE *open_token_object_path_new(char *newbuf, size_t newbuflen, + STDLL_TokData_t *tokdata, + const char *path, const char *mode) + { ++ FILE *fp; ++ + if (get_token_object_path(newbuf, newbuflen, tokdata, path, ".TMP") < 0) + return NULL; + if (get_token_object_path(basebuf, basebuflen, tokdata, path, NULL) < 0) + return NULL; +- return fopen(newbuf, mode); ++ ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(newbuf, mode); ++ if (fp == NULL && errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", newbuf); ++ ++ return fp; + } + static int get_token_data_store_path(char *buf, size_t buflen, -@@ -85,9 +93,17 @@ static FILE *open_token_data_store_path(char *buf, size_t buflen, - STDLL_TokData_t *tokdata, char *path, - char *mode) +@@ -101,9 +117,17 @@ static FILE *open_token_data_store_path(char *buf, size_t buflen, + STDLL_TokData_t *tokdata, + const char *path, const char *mode) { + FILE *fp; + - if (get_token_data_store_path(buf, buflen, tokdata, path) < 0) + if (get_token_data_store_path(buf, buflen, tokdata, path, NULL) < 0) return NULL; - return fopen(buf, mode); + @@ -75,10 +96,31 @@ index 3b919709..e416c2b2 100644 + return fp; } + static FILE *open_token_data_store_path_new(char *newbuf, size_t newbuflen, +@@ -111,11 +135,19 @@ static FILE *open_token_data_store_path_new(char *newbuf, size_t newbuflen, + STDLL_TokData_t *tokdata, + const char *path, const char *mode) + { ++ FILE *fp; ++ + if (get_token_data_store_path(newbuf, newbuflen, tokdata, path, ".TMP") < 0) + return NULL; + if (get_token_data_store_path(basebuf, basebuflen, tokdata, path, NULL) < 0) + return NULL; +- return fopen(newbuf, mode); ++ ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(newbuf, mode); ++ if (fp == NULL && errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", newbuf); ++ ++ return fp; + } + static FILE *open_token_object_index(char *buf, size_t buflen, -@@ -99,11 +115,19 @@ static FILE *open_token_object_index(char *buf, size_t buflen, +@@ -127,17 +159,27 @@ static FILE *open_token_object_index(char *buf, size_t buflen, static FILE *open_token_nvdat(char *buf, size_t buflen, - STDLL_TokData_t *tokdata, char *mode) + STDLL_TokData_t *tokdata, const char *mode) { + FILE *fp; + @@ -96,8 +138,31 @@ index 3b919709..e416c2b2 100644 + return fp; } - char *get_pk_dir(STDLL_TokData_t *tokdata, char *fname, size_t len) -@@ -223,9 +247,12 @@ CK_RV save_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) + static FILE *open_token_nvdat_new(char *newbuf, size_t newbuflen, + char *basebuf, size_t basebuflen, + STDLL_TokData_t *tokdata, const char *mode) + { ++ FILE *fp; ++ + if (ock_snprintf(newbuf, newbuflen, "%s/" PK_LITE_NV ".TMP", + tokdata->data_store)) { + TRACE_ERROR("NVDAT.TOK file name buffer overflow\n"); +@@ -148,7 +190,13 @@ static FILE *open_token_nvdat_new(char *newbuf, size_t newbuflen, + TRACE_ERROR("NVDAT.TOK file name buffer overflow\n"); + return NULL; + } +- return fopen(newbuf, mode); ++ ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(newbuf, mode); ++ if (fp == NULL && errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", newbuf); ++ ++ return fp; + } + + static CK_RV close_token_file_new(FILE * fp, CK_RV rc, +@@ -289,9 +337,12 @@ CK_RV save_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) // we didn't find it...either the index file doesn't exist or this // is a new object... // @@ -112,22 +177,7 @@ index 3b919709..e416c2b2 100644 return CKR_FUNCTION_FAILED; } -@@ -286,8 +313,12 @@ CK_RV delete_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) - - fclose(fp1); - fclose(fp2); -- fp2 = fopen(objidx, "w"); -- fp1 = fopen(idxtmp, "r"); -+ fp2 = fopen_nofollow(objidx, "w"); -+ if (fp1 == NULL && errno == ELOOP) -+ TRACE_ERROR("Refusing to follow symlink: %s\n", objidx); -+ fp1 = fopen_nofollow(idxtmp, "r"); -+ if (fp2 == NULL && errno == ELOOP) -+ TRACE_ERROR("Refusing to follow symlink: %s\n", idxtmp); - if (!fp1 || !fp2) { - if (fp1) - fclose(fp1); -@@ -616,11 +647,14 @@ CK_RV load_token_data_old(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) +@@ -663,11 +714,14 @@ CK_RV load_token_data_old(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) if (errno == ENOENT) { init_token_data(tokdata, slot_id); @@ -144,52 +194,7 @@ index 3b919709..e416c2b2 100644 rc = CKR_FUNCTION_FAILED; goto out_unlock; } -@@ -824,9 +858,12 @@ static CK_RV save_private_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj - rc = CKR_FUNCTION_FAILED; - goto error; - } -- fp = fopen(fname, "w"); -+ fp = fopen_nofollow(fname, "w"); - 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)); - rc = CKR_FUNCTION_FAILED; - goto error; - } -@@ -1590,9 +1627,12 @@ CK_RV reload_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj) - rc = CKR_FUNCTION_FAILED; - goto done; - } -- fp = fopen(fname, "r"); -+ fp = fopen_nofollow(fname, "r"); - 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)); - rc = CKR_FUNCTION_FAILED; - goto done; - } -@@ -1681,9 +1721,12 @@ CK_RV save_public_token_object_old(STDLL_TokData_t *tokdata, OBJECT * obj) - rc = CKR_FUNCTION_FAILED; - goto error; - } -- fp = fopen(fname, "w"); -+ fp = fopen_nofollow(fname, "w"); - 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)); - rc = CKR_FUNCTION_FAILED; - goto error; - } -@@ -2303,11 +2346,14 @@ CK_RV load_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) +@@ -2345,11 +2399,14 @@ CK_RV load_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id) if (errno == ENOENT) { init_token_data(tokdata, slot_id); @@ -206,75 +211,6 @@ index 3b919709..e416c2b2 100644 rc = CKR_FUNCTION_FAILED; goto out_unlock; } -@@ -2481,7 +2527,7 @@ CK_RV save_private_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) - goto done; - } - -- fp = fopen(fname, "r"); -+ fp = fopen_nofollow(fname, "r"); - if (fp == NULL) { - /* create new token object */ - new = 1; -@@ -2579,9 +2625,12 @@ do_work: - if (rc != CKR_OK) - goto done; - -- fp = fopen(fname, "w"); -+ fp = fopen_nofollow(fname, "w"); - 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)); - rc = CKR_FUNCTION_FAILED; - goto done; - } -@@ -2778,9 +2827,12 @@ CK_RV reload_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - strncat(fname, (char *) obj->name, 8); - -- fp = fopen(fname, "r"); -+ fp = fopen_nofollow(fname, "r"); - 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)); - rc = CKR_FUNCTION_FAILED; - goto done; - } -@@ -2893,9 +2945,12 @@ CK_RV save_public_token_object(STDLL_TokData_t *tokdata, OBJECT *obj) - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - strncat(fname, (char *) obj->name, 8); - -- fp = fopen(fname, "w"); -+ fp = fopen_nofollow(fname, "w"); - 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)); - rc = CKR_FUNCTION_FAILED; - goto done; - } -@@ -2956,9 +3011,12 @@ CK_RV load_public_token_objects(STDLL_TokData_t *tokdata) - sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR); - strcat(fname, tmp); - -- fp2 = fopen(fname, "r"); -- if (!fp2) -+ fp2 = fopen_nofollow(fname, "r"); -+ if (!fp2) { -+ if (errno == ELOOP) -+ TRACE_ERROR("Refusing to follow symlink: %s\n", fname); - continue; -+ } - - if (fread(header, PUB_HEADER_LEN, 1, fp2) != 1) { - fclose(fp2); diff --git a/usr/lib/common/platform.h b/usr/lib/common/platform.h index 799821b5..51cc1c73 100644 --- a/usr/lib/common/platform.h @@ -380,7 +316,7 @@ index 799821b5..51cc1c73 100644 + +#endif /* PLATFORM_H */ diff --git a/usr/lib/hsm_mk_change/hsm_mk_change.c b/usr/lib/hsm_mk_change/hsm_mk_change.c -index 161ed880..492bbd83 100644 +index f40dfb43..8c66546f 100644 --- a/usr/lib/hsm_mk_change/hsm_mk_change.c +++ b/usr/lib/hsm_mk_change/hsm_mk_change.c @@ -623,9 +623,13 @@ static FILE* hsm_mk_change_op_open(const char *id, CK_SLOT_ID slot_id, diff --git a/SOURCES/opencryptoki-3.26.0-Fix-syslog-message-printing-about-different-CPs.patch b/SOURCES/opencryptoki-3.26.0-Fix-syslog-message-printing-about-different-CPs.patch new file mode 100644 index 0000000..05029cd --- /dev/null +++ b/SOURCES/opencryptoki-3.26.0-Fix-syslog-message-printing-about-different-CPs.patch @@ -0,0 +1,36 @@ +commit 3a13de065de2e64a53eb6fe14e285318002bd505 +Author: Ingo Franzki +Date: Wed Apr 15 08:50:05 2026 +0200 + + EP11: Fix syslog message printing about different CPs + + Syslog message "Adapter xx.yyyy has different control points than adapter + xx.yyyy, using minimum." is erroneously issued even if the control points + are the same. + + The control points of subsequent APQNs are compared against a modified + control point bit string, where the unknown CPS have already been turned + ON. Comparing this with the queried control point bit string will always + show differences, even if the used/known control points are the same. + + Fix this by remembering the original, unmodified control point bit string + instead of the modified one, and compare the control point bit strings of + subsequent APQNs with that. + + Fixes: 97248f73495695436f11fafd74c2ec41a5a6f796 + + Signed-off-by: Ingo Franzki + +diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c +index facf6f58..f48946e1 100644 +--- a/usr/lib/ep11_stdll/ep11_specific.c ++++ b/usr/lib/ep11_stdll/ep11_specific.c +@@ -17900,7 +17900,7 @@ static CK_RV control_point_handler(uint_32 adapter, uint_32 domain, + data->combined_cp[CP_BYTE_NO(i)] &= + (cp[CP_BYTE_NO(i)] | ~CP_BIT_MASK(i)); + } +- memcpy(data->first_cp, data->combined_cp, sizeof(data->first_cp)); ++ memcpy(data->first_cp, cp, sizeof(data->first_cp)); + data->max_cp_index = max_cp_index; + data->first = 0; + } else { diff --git a/SOURCES/opencryptoki-openssl-3.5.x.patch b/SOURCES/opencryptoki-openssl-3.5.x.patch deleted file mode 100644 index e6dcb3a..0000000 --- a/SOURCES/opencryptoki-openssl-3.5.x.patch +++ /dev/null @@ -1,48 +0,0 @@ -commit 8209874fc0ea78079aa21c386df0f385ee0e5dca -Author: Ingo Franzki -Date: Wed Jul 9 09:09:32 2025 +0200 - - COMMON: Fix detection of EC curve not supported by OpenSSL - - OpenSSL 3.5 recently changed the behavior in regards of error reporting - with EVP_PKEY_keygen(). When the EC curve is not supported it used to - return error EC_R_INVALID_CURVE as top most entry in the error stack. - - Since commit https://github.com/openssl/openssl/commit/72351b0d18078170af270418b2d5e9fc579cb1af - this is no longer the case, instead a generic EVP_R_PROVIDER_KEYMGMT_FAILURE - error is now the top most entry, and EC_R_INVALID_CURVE is the second one. - - Make the detection independent of the error reporting and check for the - curve already in curve_nid_from_params(). - - Closes: https://github.com/opencryptoki/opencryptoki/issues/877 - - Signed-off-by: Ingo Franzki - -diff --git a/usr/lib/common/mech_openssl.c b/usr/lib/common/mech_openssl.c -index f29b4946..e1bb6b83 100644 ---- a/usr/lib/common/mech_openssl.c -+++ b/usr/lib/common/mech_openssl.c -@@ -1854,6 +1854,7 @@ static int curve_nid_from_params(const CK_BYTE *params, CK_ULONG params_len) - { - const unsigned char *oid; - ASN1_OBJECT *obj = NULL; -+ EC_GROUP *grp; - int nid; - - oid = params; -@@ -1866,6 +1867,14 @@ static int curve_nid_from_params(const CK_BYTE *params, CK_ULONG params_len) - nid = OBJ_obj2nid(obj); - ASN1_OBJECT_free(obj); - -+ grp = EC_GROUP_new_by_curve_name(nid); -+ if (grp == NULL) { -+ TRACE_ERROR("curve not supported by OpenSSL.\n"); -+ return NID_undef; -+ } -+ -+ EC_GROUP_free(grp); -+ - return nid; - } - diff --git a/SOURCES/opencryptoki-v3.26.0-CVE-2026-40253-part1.patch b/SOURCES/opencryptoki-v3.26.0-CVE-2026-40253-part1.patch new file mode 100644 index 0000000..13e99df --- /dev/null +++ b/SOURCES/opencryptoki-v3.26.0-CVE-2026-40253-part1.patch @@ -0,0 +1,110 @@ +commit 54e1a3e9c5474a3563b48c99527f9d6966ea4746 +Author: Ingo Franzki +Date: Thu Jan 8 10:48:29 2026 +0100 + + COMMON: Fix CKM_ECDH_AES_KEY_WRAP buffer size calculation with compressed keys + + When a C_WrapKey with CKM_ECDH_AES_KEY_WRAP is performed, and the EC public + key used with it uses a compressed EC point, then the size of the wrapped + key material is calculated wrongly. This may lead to an out-of-bounds write + when the caller provides a buffer of that calculated size. + + The temporary EC key generated internally by this mechanism is always + uses an uncompressed EC point, but the buffer size is erroneously calculated + using the EC point of the supplied EC public key. Thus, in case a compressed + EC point is supplied, the buffer size calculation results in a too short + buffer. + + Fix this by calculating the buffer size using the EC point of the internally + generated EC key, because this is what is later on written to the buffer. + + Fixes: 785d7577e1477d12fbe235554e7e7b24f2de34b7 + Reported-by: Pavel Kohout of Aisle Research, www.aisle.com + Signed-off-by: Ingo Franzki + +diff --git a/usr/lib/common/mech_ec.c b/usr/lib/common/mech_ec.c +index 2399c1cf..ce031ec0 100644 +--- a/usr/lib/common/mech_ec.c ++++ b/usr/lib/common/mech_ec.c +@@ -1758,6 +1758,31 @@ CK_RV ecdh_aes_key_wrap(STDLL_TokData_t *tokdata, SESSION *sess, + goto done; + } + ++ /* Get the (raw) size of the generated EC point */ ++ rc = object_mgr_find_in_map1(tokdata, ec_publ_key_handle, ++ &pub_key_obj, READ_LOCK); ++ if (rc != CKR_OK) { ++ TRACE_ERROR("Failed to acquire key from EC public key handle.\n"); ++ if (rc == CKR_OBJECT_HANDLE_INVALID) ++ rc = CKR_KEY_HANDLE_INVALID; ++ goto done; ++ } ++ ++ rc = template_attribute_get_non_empty(pub_key_obj->template, CKA_EC_POINT, ++ &ec_point); ++ if (rc != CKR_OK) { ++ TRACE_DEVEL("Failed to get CKA_EC_POINT.\n"); ++ goto done; ++ } ++ ++ rc = ber_decode_OCTET_STRING((CK_BYTE *)ec_point->pValue, ++ &pub_ec_point, &pub_ec_point_len, &field_len); ++ if (rc != CKR_OK || field_len != ec_point->ulValueLen) { ++ rc = CKR_FUNCTION_FAILED; ++ TRACE_DEVEL("Failed to decode CKA_EC_POINT.\n"); ++ goto done; ++ } ++ + /* Perform ECDH to derive a shared AES key */ + ecdh_params.kdf = params->kdf; + ecdh_params.pSharedData = params->pSharedData; +@@ -1813,7 +1838,7 @@ CK_RV ecdh_aes_key_wrap(STDLL_TokData_t *tokdata, SESSION *sess, + } + + /* Calculate the final length of the wrapped key data */ +- total_len = ecdh_params.ulPublicDataLen + wrapped_key_len; ++ total_len = pub_ec_point_len + wrapped_key_len; + + if (length_only) { + *out_data_len = total_len; +@@ -1831,31 +1856,6 @@ CK_RV ecdh_aes_key_wrap(STDLL_TokData_t *tokdata, SESSION *sess, + * Copy the (raw) EC point of the public transport EC key as first part of + * the wrapped key data. + */ +- rc = object_mgr_find_in_map1(tokdata, ec_publ_key_handle, +- &pub_key_obj, READ_LOCK); +- if (rc != CKR_OK) { +- TRACE_ERROR("Failed to acquire key from EC public key handle.\n"); +- if (rc == CKR_OBJECT_HANDLE_INVALID) +- return CKR_KEY_HANDLE_INVALID; +- else +- return rc; +- } +- +- rc = template_attribute_get_non_empty(pub_key_obj->template, CKA_EC_POINT, +- &ec_point); +- if (rc != CKR_OK) { +- TRACE_DEVEL("Failed to get CKA_EC_POINT.\n"); +- goto done; +- } +- +- rc = ber_decode_OCTET_STRING((CK_BYTE *)ec_point->pValue, +- &pub_ec_point, &pub_ec_point_len, &field_len); +- if (rc != CKR_OK || field_len != ec_point->ulValueLen) { +- rc = CKR_FUNCTION_FAILED; +- TRACE_DEVEL("Failed to decode CKA_EC_POINT.\n"); +- goto done; +- } +- + memcpy(out_data, pub_ec_point, pub_ec_point_len); + + /* +@@ -1864,7 +1864,7 @@ CK_RV ecdh_aes_key_wrap(STDLL_TokData_t *tokdata, SESSION *sess, + */ + rc = encr_mgr_encrypt(tokdata, sess, FALSE, &aeskw_ctx, + in_data, in_data_len, +- out_data + ecdh_params.ulPublicDataLen, ++ out_data + pub_ec_point_len, + &wrapped_key_len); + if (rc != CKR_OK) { + TRACE_ERROR("Failed to encrypt the to-be-wrapped key: %s (0x%lx)\n", diff --git a/SOURCES/opencryptoki-v3.26.0-CVE-2026-40253-part2.patch b/SOURCES/opencryptoki-v3.26.0-CVE-2026-40253-part2.patch new file mode 100644 index 0000000..da5d3f9 --- /dev/null +++ b/SOURCES/opencryptoki-v3.26.0-CVE-2026-40253-part2.patch @@ -0,0 +1,2031 @@ +commit 838ede224ad29ac3e1e6769bd00bf6be52185b5b +Author: Ingo Franzki +Date: Mon Mar 30 10:19:40 2026 +0200 + + COMMON: Fix possible out-of-bounds access in BER decode functions + + When decoding BER encoded data the length of the BER encoded data as well as + any length fields inside the BER encoded data must be validated to not cause + an out-of-bounds access to data behind the BER encoded data. + + Add length parameters to any of the BER decoder functions to allow validation + of the decoded length information. + + Reported-by: Sebastián Alba + Signed-off-by: Ingo Franzki + +diff --git a/usr/lib/cca_stdll/cca_specific.c b/usr/lib/cca_stdll/cca_specific.c +index c6f08882..b99f99da 100644 +--- a/usr/lib/cca_stdll/cca_specific.c ++++ b/usr/lib/cca_stdll/cca_specific.c +@@ -12404,8 +12404,8 @@ static CK_RV import_ec_pubkey(STDLL_TokData_t *tokdata, TEMPLATE *pub_templ) + return rc; + } + +- rc = ber_decode_OCTET_STRING(attr->pValue, &pubkey, &publen, +- &field_len); ++ rc = ber_decode_OCTET_STRING(attr->pValue, attr->ulValueLen, ++ &pubkey, &publen, &field_len); + if (rc != CKR_OK || attr->ulValueLen != field_len) { + TRACE_DEVEL("ber decoding of public key failed\n"); + return CKR_ATTRIBUTE_VALUE_INVALID; +diff --git a/usr/lib/common/asn1.c b/usr/lib/common/asn1.c +index 93af67d3..c2e2d4b5 100644 +--- a/usr/lib/common/asn1.c ++++ b/usr/lib/common/asn1.c +@@ -155,13 +155,13 @@ CK_ULONG ber_encode_INTEGER(CK_BBOOL length_only, + + // + // +-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_int, + // + 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_int, + } + + 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_int, + 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_int, + 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 length_only, + + // + // +-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 *str, + // 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 *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; ++ } + + *data = &str[2]; + *data_len = len; +@@ -372,9 +396,17 @@ CK_RV ber_decode_OCTET_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; ++ } + + *data = &str[3]; + *data_len = len; +@@ -386,6 +418,10 @@ CK_RV ber_decode_OCTET_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; ++ } + + *data = &str[4]; + *data_len = len; +@@ -399,6 +435,10 @@ CK_RV ber_decode_OCTET_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; ++ } + + *data = &str[5]; + *data_len = len; +@@ -515,13 +555,13 @@ CK_ULONG ber_encode_BIT_STRING(CK_BBOOL length_only, + * 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 length_only, + + // + // +-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; +@@ -834,7 +934,8 @@ CK_RV ber_encode_CHOICE(CK_BBOOL length_only, + return CKR_FUNCTION_FAILED; + } + +-CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed, ++CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_ULONG choice_len, ++ CK_BBOOL constructed, + CK_BYTE **data, + CK_ULONG *data_len, CK_ULONG *field_len, + CK_ULONG *option) +@@ -842,7 +943,7 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed, + 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; + } +@@ -858,6 +959,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed, + // + 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; +@@ -865,9 +970,17 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed, + } + + 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; +@@ -878,6 +991,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed, + 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; +@@ -890,6 +1007,10 @@ CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed, + 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; +@@ -1000,10 +1121,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; +@@ -1015,7 +1135,7 @@ CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data, + 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; +@@ -1023,7 +1143,8 @@ CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data, + // 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; +@@ -1032,15 +1153,18 @@ CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data, + + // '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"); + +@@ -1058,13 +1182,14 @@ CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data, + * 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; + +@@ -1072,7 +1197,9 @@ CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_BYTE **alg_oid, CK_ULONG *alg_oid_len, + *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); +@@ -1080,23 +1207,35 @@ CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_BYTE **alg_oid, CK_ULONG *alg_oid_len, + } + + 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); +@@ -1363,10 +1502,11 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + 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; +@@ -1378,7 +1518,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + 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; + +@@ -1388,7 +1529,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1397,7 +1539,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1406,7 +1549,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1415,7 +1559,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1424,7 +1569,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1433,7 +1579,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1442,7 +1589,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1451,7 +1599,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1460,7 +1609,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1480,7 +1630,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1489,7 +1640,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1504,7 +1656,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1519,7 +1672,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1534,7 +1688,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1549,7 +1704,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1564,7 +1720,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1579,7 +1736,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1594,7 +1752,8 @@ CK_RV ber_decode_RSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -1782,9 +1941,7 @@ CK_RV ber_decode_RSAPublicKey(CK_BYTE *data, + 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"); +@@ -1794,7 +1951,8 @@ CK_RV ber_decode_RSAPublicKey(CK_BYTE *data, + /* + * 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"); +@@ -1806,20 +1964,21 @@ CK_RV ber_decode_RSAPublicKey(CK_BYTE *data, + 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; +@@ -2053,11 +2212,12 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + 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; +@@ -2071,7 +2231,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + } + // 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; +@@ -2080,7 +2241,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -2089,7 +2251,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -2098,7 +2261,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -2117,7 +2281,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -2132,7 +2297,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -2147,7 +2313,8 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -2162,7 +2329,7 @@ CK_RV ber_decode_DSAPrivateKey(CK_BYTE *data, + + // 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; +@@ -2405,9 +2572,7 @@ CK_RV ber_decode_DSAPublicKey(CK_BYTE *data, + 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"); +@@ -2422,27 +2587,29 @@ CK_RV ber_decode_DSAPublicKey(CK_BYTE *data, + 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; +@@ -2541,8 +2708,8 @@ CK_RV der_encode_ECPrivateKey(CK_BBOOL length_only, + } + // 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; +@@ -2624,8 +2791,8 @@ CK_RV der_encode_ECPrivateKey(CK_BBOOL length_only, + + /* 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; +@@ -2717,7 +2884,7 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, + 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; +@@ -2731,7 +2898,7 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, + * 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; +@@ -2743,7 +2910,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, + 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; +@@ -2756,7 +2924,7 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, + } + + /* 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; +@@ -2764,7 +2932,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, + 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; +@@ -2772,8 +2941,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, + 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; +@@ -2785,8 +2954,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, + if (buf_offset + offset < data_len) { + + /* Decode CHOICE */ +- rc = ber_decode_CHOICE(buf + offset, TRUE, &choice, &choice_len, +- &field_len, &option); ++ rc = ber_decode_CHOICE(buf + offset, buf_len - offset, TRUE, ++ &choice, &choice_len, &field_len, &option); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_CHOICE failed\n"); + goto cleanup; +@@ -2803,8 +2972,8 @@ CK_RV der_decode_ECPrivateKey(CK_BYTE *data, + 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; +@@ -2887,7 +3056,8 @@ CK_RV ber_encode_ECPublicKey(CK_BBOOL length_only, CK_BYTE **data, + 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__); +@@ -3018,9 +3188,7 @@ CK_RV der_decode_ECPublicKey(CK_BYTE *data, + 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"); +@@ -3032,8 +3200,9 @@ CK_RV der_decode_ECPublicKey(CK_BYTE *data, + * 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; +@@ -3251,10 +3420,11 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data, + 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; +@@ -3267,7 +3437,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data, + } + // extract the parameter data into ATTRIBUTES + // +- rc = ber_decode_SEQUENCE(alg + ber_idDHLen, &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; +@@ -3275,7 +3446,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data, + 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; +@@ -3283,7 +3455,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data, + 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; +@@ -3299,7 +3472,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data, + 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; +@@ -3313,7 +3487,8 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data, + } + + // 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; +@@ -3327,7 +3502,7 @@ CK_RV ber_decode_DHPrivateKey(CK_BYTE *data, + } + + // 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; +@@ -3549,9 +3724,7 @@ CK_RV ber_decode_DHPublicKey(CK_BYTE *data, + 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"); +@@ -3566,20 +3739,21 @@ CK_RV ber_decode_DHPublicKey(CK_BYTE *data, + 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; +@@ -3823,10 +3997,8 @@ static CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data, + 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; +@@ -3843,14 +4015,14 @@ static CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data, + * 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; +@@ -3860,7 +4032,8 @@ static CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data, + + /* 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; +@@ -3883,7 +4056,7 @@ static CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data, + } + + /* 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; +@@ -4179,12 +4352,13 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + 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; +@@ -4203,7 +4377,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + } + + /* 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; + +@@ -4211,7 +4386,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + 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; +@@ -4219,7 +4395,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + 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; +@@ -4235,7 +4412,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + } + + /* 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; +@@ -4251,7 +4429,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + } + + /* 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; +@@ -4267,7 +4446,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + } + + /* 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; +@@ -4283,7 +4463,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + } + + /* 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; +@@ -4299,7 +4480,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + } + + /* 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; +@@ -4316,8 +4498,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + + /* t1 (optional, within choice) */ + if (offset < buf_len) { +- rc = ber_decode_CHOICE(buf + offset, TRUE, &tmp, &len, &field_len, +- &option); ++ rc = ber_decode_CHOICE(buf + offset, buf_len - offset, TRUE, ++ &tmp, &len, &field_len, &option); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n"); + goto cleanup; +@@ -4331,7 +4513,8 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + + 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; +@@ -4355,7 +4538,7 @@ static CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data, + } + + /* 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; +@@ -4577,10 +4760,8 @@ static CK_RV ber_decode_IBM_KyberPublicKey(CK_BYTE *data, + 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; +@@ -4596,14 +4777,14 @@ static CK_RV ber_decode_IBM_KyberPublicKey(CK_BYTE *data, + * 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; +@@ -4619,7 +4800,7 @@ static CK_RV ber_decode_IBM_KyberPublicKey(CK_BYTE *data, + } + + /* 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; +@@ -4845,12 +5026,12 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data, + 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; +@@ -4869,7 +5050,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data, + } + + /* 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; + +@@ -4877,7 +5059,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data, + 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; +@@ -4885,7 +5068,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data, + 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; +@@ -4902,8 +5086,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data, + + /* pk (optional, within choice) */ + if (offset < buf_len) { +- rc = ber_decode_CHOICE(buf + offset, TRUE, &tmp, &len, &field_len, +- &option); ++ rc = ber_decode_CHOICE(buf + offset, buf_len - offset, TRUE, ++ &tmp, &len, &field_len, &option); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n"); + goto cleanup; +@@ -4917,7 +5101,8 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data, + + 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; +@@ -4944,7 +5129,7 @@ static CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data, + } + + /* 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; +@@ -5102,8 +5287,8 @@ CK_RV ber_decode_IBM_ML_DSA_PublicKey(CK_MECHANISM_TYPE mech, + * BIT STRING - public key (rho | t1) + */ + +- rc = ber_decode_SPKI(data, &algoid, &algoid_len, ¶m, ¶m_len, +- &pub, &pub_len); ++ rc = ber_decode_SPKI(data, data_len, &algoid, &algoid_len, ++ ¶m, ¶m_len, &pub, &pub_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_SPKI failed\n"); + return rc; +@@ -5139,7 +5324,7 @@ CK_RV ber_decode_IBM_ML_DSA_PublicKey(CK_MECHANISM_TYPE mech, + } + + /* Add raw SPKI as CKA_VALUE to public key (z/OS ICSF compatibility) */ +- rc = ber_decode_SEQUENCE(data, &pub, &pub_len, &raw_spki_len); ++ rc = ber_decode_SEQUENCE(data, data_len, &pub, &pub_len, &raw_spki_len); + if (rc != CKR_OK) { + TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n", + __func__, rc); +@@ -5375,7 +5560,7 @@ CK_RV ber_decode_IBM_ML_DSA_PrivateKey(CK_MECHANISM_TYPE mech, + CK_BYTE *algid = NULL, *priv = NULL, *both = NULL, *key = NULL; + CK_BYTE *pseed = NULL, *tmp = NULL; + CK_ULONG both_len, field_len, algid_len, key_len = 0, pseed_len = 0; +- CK_ULONG ofs = 0, option, len; ++ CK_ULONG ofs = 0, option, len, priv_len; + CK_RV rc; + + if (mech == CKM_IBM_DILITHIUM) { +@@ -5387,7 +5572,7 @@ CK_RV ber_decode_IBM_ML_DSA_PrivateKey(CK_MECHANISM_TYPE mech, + + /* Check if this is a ML-DSA private key */ + rc = ber_decode_PrivateKeyInfo(data, data_len, &algid, &algid_len, +- &priv); ++ &priv, &priv_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n"); + return rc; +@@ -5413,35 +5598,37 @@ CK_RV ber_decode_IBM_ML_DSA_PrivateKey(CK_MECHANISM_TYPE mech, + */ + switch (priv[0]) { + case 0x30: /* SEQUENCE - both format*/ +- rc = ber_decode_SEQUENCE(priv, &both, &both_len, &field_len); ++ rc = ber_decode_SEQUENCE(priv, priv_len, &both, &both_len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_SEQUENCE failed\n"); + return rc; + } + +- rc = ber_decode_OCTET_STRING(both, &pseed, &pseed_len, &field_len); ++ rc = ber_decode_OCTET_STRING(both, both_len, &pseed, &pseed_len, ++ &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); + return rc; + } + +- rc = ber_decode_OCTET_STRING(both + field_len, &key, &key_len, +- &field_len); ++ rc = ber_decode_OCTET_STRING(both + field_len, both_len - field_len, ++ &key, &key_len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); + return rc; + } + break; + case 0x04: /* OCTET STRING - expanded key */ +- rc = ber_decode_OCTET_STRING(priv, &key, &key_len, &field_len); ++ rc = ber_decode_OCTET_STRING(priv, priv_len, &key, &key_len, ++ &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); + return rc; + } + break; + case 0x80: /* CHOICE - private seed only */ +- rc = ber_decode_CHOICE(priv, FALSE, &pseed, &pseed_len, &field_len, +- &option); ++ rc = ber_decode_CHOICE(priv, priv_len, FALSE, &pseed, &pseed_len, ++ &field_len, &option); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_CHOICE failed\n"); + return rc; +@@ -5529,7 +5716,7 @@ CK_RV ber_decode_IBM_ML_DSA_PrivateKey(CK_MECHANISM_TYPE mech, + } + + /* 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); +@@ -5689,8 +5876,8 @@ CK_RV ber_decode_IBM_ML_KEM_PublicKey(CK_MECHANISM_TYPE mech, + * BIT STRING - public key (pk) + */ + +- rc = ber_decode_SPKI(data, &algoid, &algoid_len, ¶m, ¶m_len, +- &pub, &pub_len); ++ rc = ber_decode_SPKI(data, data_len, &algoid, &algoid_len, ++ ¶m, ¶m_len, &pub, &pub_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_SPKI failed\n"); + return rc; +@@ -5716,7 +5903,7 @@ CK_RV ber_decode_IBM_ML_KEM_PublicKey(CK_MECHANISM_TYPE mech, + } + + /* Add raw SPKI as CKA_VALUE to public key (z/OS ICSF compatibility) */ +- rc = ber_decode_SEQUENCE(data, &pub, &pub_len, &raw_spki_len); ++ rc = ber_decode_SEQUENCE(data, data_len, &pub, &pub_len, &raw_spki_len); + if (rc != CKR_OK) { + TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n", + __func__, rc); +@@ -5898,7 +6085,7 @@ CK_RV ber_decode_IBM_ML_KEM_PrivateKey(CK_MECHANISM_TYPE mech, + CK_BYTE *algid = NULL, *priv = NULL, *both = NULL, *key = NULL; + CK_BYTE *pseed = NULL, *tmp = NULL; + CK_ULONG both_len, field_len, algid_len, key_len = 0, pseed_len = 0; +- CK_ULONG option, len; ++ CK_ULONG option, len, priv_len; + CK_RV rc; + + if (mech == CKM_IBM_KYBER) { +@@ -5909,7 +6096,7 @@ CK_RV ber_decode_IBM_ML_KEM_PrivateKey(CK_MECHANISM_TYPE mech, + + /* Check if this is a ML-KEM private key */ + rc = ber_decode_PrivateKeyInfo(data, data_len, &algid, &algid_len, +- &priv); ++ &priv, &priv_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n"); + return rc; +@@ -5935,35 +6122,37 @@ CK_RV ber_decode_IBM_ML_KEM_PrivateKey(CK_MECHANISM_TYPE mech, + */ + switch (priv[0]) { + case 0x30: /* SEQUENCE - both format*/ +- rc = ber_decode_SEQUENCE(priv, &both, &both_len, &field_len); ++ rc = ber_decode_SEQUENCE(priv, priv_len, &both, &both_len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_SEQUENCE failed\n"); + return rc; + } + +- rc = ber_decode_OCTET_STRING(both, &pseed, &pseed_len, &field_len); ++ rc = ber_decode_OCTET_STRING(both, both_len, &pseed, &pseed_len, ++ &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); + return rc; + } + +- rc = ber_decode_OCTET_STRING(both + field_len, &key, &key_len, +- &field_len); ++ rc = ber_decode_OCTET_STRING(both + field_len, both_len - field_len, ++ &key, &key_len, &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); + return rc; + } + break; + case 0x04: /* OCTET STRING - expanded key */ +- rc = ber_decode_OCTET_STRING(priv, &key, &key_len, &field_len); ++ rc = ber_decode_OCTET_STRING(priv, priv_len, &key, &key_len, ++ &field_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_OCTET_STRING failed\n"); + return rc; + } + break; + case 0x80: /* CHOICE - private seed only */ +- rc = ber_decode_CHOICE(priv, FALSE, &pseed, &pseed_len, &field_len, +- &option); ++ rc = ber_decode_CHOICE(priv, priv_len, FALSE, &pseed, &pseed_len, ++ &field_len, &option); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_CHOICE failed\n"); + return rc; +@@ -6006,7 +6195,7 @@ CK_RV ber_decode_IBM_ML_KEM_PrivateKey(CK_MECHANISM_TYPE mech, + } + + /* 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); +diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h +index 884bc9ed..c61969b6 100644 +--- a/usr/lib/common/h_extern.h ++++ b/usr/lib/common/h_extern.h +@@ -2923,7 +2923,7 @@ CK_ULONG ber_encode_INTEGER(CK_BBOOL length_only, + 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); + +@@ -2933,7 +2933,7 @@ CK_ULONG ber_encode_BIT_STRING(CK_BBOOL length_only, + CK_ULONG data_len, + CK_BYTE unused_bits); + +-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); + +@@ -2942,7 +2942,7 @@ CK_RV ber_encode_OCTET_STRING(CK_BBOOL length_only, + 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); + +@@ -2951,7 +2951,7 @@ CK_RV ber_encode_SEQUENCE(CK_BBOOL length_only, + 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); + +@@ -2961,7 +2961,8 @@ CK_RV ber_encode_CHOICE(CK_BBOOL length_only, + CK_ULONG *str_len, CK_BYTE *data, CK_ULONG data_len, + CK_BBOOL constructed); + +-CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_BBOOL constructed, ++CK_RV ber_decode_CHOICE(CK_BYTE *choice, CK_ULONG choice_len, ++ CK_BBOOL constructed, + CK_BYTE **data, + CK_ULONG *data_len, CK_ULONG *field_len, + CK_ULONG *option); +@@ -2973,12 +2974,12 @@ CK_RV ber_encode_PrivateKeyInfo(CK_BBOOL length_only, + const CK_ULONG algorithm_id_len, + CK_BYTE *priv_key, CK_ULONG priv_key_len); + +-CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data, +- CK_ULONG data_len, +- CK_BYTE **algorithm_id, +- CK_ULONG *alg_len, CK_BYTE **priv_key); ++CK_RV ber_decode_PrivateKeyInfo(CK_BYTE *data, CK_ULONG data_len, ++ CK_BYTE **algorithm_id, CK_ULONG *alg_len, ++ CK_BYTE **priv_key, CK_ULONG *priv_key_len); + +-CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_BYTE **alg_oid, CK_ULONG *alg_oid_len, ++CK_RV ber_decode_SPKI(CK_BYTE *spki, CK_ULONG spki_len, ++ CK_BYTE **alg_oid, CK_ULONG *alg_oid_len, + CK_BYTE **param, CK_ULONG *param_len, + CK_BYTE **key, CK_ULONG *key_len); + +diff --git a/usr/lib/common/key_mgr.c b/usr/lib/common/key_mgr.c +index 08b38a80..4d100307 100644 +--- a/usr/lib/common/key_mgr.c ++++ b/usr/lib/common/key_mgr.c +@@ -1656,10 +1656,11 @@ CK_RV key_mgr_get_private_key_type(CK_BYTE *keydata, + { + CK_BYTE *alg = NULL; + CK_BYTE *priv_key = NULL; +- CK_ULONG alg_len, i; ++ CK_ULONG alg_len, priv_key_len, i; + CK_RV rc; + +- rc = ber_decode_PrivateKeyInfo(keydata, keylen, &alg, &alg_len, &priv_key); ++ rc = ber_decode_PrivateKeyInfo(keydata, keylen, &alg, &alg_len, ++ &priv_key, &priv_key_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_PrivateKeyInfo failed.\n"); + return rc; +diff --git a/usr/lib/common/mech_ec.c b/usr/lib/common/mech_ec.c +index ce031ec0..2b1609e4 100644 +--- a/usr/lib/common/mech_ec.c ++++ b/usr/lib/common/mech_ec.c +@@ -1511,7 +1511,7 @@ int ec_point_from_public_data(const CK_BYTE *data, CK_ULONG data_len, + + 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 */ +@@ -1776,6 +1776,7 @@ CK_RV ecdh_aes_key_wrap(STDLL_TokData_t *tokdata, SESSION *sess, + } + + rc = ber_decode_OCTET_STRING((CK_BYTE *)ec_point->pValue, ++ ec_point->ulValueLen, + &pub_ec_point, &pub_ec_point_len, &field_len); + if (rc != CKR_OK || field_len != ec_point->ulValueLen) { + rc = CKR_FUNCTION_FAILED; +@@ -1796,6 +1797,7 @@ CK_RV ecdh_aes_key_wrap(STDLL_TokData_t *tokdata, SESSION *sess, + } + + rc = ber_decode_OCTET_STRING((CK_BYTE *)ec_point->pValue, ++ ec_point->ulValueLen, + &ecdh_params.pPublicData, + &ecdh_params.ulPublicDataLen, + &field_len); +diff --git a/usr/lib/common/pkey_utils.c b/usr/lib/common/pkey_utils.c +index 0a9f77e7..241629f8 100644 +--- a/usr/lib/common/pkey_utils.c ++++ b/usr/lib/common/pkey_utils.c +@@ -1604,8 +1604,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; +@@ -1752,8 +1752,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; +diff --git a/usr/lib/ep11_stdll/ep11_login.c b/usr/lib/ep11_stdll/ep11_login.c +index 10f1366e..e89e1b5c 100644 +--- a/usr/lib/ep11_stdll/ep11_login.c ++++ b/usr/lib/ep11_stdll/ep11_login.c +@@ -113,13 +113,14 @@ static CK_RV get_login_importer_key(target_t target, + * 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; +@@ -128,7 +129,7 @@ static CK_RV get_login_importer_key(target_t target, + 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; +@@ -137,7 +138,7 @@ static CK_RV get_login_importer_key(target_t target, + data += field_len; + data_len -= field_len; + +- rc = ber_decode_OCTET_STRING(data, &cnt, &cnt_len, &field_len); ++ rc = ber_decode_OCTET_STRING(data, data_len, &cnt, &cnt_len, &field_len); + if (rc != CKR_OK || field_len > data_len) { + TRACE_ERROR("%s ber_decode_OCTET_STRING (COUNTER) failed\n", __func__); + return CKR_FUNCTION_FAILED; +diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c +index cb474ebe..df41be57 100644 +--- a/usr/lib/ep11_stdll/ep11_specific.c ++++ b/usr/lib/ep11_stdll/ep11_specific.c +@@ -1586,7 +1586,8 @@ CK_RV ep11tok_extract_blob_info(CK_BYTE *blob, CK_ULONG blob_len, + * 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, &field_len) == CKR_OK) { ++ ber_decode_SEQUENCE(blob, blob_len, &data, &data_len, ++ &field_len) == CKR_OK) { + /* It is a SPKI, fields follow as OCTET STRINGs right after SPKI data */ + if (blob_len < field_len) { + TRACE_ERROR("MACed SPKI is too small\n"); +@@ -1617,7 +1618,8 @@ CK_RV ep11tok_extract_blob_info(CK_BYTE *blob, CK_ULONG blob_len, + return CKR_FUNCTION_FAILED; + } + +- if (ber_decode_OCTET_STRING(blob + ofs, &data, &data_len, ++ if (ber_decode_OCTET_STRING(blob + ofs, blob_len - ofs, ++ &data, &data_len, + &field_len) != CKR_OK) { + TRACE_ERROR("Failed to decode MACed SPKI field %s\n", + fields[i].field); +@@ -3671,7 +3673,8 @@ static CK_RV make_maced_spki(STDLL_TokData_t *tokdata, SESSION *sess, + 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; + } +@@ -3798,9 +3801,7 @@ static int get_curve_type_from_spki(CK_BYTE *spki, CK_ULONG spki_len) + CK_ULONG field_len, len, i; + CK_RV rc; + +- UNUSED(spki_len); +- +- rc = ber_decode_SPKI(spki, &algid, &algid_len, ¶m, ¶m_len, ++ rc = ber_decode_SPKI(spki, spki_len, &algid, &algid_len, ¶m, ¶m_len, + &pubkey, &pubkey_len); + if (rc != CKR_OK) { + TRACE_DEVEL("ber_decode_SPKI failed\n"); +@@ -3812,8 +3813,8 @@ static int get_curve_type_from_spki(CK_BYTE *spki, CK_ULONG spki_len) + * 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 -1; +@@ -4335,8 +4336,9 @@ static CK_RV import_EC_key(STDLL_TokData_t *tokdata, SESSION *sess, + } + + /* 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; +@@ -5295,7 +5297,7 @@ static CK_RV import_blob_private_public(STDLL_TokData_t *tokdata, SESSION *sess, + } + + /* SPKI is a MACed SPKI, get length of SPKI part only */ +- rc = ber_decode_SEQUENCE(spki, &data, &data_len, &raw_spki_len); ++ rc = ber_decode_SEQUENCE(spki, spki_len, &data, &data_len, &raw_spki_len); + if (rc != CKR_OK) { + TRACE_ERROR("%s ber_decode_SEQUENCE failed rc=0x%lx\n", + __func__, rc); +@@ -6189,7 +6191,7 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess, + + 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); +@@ -8741,8 +8743,10 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t *tokdata, SESSION *session, + 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 */ +@@ -9524,15 +9528,15 @@ static CK_RV dh_generate_keypair(STDLL_TokData_t *tokdata, + #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; +@@ -9933,15 +9937,15 @@ static CK_RV dsa_generate_keypair(STDLL_TokData_t *tokdata, + } + + /* 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); +@@ -10214,7 +10218,7 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata, + 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", +@@ -10310,8 +10314,9 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata, + * 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", +@@ -10322,7 +10327,8 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata, + /* 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); +@@ -10330,7 +10336,9 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata, + } + + 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; +@@ -10357,7 +10365,9 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t *tokdata, + + /* 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); +@@ -13929,7 +13939,7 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session, + } + + /* csum is a MACed SPKI, get length of SPKI part only */ +- rc = ber_decode_SEQUENCE(csum, &temp, &temp_len, &cslen); ++ rc = ber_decode_SEQUENCE(csum, cslen, &temp, &temp_len, &cslen); + if (rc != CKR_OK) { + TRACE_ERROR("%s ber_decode_SEQUENCE failed rc=0x%lx\n", + __func__, rc); +diff --git a/usr/lib/ica_s390_stdll/ica_specific.c b/usr/lib/ica_s390_stdll/ica_specific.c +index 005b3c19..192b1ea5 100644 +--- a/usr/lib/ica_s390_stdll/ica_specific.c ++++ b/usr/lib/ica_s390_stdll/ica_specific.c +@@ -6244,8 +6244,8 @@ static CK_RV ica_build_ec_pub_key(OBJECT *key_obj, ICA_EC_KEY **eckey, + } + + /* 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; diff --git a/SPECS/opencryptoki.spec b/SPECS/opencryptoki.spec index 8319a7a..eb25233 100644 --- a/SPECS/opencryptoki.spec +++ b/SPECS/opencryptoki.spec @@ -1,7 +1,7 @@ Name: opencryptoki Summary: Implementation of the PKCS#11 (Cryptoki) specification v3.0 and partially v3.1 -Version: 3.25.0 -Release: 4%{?dist}.2 +Version: 3.26.0 +Release: 2%{?dist}.2 License: CPL-1.0 URL: https://github.com/opencryptoki/opencryptoki Source0: https://github.com/opencryptoki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz @@ -19,25 +19,12 @@ Patch2: opencryptoki-3.24.0-tmpfiles-image-mode.patch Patch3: opencryptoki-lockdir-image-mode.patch # upstream patches -# Fix detection of EC curve not supported by OpenSSL-3.5.x -Patch10: opencryptoki-openssl-3.5.x.patch - -# Fix covscan findings, https://github.com/opencryptoki/opencryptoki/pull/880 -Patch11: opencryptoki-3.25.0-covscan-findings.patch - -# Remove the use of MD5, pkcsslotd crashes in FIPS mode -Patch12: opencryptoki-3.25.0-reject-using-md5-in-fips-mode.patch - -# EP11: Fix unwrapping of attribute bound EC keys -# https://github.com/ifranzki/opencryptoki/commit/d3dc88c -Patch13: opencryptoki-3.25.0-fix-unwrapping-attribute-bound-EC-keys.patch - -# EP11: Fix private secure key blob import -# https://github.com/ifranzki/opencryptoki/commit/ab740fd -Patch14: opencryptoki-3.25.0-fix-private-secure-key-blob-import.patch - -# CVE-2026-23893, symlink-following vulnerabilities -Patch15: opencryptoki-3.25.0-CVE-2026-23893.patch +# CVE-3-2026-23893 +Patch100: opencryptoki-3.26.0-CVE-3-2026-23893.patch +Patch101: opencryptoki-3.26.0-Fix-syslog-message-printing-about-different-CPs.patch +# Fix CVE-2026-40253 +Patch102: opencryptoki-v3.26.0-CVE-2026-40253-part1.patch +Patch103: opencryptoki-v3.26.0-CVE-2026-40253-part2.patch Requires(pre): coreutils Requires: (selinux-policy >= 38.1.14-1 if selinux-policy-targeted) @@ -424,13 +411,20 @@ fi %changelog -* Tue Mar 03 2026 Than Ngo - 3.25.0-4.2 -- Resolves: RHEL-144820, Privilege Escalation or Data Exposure via Symlink Following +* Tue May 26 2026 Than Ngo - 3.26.0-2.2 +- Resolves: RHEL-171562, Fix CVE-2026-40253, possible out-of-bounds access in BER decode functions -* Tue Feb 03 2026 Than Ngo - 3.25.0-4.1 -- Fix unwrapping of attribute bound EC keys -- Fix private secure key blob import - Resolves: RHEL-131644 +* Tue Apr 28 2026 Than Ngo - 3.26.0-2.1 +- Resolves: RHEL-169586, Fix syslog message printing about different CPs + +* Fri Feb 13 2026 Than Ngo - 3.26.0-2 +- Resolves: RHEL-144821, CVE-2026-23893 + +* Wed Dec 17 2025 Than Ngo - 3.26.0-1 +- Resolves: RHEL-75139, ep11 token BLS support +- Resolves: RHEL-85381, ep11 token: ML-KEM and ML-DSA support +- Resolves: RHEL-85384. cca token: ML-KEM and ML-DSA support +- Resolves: RHEL-100059, openCryptoki 3.26.0 * Wed Aug 13 2025 Than Ngo - 3.25.0-4 - Fix pkcsslotd fails to start in FIPS