import CS opencryptoki-3.26.0-2.el9

This commit is contained in:
AlmaLinux RelEng Bot 2026-03-30 10:49:14 -04:00
parent e11bf47e77
commit 06bdf30491
7 changed files with 468 additions and 279 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/opencryptoki-3.25.0.tar.gz
SOURCES/opencryptoki-3.26.0.tar.gz

View File

@ -1 +1 @@
a52c4873734e8e68ae8d599e08d5a55c0b3459ad SOURCES/opencryptoki-3.25.0.tar.gz
c2e2f0fc220d106ece01dd4b4fd8091704cb8fac SOURCES/opencryptoki-3.26.0.tar.gz

View File

@ -1,43 +0,0 @@
commit 003d658322df316a352af591a3d059ca22fc40a3
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Mon Jul 21 11:02:42 2025 +0200
Fix covscan findings
Closes: https://github.com/opencryptoki/opencryptoki/issues/879
Reported-by: Than Ngo <than@redhat.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
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);

View File

@ -1,176 +0,0 @@
commit 144456ede9897662eed35ac8415d0ecb1c5907e3
Author: Ingo Franzki <ifranzki@linux.ibm.com>
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 <ifranzki@linux.ibm.com>
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 */

View File

@ -0,0 +1,453 @@
commit a1aaf9f9080202f48570d3a207d0595db159f99c
Author: Pavel Kohout <pavel@aisle.com>
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 <pavel@aisle.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
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 <dlfcn.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
#if defined(_AIX)
#include "aix/getopt.h"
@@ -30,10 +39,81 @@
/* for htobexx, htolexx, bexxtoh and lexxtoh macros */
#include <endian.h>
/* macros from bsdlog and friends */
-#include <stdio.h>
#include <err.h>
#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;
}

View File

@ -1,48 +0,0 @@
commit 8209874fc0ea78079aa21c386df0f385ee0e5dca
Author: Ingo Franzki <ifranzki@linux.ibm.com>
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 <ifranzki@linux.ibm.com>
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;
}

View File

@ -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 <than@redhat.com> - 3.26.0-2
- Resolves: RHEL-144821, CVE-2026-23893
* Wed Dec 17 2025 Than Ngo <than@redhat.com> - 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 <than@redhat.com> - 3.25.0-4
- Fix pkcsslotd fails to start in FIPS
- Drop tier1 test as it mostly provides duplicate results