From 06bdf304912acb9411bf789bc3b1e20904ef4702 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Mon, 30 Mar 2026 10:49:14 -0400 Subject: [PATCH] import CS opencryptoki-3.26.0-2.el9 --- .gitignore | 2 +- .opencryptoki.metadata | 2 +- ...opencryptoki-3.25.0-covscan-findings.patch | 43 -- ...3.25.0-reject-using-md5-in-fips-mode.patch | 176 ------- ...opencryptoki-3.26.0-CVE-3-2026-23893.patch | 453 ++++++++++++++++++ SOURCES/opencryptoki-openssl-3.5.x.patch | 48 -- SPECS/opencryptoki.spec | 23 +- 7 files changed, 468 insertions(+), 279 deletions(-) delete mode 100644 SOURCES/opencryptoki-3.25.0-covscan-findings.patch delete mode 100644 SOURCES/opencryptoki-3.25.0-reject-using-md5-in-fips-mode.patch create mode 100644 SOURCES/opencryptoki-3.26.0-CVE-3-2026-23893.patch delete mode 100644 SOURCES/opencryptoki-openssl-3.5.x.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-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.26.0-CVE-3-2026-23893.patch b/SOURCES/opencryptoki-3.26.0-CVE-3-2026-23893.patch new file mode 100644 index 0000000..85bb2fd --- /dev/null +++ b/SOURCES/opencryptoki-3.26.0-CVE-3-2026-23893.patch @@ -0,0 +1,453 @@ +commit a1aaf9f9080202f48570d3a207d0595db159f99c +Author: Pavel Kohout +Date: Tue Jan 13 00:00:00 2026 +0000 + + Fix symlink-following vulnerabilities (CWE-59) + + Multiple symlink-following vulnerabilities exist in OpenCryptoki that run + in privileged contexts. These allow a token-group user to redirect file + operations to arbitrary filesystem targets by planting symlinks in + group-writable token directories, resulting in privilege escalation or + data exposure. + + Affected components: + 1. pkcstok_admin: set_file_permissions() uses stat() which follows symlinks, + then applies chmod/chown to the symlink target. + 2. pkcstok_migrate: fopen() follows symlinks, then set_perm() modifies the + target permissions. + 3. loadsave.c: Multiple wrapper functions use fopen() followed by set_perm(). + 4. hsm_mk_change.c: hsm_mk_change_op_open() uses fopen() followed by + hsm_mk_change_op_set_perm(). + 5. pbkdf.c: fopen() followed by set_perms() in two locations. + + This fix: + - Introduces fopen_nofollow() helper in platform.h + - Checks for O_NOFOLLOW at compile time (not hardcoded per-platform) + - On platforms with O_NOFOLLOW: uses open(O_NOFOLLOW) + fdopen() for atomic + symlink rejection (race-condition free) + - On platforms without O_NOFOLLOW: falls back to lstat() + fopen() and emits + a compiler warning so the unsafe fallback doesn't go unnoticed + - Updates all affected wrapper functions to use fopen_nofollow() + - pkcstok_admin: Uses lstat() instead of stat() and skips symlinks + + Reported-by: Pavel Kohout, Aisle Research, www.aisle.com + Signed-off-by: Pavel Kohout + Signed-off-by: Ingo Franzki + +diff --git a/usr/lib/common/loadsave.c b/usr/lib/common/loadsave.c +index 18b8aa04..f9c0cc7f 100644 +--- a/usr/lib/common/loadsave.c ++++ b/usr/lib/common/loadsave.c +@@ -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, NULL) < 0) + return NULL; +- return fopen(buf, mode); ++ ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(buf, mode); ++ if (fp == NULL && errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", buf); ++ ++ return fp; + } + + static FILE *open_token_object_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, +@@ -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, NULL) < 0) + return NULL; +- return fopen(buf, mode); ++ ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(buf, mode); ++ if (fp == NULL && errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", buf); ++ ++ return fp; + } + + static FILE *open_token_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, +@@ -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, const char *mode) + { ++ FILE *fp; ++ + if (ock_snprintf(buf, buflen, "%s/" PK_LITE_NV, tokdata->data_store)) { + TRACE_ERROR("NVDAT.TOK file name buffer overflow\n"); + return NULL; + } +- return fopen(buf, mode); ++ ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(buf, mode); ++ if (fp == NULL && errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", buf); ++ ++ return fp; + } + + 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... + // +- fp = fopen(fname, "a"); ++ fp = fopen_nofollow(fname, "a"); + if (!fp) { +- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); ++ if (errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", fname); ++ else ++ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); + return CKR_FUNCTION_FAILED; + } + +@@ -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); + +- fp = fopen(fname, "r"); ++ fp = fopen_nofollow(fname, "r"); + if (!fp) { + // were really hosed here since the created + // did not occur +- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); ++ if (errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", fname); ++ else ++ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); + rc = CKR_FUNCTION_FAILED; + goto out_unlock; + } +@@ -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); + +- fp = fopen(fname, "r"); ++ fp = fopen_nofollow(fname, "r"); + if (!fp) { + // were really hosed here since the created + // did not occur +- TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); ++ if (errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", fname); ++ else ++ TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno)); + rc = CKR_FUNCTION_FAILED; + goto out_unlock; + } +diff --git a/usr/lib/common/platform.h b/usr/lib/common/platform.h +index 799821b5..51cc1c73 100644 +--- a/usr/lib/common/platform.h ++++ b/usr/lib/common/platform.h +@@ -7,7 +7,16 @@ + * found in the file LICENSE file or at + * https://opensource.org/licenses/cpl1.0.php + */ ++#ifndef PLATFORM_H ++#define PLATFORM_H ++ + #include ++#include ++#include ++#include ++#include ++#include ++#include + + #if defined(_AIX) + #include "aix/getopt.h" +@@ -30,10 +39,81 @@ + /* for htobexx, htolexx, bexxtoh and lexxtoh macros */ + #include + /* macros from bsdlog and friends */ +-#include + #include + + #define OCK_API_LIBNAME "libopencryptoki.so" + #define DYNLIB_LDFLAGS (RTLD_NOW) + + #endif /* _AIX */ ++ ++/* ++ * Check for O_NOFOLLOW support at compile time. ++ * If not available, fall back to lstat() + fopen() (has TOCTOU race). ++ */ ++#ifndef O_NOFOLLOW ++#define OCK_NO_O_NOFOLLOW 1 ++#warning "O_NOFOLLOW not supported, symlink protection uses racy lstat() fallback!" ++#endif ++ ++/* ++ * CWE-59 fix: Open file without following symlinks. ++ * ++ * On platforms with O_NOFOLLOW support: ++ * Uses open(O_NOFOLLOW) + fdopen() for atomic symlink rejection. ++ * ++ * On platforms without O_NOFOLLOW (e.g., older AIX): ++ * Falls back to lstat() + fopen(). This has a TOCTOU race condition, ++ * but still catches pre-planted symlinks which is the common attack ++ * scenario. Better than no protection at all. ++ * ++ * Returns NULL with errno=ELOOP if path is a symlink. ++ */ ++static inline FILE *fopen_nofollow(const char *path, const char *mode) ++{ ++#ifdef OCK_NO_O_NOFOLLOW ++ /* ++ * Fallback for platforms without O_NOFOLLOW: use lstat() check. ++ * This has a TOCTOU race but catches pre-planted symlinks. ++ */ ++ struct stat sb; ++ ++ if (lstat(path, &sb) == 0) { ++ if (S_ISLNK(sb.st_mode)) { ++ errno = ELOOP; ++ return NULL; ++ } ++ } ++ /* Note: if lstat fails (e.g., file doesn't exist for "w" mode), ++ * we proceed with fopen() which will handle the error appropriately */ ++ return fopen(path, mode); ++#else ++ /* Preferred: atomic symlink rejection via O_NOFOLLOW */ ++ int flags = O_NOFOLLOW; ++ int fd; ++ FILE *fp; ++ ++ /* Determine flags based on mode */ ++ if (mode[0] == 'r') { ++ flags |= (mode[1] == '+') ? O_RDWR : O_RDONLY; ++ } else if (mode[0] == 'w') { ++ flags |= O_CREAT | O_TRUNC | ((mode[1] == '+') ? O_RDWR : O_WRONLY); ++ } else if (mode[0] == 'a') { ++ flags |= O_CREAT | O_APPEND | ((mode[1] == '+') ? O_RDWR : O_WRONLY); ++ } else { ++ return NULL; ++ } ++ ++ fd = open(path, flags, 0600); ++ if (fd < 0) ++ return NULL; ++ ++ fp = fdopen(fd, mode); ++ if (fp == NULL) { ++ close(fd); ++ return NULL; ++ } ++ return fp; ++#endif ++} ++ ++#endif /* PLATFORM_H */ +diff --git a/usr/lib/hsm_mk_change/hsm_mk_change.c b/usr/lib/hsm_mk_change/hsm_mk_change.c +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, + + TRACE_DEVEL("file to open: %s mode: %s\n", hsm_mk_change_file, mode); + +- fp = fopen(hsm_mk_change_file, mode); ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(hsm_mk_change_file, mode); + if (fp == NULL) { +- TRACE_ERROR("%s fopen(%s, %s): %s\n", __func__, ++ if (errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", hsm_mk_change_file); ++ else ++ TRACE_ERROR("%s fopen(%s, %s): %s\n", __func__, + hsm_mk_change_file, mode, strerror(errno)); + } + +diff --git a/usr/lib/icsf_stdll/pbkdf.c b/usr/lib/icsf_stdll/pbkdf.c +index 47d1b97c..91230804 100644 +--- a/usr/lib/icsf_stdll/pbkdf.c ++++ b/usr/lib/icsf_stdll/pbkdf.c +@@ -26,6 +26,7 @@ + #include "h_extern.h" + #include "pbkdf.h" + #include "trace.h" ++#include "platform.h" + + + CK_RV get_randombytes(unsigned char *output, int bytes) +@@ -546,9 +547,13 @@ CK_RV secure_racf(STDLL_TokData_t *tokdata, + totallen = outputlen + AES_INIT_VECTOR_SIZE; + + snprintf(fname, sizeof(fname), "%s/%s/%s", CONFIG_PATH, tokname, RACFFILE); +- fp = fopen(fname, "w"); ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(fname, "w"); + if (!fp) { +- TRACE_ERROR("fopen failed: %s\n", strerror(errno)); ++ if (errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", fname); ++ else ++ TRACE_ERROR("fopen failed: %s\n", strerror(errno)); + return CKR_FUNCTION_FAILED; + } + +@@ -619,9 +624,13 @@ CK_RV secure_masterkey(STDLL_TokData_t *tokdata, + /* get the total length */ + totallen = outputlen + SALTSIZE; + +- fp = fopen(fname, "w"); ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ fp = fopen_nofollow(fname, "w"); + if (!fp) { +- TRACE_ERROR("fopen failed: %s\n", strerror(errno)); ++ if (errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", fname); ++ else ++ TRACE_ERROR("fopen failed: %s\n", strerror(errno)); + return CKR_FUNCTION_FAILED; + } + +diff --git a/usr/sbin/pkcstok_admin/pkcstok_admin.c b/usr/sbin/pkcstok_admin/pkcstok_admin.c +index 9912804e..d144cc04 100644 +--- a/usr/sbin/pkcstok_admin/pkcstok_admin.c ++++ b/usr/sbin/pkcstok_admin/pkcstok_admin.c +@@ -336,11 +336,18 @@ static int set_file_permissions(const char *fname, const struct group *group, + pr_verbose("Setting permissions for '%s' with group '%s'", fname, + group->gr_name); + +- if (stat(fname, &sb) != 0) { ++ /* CWE-59 fix: Use lstat to detect symlinks */ ++ if (lstat(fname, &sb) != 0) { + warnx("'%s' does not exist.", fname); + return -1; + } + ++ /* Only process regular files and directories (CWE-59 fix) */ ++ if (!S_ISREG(sb.st_mode) && !S_ISDIR(sb.st_mode)) { ++ warnx("Skipping '%s': not a regular file or directory.", fname); ++ return 0; ++ } ++ + if (sb.st_uid != 0) { + /* owner is not root */ + pwd = getpwuid(sb.st_uid); +diff --git a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c +index 12b605b5..9579e236 100644 +--- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c ++++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c +@@ -48,6 +48,7 @@ + #include "local_types.h" + #include "h_extern.h" + #include "slotmgr.h" // for ock_snprintf ++#include "platform.h" + + #define OCK_TOOL + #include "pkcs_utils.h" +@@ -77,9 +78,14 @@ static FILE *open_datastore_file(char *buf, size_t buflen, + TRACE_ERROR("Path overflow for datastore file %s\n", file); + return NULL; + } +- res = fopen(buf, mode); +- if (!res) +- TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno)); ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ res = fopen_nofollow(buf, mode); ++ if (!res) { ++ if (errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", buf); ++ else ++ TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno)); ++ } + return res; + } + +@@ -94,9 +100,14 @@ static FILE *open_tokenobject(char *buf, size_t buflen, + file, tokenobj); + return NULL; + } +- res = fopen(buf, mode); +- if (!res) +- TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno)); ++ /* CWE-59 fix: Use fopen_nofollow to prevent symlink attacks */ ++ res = fopen_nofollow(buf, mode); ++ if (!res) { ++ if (errno == ELOOP) ++ TRACE_ERROR("Refusing to follow symlink: %s\n", buf); ++ else ++ TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno)); ++ } + return res; + } + diff --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/SPECS/opencryptoki.spec b/SPECS/opencryptoki.spec index 2bb3efd..2d75653 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} +Version: 3.26.0 +Release: 2%{?dist} License: CPL-1.0 URL: https://github.com/opencryptoki/opencryptoki Source0: https://github.com/opencryptoki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz @@ -19,14 +19,8 @@ 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 +# CVE-3-2026-23893 +Patch100: opencryptoki-3.26.0-CVE-3-2026-23893.patch Requires(pre): coreutils Requires: (selinux-policy >= 38.1.14-1 if selinux-policy-targeted) @@ -413,6 +407,15 @@ fi %changelog +* 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 - Drop tier1 test as it mostly provides duplicate results