diff --git a/.gitignore b/.gitignore index afd172af..6942eb1f 100644 --- a/.gitignore +++ b/.gitignore @@ -35,14 +35,12 @@ coverage.info cmake/wolfpkcs11Config.cmake cmake/wolfpkcs11Targets.cmake cmake/wolfpkcs11ConfigVersion.cmake -tests/pkcs11test -tests/pkcs11mtt -tests/pkcs11str -tests/object_id_uniqueness_test -tests/rsa_session_persistence_test -tests/debug_test -tests/token_path_test -tests/pkcs11v3test +# Test binaries and build artifacts +tests/* +!tests/*.c +!tests/*.h +!tests/*.am +!tests/README.md examples/add_aes_key examples/add_hmac_key examples/add_rsa_key @@ -53,16 +51,7 @@ examples/mech_info examples/obj_list examples/slot_info examples/token_info -store/wp11* -store/debug -store/empty_pin_test -store/object -store/pkcs11mtt -store/pkcs11test -store/pkcs11v3test -store/rsa -store/str -store/debug +store/* test/* *.gcda *.gcno @@ -73,18 +62,13 @@ add_cert_file .cache compile_commands.json -tests/wp11_rsakey_* -tests/wp11_dhkey_* -tests/wp11_ecckey_* -tests/wp11_symmkey_* -tests/wp11_token_* -tests/wp11_obj_* -tests/token_path_test -tests/rsa_session_persistence_test -tests/empty_pin_store_test IDE/VisualStudio/.vs doc/doxygen_warnings doc/html/ doc/refman.pdf + +AGENTS.md +CLAUDE.md +.clangd diff --git a/src/crypto.c b/src/crypto.c index 99e7492c..295a3a81 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -1868,6 +1868,12 @@ static CK_RV EncryptInit(CK_SESSION_HANDLE hSession, return ret; } + if (WP11_Session_IsOpCategoryActive(session, WP11_OP_ENCRYPT)) { + rv = CKR_OPERATION_ACTIVE; + WOLFPKCS11_LEAVE("C_EncryptInit", rv); + return rv; + } + type = WP11_Object_GetType(obj); switch (pMechanism->mechanism) { #ifndef NO_RSA @@ -2143,7 +2149,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pulEncryptedDataLen) { CK_RV rv; - int ret; + int ret = 0; WP11_Session* session; WP11_Object* obj = NULL; word32 encDataLen; @@ -2196,7 +2202,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, &encDataLen, obj, WP11_Session_GetSlot(session)); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; case CKM_RSA_PKCS: @@ -2215,7 +2221,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, pEncryptedData, &encDataLen, obj, WP11_Session_GetSlot(session)); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; #ifndef WC_NO_RSA_OAEP @@ -2237,7 +2243,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, pEncryptedData, &encDataLen, obj, session); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; #endif @@ -2261,7 +2267,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_AesCbc_Encrypt(pData, (int)ulDataLen, pEncryptedData, &encDataLen, session); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; case CKM_AES_CBC_PAD: @@ -2285,7 +2291,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_AesCbcPad_Encrypt(pData, (int)ulDataLen, pEncryptedData, &encDataLen, session); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; #endif @@ -2305,7 +2311,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_AesCtr_Do(pData, (word32)ulDataLen, pEncryptedData, &encDataLen, session); if (ret != 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; #endif @@ -2328,7 +2334,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_AesGcm_Encrypt(pData, (int)ulDataLen, pEncryptedData, &encDataLen, obj, session); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; #endif @@ -2351,7 +2357,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_AesCcm_Encrypt(pData, (int)ulDataLen, pEncryptedData, &encDataLen, obj, session); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; #endif @@ -2373,7 +2379,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_AesEcb_Encrypt(pData, (int)ulDataLen, pEncryptedData, &encDataLen, obj, session); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; #endif @@ -2393,7 +2399,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_AesCts_Encrypt(pData, (int)ulDataLen, pEncryptedData, &encDataLen, session); if (ret < 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; #endif @@ -2416,7 +2422,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_AesKeyWrap_Encrypt(pData, (word32)ulDataLen, pEncryptedData, &encDataLen, session); if (ret != 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; case CKM_AES_KEY_WRAP_PAD: { @@ -2437,8 +2443,10 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, return CKR_BUFFER_TOO_SMALL; paddedData = (byte*)XMALLOC(ulDataLen + padding, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (paddedData == NULL) + if (paddedData == NULL) { + WP11_Session_SetOpInitialized(session, 0); return CKR_DEVICE_MEMORY; + } XMEMCPY(paddedData, pData, ulDataLen); XMEMSET(paddedData + ulDataLen, padding, padding); @@ -2447,7 +2455,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, wc_ForceZero(paddedData, ulDataLen + padding); XFREE(paddedData, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ret != 0) - return CKR_FUNCTION_FAILED; + break; *pulEncryptedDataLen = encDataLen; break; } @@ -2458,9 +2466,13 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, (void)encDataLen; (void)ulDataLen; (void)pEncryptedData; + WP11_Session_SetOpInitialized(session, 0); return CKR_MECHANISM_INVALID; } + WP11_Session_SetOpInitialized(session, 0); + if (ret != 0) + return CKR_FUNCTION_FAILED; return CKR_OK; } @@ -2723,6 +2735,7 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, encPartLen = WP11_AesCbc_PartLen(session); if (encPartLen != 0) { WP11_AesCbc_EncryptFinal(session); + WP11_Session_SetOpInitialized(session, 0); return CKR_DATA_LEN_RANGE; } *pulLastEncryptedPartLen = 0; @@ -2730,8 +2743,10 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, return CKR_OK; ret = WP11_AesCbc_EncryptFinal(session); - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } break; case CKM_AES_CBC_PAD: if (!WP11_Session_IsOpInitialized(session, @@ -2749,8 +2764,10 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, ret = WP11_AesCbcPad_EncryptFinal(pLastEncryptedPart, &encPartLen, session); - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } break; #endif #ifdef HAVE_AESCTR @@ -2764,8 +2781,10 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, } ret = WP11_AesCtr_Final(session); - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } *pulLastEncryptedPartLen = 0; break; #endif @@ -2784,8 +2803,10 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, ret = WP11_AesGcm_EncryptFinal(pLastEncryptedPart, &encPartLen, session); - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } *pulLastEncryptedPartLen = encPartLen; break; #endif @@ -2804,8 +2825,10 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, session); if (ret == BUFFER_E) return CKR_BUFFER_TOO_SMALL; - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } *pulLastEncryptedPartLen = encPartLen; break; #endif @@ -2814,9 +2837,11 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, (void)encPartLen; (void)ret; (void)pLastEncryptedPart; + WP11_Session_SetOpInitialized(session, 0); return CKR_MECHANISM_INVALID; } + WP11_Session_SetOpInitialized(session, 0); return CKR_OK; } @@ -2858,6 +2883,12 @@ static CK_RV DecryptInit(CK_SESSION_HANDLE hSession, return ret; } + if (WP11_Session_IsOpCategoryActive(session, WP11_OP_DECRYPT)) { + rv = CKR_OPERATION_ACTIVE; + WOLFPKCS11_LEAVE("C_DecryptInit", rv); + return rv; + } + type = WP11_Object_GetType(obj); switch (pMechanism->mechanism) { #ifndef NO_RSA @@ -3125,7 +3156,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { - int ret; + int ret = 0; WP11_Session* session; WP11_Object* obj = NULL; word32 decDataLen; @@ -3173,7 +3204,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, &decDataLen, obj, WP11_Session_GetSlot(session)); if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; case CKM_RSA_PKCS: @@ -3193,7 +3224,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, &decDataLen, obj, WP11_Session_GetSlot(session)); if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; #ifndef WC_NO_RSA_OAEP @@ -3215,7 +3246,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, (int)ulEncryptedDataLen, pData, &decDataLen, obj, session); if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; #endif @@ -3239,7 +3270,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, ret = WP11_AesCbc_Decrypt(pEncryptedData, (int)ulEncryptedDataLen, pData, &decDataLen, session); if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; case CKM_AES_CBC_PAD: @@ -3260,7 +3291,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, (int)ulEncryptedDataLen, pData, &decDataLen, session); if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; #endif @@ -3280,7 +3311,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, ret = WP11_AesCtr_Do(pEncryptedData, (word32)ulEncryptedDataLen, pData, &decDataLen, session); if (ret != 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; #endif @@ -3303,7 +3334,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, ret = WP11_AesGcm_Decrypt(pEncryptedData, (int)ulEncryptedDataLen, pData, &decDataLen, obj, session); if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; #endif @@ -3326,7 +3357,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, ret = WP11_AesCcm_Decrypt(pEncryptedData, (int)ulEncryptedDataLen, pData, &decDataLen, obj, session); if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; #endif @@ -3348,7 +3379,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, ret = WP11_AesEcb_Decrypt(pEncryptedData, (int)ulEncryptedDataLen, pData, &decDataLen, obj, session); if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; #endif @@ -3370,7 +3401,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, if (ret == BUFFER_E) return CKR_BUFFER_TOO_SMALL; if (ret < 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; *pulDataLen = decDataLen; break; #endif @@ -3395,7 +3426,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, ret = WP11_AesKeyWrap_Decrypt(pEncryptedData, (word32)ulEncryptedDataLen, pData, &decDataLen, session); if (ret != 0) - return CKR_ENCRYPTED_DATA_INVALID; + break; if (mechanism == CKM_AES_KEY_WRAP_PAD) { int i; byte padValue = pData[decDataLen - 1]; @@ -3422,8 +3453,10 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, (unsigned int)padValue); } - if (badPad != 0) - return CKR_ENCRYPTED_DATA_INVALID; + if (badPad != 0) { + ret = -1; + break; + } decDataLen -= padValue; } *pulDataLen = decDataLen; @@ -3435,9 +3468,13 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, (void)ret; (void)ulEncryptedDataLen; (void)pData; + WP11_Session_SetOpInitialized(session, 0); return CKR_MECHANISM_INVALID; } + WP11_Session_SetOpInitialized(session, 0); + if (ret != 0) + return CKR_ENCRYPTED_DATA_INVALID; return CKR_OK; } @@ -3681,6 +3718,7 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, decPartLen = WP11_AesCbc_PartLen(session); if (decPartLen != 0) { WP11_AesCbc_DecryptFinal(session); + WP11_Session_SetOpInitialized(session, 0); return CKR_DATA_LEN_RANGE; } *pulLastPartLen = 0; @@ -3688,8 +3726,10 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, return CKR_OK; ret = WP11_AesCbc_DecryptFinal(session); - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } break; case CKM_AES_CBC_PAD: if (!WP11_Session_IsOpInitialized(session, @@ -3700,6 +3740,7 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, decPartLen = WP11_AesCbc_PartLen(session); if (decPartLen != 16) { WP11_AesCbc_DecryptFinal(session); + WP11_Session_SetOpInitialized(session, 0); return CKR_DATA_LEN_RANGE; } *pulLastPartLen = 15; @@ -3707,8 +3748,10 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, return CKR_OK; ret = WP11_AesCbcPad_DecryptFinal(pLastPart, &decPartLen, session); - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } *pulLastPartLen = decPartLen; break; #endif @@ -3723,8 +3766,10 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, } ret = WP11_AesCtr_Final(session); - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } *pulLastPartLen = 0; break; #endif @@ -3734,8 +3779,10 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, return CKR_OPERATION_NOT_INITIALIZED; if (WP11_AesGcm_EncDataLen(session) < - WP11_AesGcm_GetTagBits(session) / 8) + WP11_AesGcm_GetTagBits(session) / 8) { + WP11_Session_SetOpInitialized(session, 0); return CKR_ENCRYPTED_DATA_LEN_RANGE; + } decPartLen = WP11_AesGcm_EncDataLen(session) - WP11_AesGcm_GetTagBits(session) / 8; if (pLastPart == NULL) { @@ -3747,8 +3794,10 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, ret = WP11_AesGcm_DecryptFinal(pLastPart, &decPartLen, obj, session); - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } *pulLastPartLen = decPartLen; break; #endif @@ -3766,8 +3815,10 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, ret = WP11_AesCts_DecryptFinal(pLastPart, &decPartLen, session); if (ret == BUFFER_E) return CKR_BUFFER_TOO_SMALL; - if (ret < 0) + if (ret < 0) { + WP11_Session_SetOpInitialized(session, 0); return CKR_FUNCTION_FAILED; + } *pulLastPartLen = decPartLen; break; #endif @@ -3776,9 +3827,11 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, (void)decPartLen; (void)ret; (void)pLastPart; + WP11_Session_SetOpInitialized(session, 0); return CKR_MECHANISM_INVALID; } + WP11_Session_SetOpInitialized(session, 0); return CKR_OK; } @@ -3831,6 +3884,11 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, WOLFPKCS11_LEAVE("C_DigestInit", rv); return rv; } + if (WP11_Session_IsOpCategoryActive(session, WP11_OP_DIGEST)) { + rv = CKR_OPERATION_ACTIVE; + WOLFPKCS11_LEAVE("C_DigestInit", rv); + return rv; + } init = WP11_INIT_DIGEST; ret = WP11_Digest_Init(pMechanism->mechanism, session); @@ -3892,7 +3950,13 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, session); *pulDigestLen = hashLen; - return ret; + if (ret != BUFFER_E && (pDigest != NULL || ret != 0)) + WP11_Session_SetOpInitialized(session, 0); + if (ret == BUFFER_E) + return CKR_BUFFER_TOO_SMALL; + if (ret != 0) + return CKR_FUNCTION_FAILED; + return CKR_OK; } /** @@ -4027,7 +4091,13 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, ret = WP11_Digest_Final(pDigest, &hashLen, session); *pulDigestLen = hashLen; - return ret; + if (ret != BUFFER_E && (pDigest != NULL || ret != 0)) + WP11_Session_SetOpInitialized(session, 0); + if (ret == BUFFER_E) + return CKR_BUFFER_TOO_SMALL; + if (ret != 0) + return CKR_FUNCTION_FAILED; + return CKR_OK; } #ifdef WOLFSSL_HAVE_PRF @@ -4214,6 +4284,11 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, return CKR_MECHANISM_PARAM_INVALID; } + if (WP11_Session_IsOpCategoryActive(session, WP11_OP_SIGN)) { + rv = CKR_OPERATION_ACTIVE; + WOLFPKCS11_LEAVE("C_SignInit", rv); + return rv; + } /* The private key is pre-provisioned so no object to set. */ init = WP11_INIT_ECDSA_SIGN; WP11_Session_SetMechanism(session, pMechanism->mechanism); @@ -4231,6 +4306,12 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, if (ret != CKR_OK) return ret; + if (WP11_Session_IsOpCategoryActive(session, WP11_OP_SIGN)) { + rv = CKR_OPERATION_ACTIVE; + WOLFPKCS11_LEAVE("C_SignInit", rv); + return rv; + } + type = WP11_Object_GetType(obj); init = GetInitValue(pMechanism->mechanism); switch (pMechanism->mechanism) { @@ -4606,11 +4687,14 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, if (wc_Hash(hash_type, pData, (word32)ulDataLen, digest, sizeof(digest)) != 0 || (dataSz = wc_HashGetDigestSize(hash_type)) < 0) { - return CKR_FUNCTION_FAILED; + ret = -1; + break; } oid = wc_HashGetOID(hash_type); - if (oid < 0) - return CKR_FUNCTION_FAILED; + if (oid < 0) { + ret = -1; + break; + } ret = wc_EncodeSignature(digest, digest, dataSz, oid); @@ -4619,7 +4703,8 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, dataSz = ret; } else { - return CKR_FUNCTION_FAILED; + ret = -1; + break; } } @@ -4671,7 +4756,8 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, if (wc_Hash(hash_type, pData, (word32)ulDataLen, digest, sizeof(digest)) != 0 || (dataSz = wc_HashGetDigestSize(hash_type)) < 0) { - return CKR_FUNCTION_FAILED; + ret = -1; + break; } data = digest; } @@ -4722,7 +4808,8 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, if (wc_Hash(hash_type, pData, (word32)ulDataLen, digest, sizeof(digest)) != 0 || (dataSz = wc_HashGetDigestSize(hash_type)) < 0) { - return CKR_FUNCTION_FAILED; + ret = -1; + break; } data = digest; } @@ -4847,8 +4934,10 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, (void)sigLen; (void)ulDataLen; (void)pSignature; + WP11_Session_SetOpInitialized(session, 0); return CKR_MECHANISM_INVALID; } + WP11_Session_SetOpInitialized(session, 0); if (ret < 0) return CKR_FUNCTION_FAILED; @@ -5109,12 +5198,19 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, if (!WP11_Session_IsOpInitialized(session, WP11_INIT_TLS_MAC_SIGN)) return CKR_OPERATION_NOT_INITIALIZED; + if (pSignature == NULL) { + *pulSignatureLen = (CK_ULONG)WP11_TLS_MAC_get_len(session); + return CKR_OK; + } + WP11_Session_GetData(session, &data, &dataLen); ret = (int)C_Sign(hSession, data, dataLen, pSignature, pulSignatureLen); WP11_Session_FreeData(session); - if (ret != CKR_OK) + if (ret != CKR_OK) { + WP11_Session_SetOpInitialized(session, 0); return ret; + } break; } @@ -5122,8 +5218,10 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, default: (void)sigLen; (void)pSignature; + WP11_Session_SetOpInitialized(session, 0); return CKR_MECHANISM_INVALID; } + WP11_Session_SetOpInitialized(session, 0); if (ret < 0) return CKR_FUNCTION_FAILED; @@ -5305,6 +5403,12 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, if (ret != CKR_OK) return ret; + if (WP11_Session_IsOpCategoryActive(session, WP11_OP_VERIFY)) { + rv = CKR_OPERATION_ACTIVE; + WOLFPKCS11_LEAVE("C_VerifyInit", rv); + return rv; + } + type = WP11_Object_GetType(obj); init = GetInitValue(pMechanism->mechanism); switch (pMechanism->mechanism) { @@ -5656,11 +5760,14 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, if (wc_Hash(hash_type, pData, (word32)ulDataLen, digest, sizeof(digest)) != 0 || (dataSz = wc_HashGetDigestSize(hash_type)) < 0) { - return CKR_FUNCTION_FAILED; + ret = -1; + break; } oid = wc_HashGetOID(hash_type); - if (oid < 0) - return CKR_FUNCTION_FAILED; + if (oid < 0) { + ret = -1; + break; + } ret = wc_EncodeSignature(digest, digest, dataSz, oid); @@ -5669,7 +5776,8 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, dataSz = ret; } else { - return CKR_FUNCTION_FAILED; + ret = -1; + break; } } @@ -5710,7 +5818,8 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, if (wc_Hash(hash_type, pData, (word32)ulDataLen, digest, sizeof(digest)) != 0 || (dataSz = wc_HashGetDigestSize(hash_type)) < 0) { - return CKR_FUNCTION_FAILED; + ret = -1; + break; } data = digest; } @@ -5752,7 +5861,8 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, if (wc_Hash(hash_type, pData, (word32)ulDataLen, digest, sizeof(digest)) != 0 || (dataSz = wc_HashGetDigestSize(hash_type)) < 0) { - return CKR_FUNCTION_FAILED; + ret = -1; + break; } data = digest; } @@ -5770,6 +5880,10 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, ret = WP11_Mldsa_Verify(pSignature, (int)ulSignatureLen, pData, (int)ulDataLen, &stat, obj, session); + if (ret < 0) { + stat = 0; + ret = 0; + } break; #endif #ifndef NO_HMAC @@ -5844,11 +5958,13 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, default: (void)ulDataLen; (void)ulSignatureLen; + WP11_Session_SetOpInitialized(session, 0); return CKR_MECHANISM_INVALID; } + WP11_Session_SetOpInitialized(session, 0); if (ret < 0) return CKR_FUNCTION_FAILED; - if (!stat) + if (ret != 0 || !stat) return CKR_SIGNATURE_INVALID; return CKR_OK; @@ -6082,11 +6198,13 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, #endif default: (void)ulSignatureLen; + WP11_Session_SetOpInitialized(session, 0); return CKR_MECHANISM_INVALID; } + WP11_Session_SetOpInitialized(session, 0); if (ret < 0) return CKR_FUNCTION_FAILED; - if (!stat) + if (ret != 0 || !stat) return CKR_SIGNATURE_INVALID; return CKR_OK; @@ -6174,8 +6292,10 @@ CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, if (ret != CKR_OK) return ret; - if (WP11_Session_IsOpInitialized(session, init)) { - return CKR_OPERATION_ACTIVE; + if (WP11_Session_IsOpCategoryActive(session, WP11_OP_VERIFY)) { + rv = CKR_OPERATION_ACTIVE; + WOLFPKCS11_LEAVE("C_VerifyRecoverInit", rv); + return rv; } WP11_Session_SetMechanism(session, pMechanism->mechanism); @@ -6276,6 +6396,7 @@ CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, ret = WP11_Rsa_Verify_Recover(mechanism, pSignature, (word32)ulSignatureLen, pData, pulDataLen, obj); + WP11_Session_SetOpInitialized(session, 0); if (ret != CKR_OK) { return ret; } diff --git a/src/internal.c b/src/internal.c index 97b17eb9..9907f2e0 100644 --- a/src/internal.c +++ b/src/internal.c @@ -954,6 +954,8 @@ static void wp11_Session_Final(WP11_Session* session) } #endif #endif + /* Clear any remaining active operation state not handled above. */ + session->init = 0; } #ifndef WOLFPKCS11_NO_STORE @@ -7145,6 +7147,91 @@ int WP11_Session_IsOpInitialized(WP11_Session* session, int init) return (session->init & ~WP11_INIT_DIGEST_MASK) == init; } +/** + * Get the operation category for an init value. + * + * @param init [in] Init value (with digest bits masked out). + * @return Operation category (WP11_OP_*), or -1 if unknown. + */ +static int wp11_init_get_op_category(int init) +{ + switch (init) { + case WP11_INIT_AES_CBC_ENC: + case WP11_INIT_AES_GCM_ENC: + case WP11_INIT_AES_CBC_PAD_ENC: + case WP11_INIT_AES_CCM_ENC: + case WP11_INIT_AES_ECB_ENC: + case WP11_INIT_AES_CTS_ENC: + case WP11_INIT_AES_CTR_ENC: + case WP11_INIT_RSA_X_509_ENC: + case WP11_INIT_RSA_PKCS_ENC: + case WP11_INIT_RSA_PKCS_OAEP_ENC: + case WP11_INIT_AES_KEYWRAP_ENC: + return WP11_OP_ENCRYPT; + + case WP11_INIT_AES_CBC_DEC: + case WP11_INIT_AES_GCM_DEC: + case WP11_INIT_AES_CBC_PAD_DEC: + case WP11_INIT_AES_CCM_DEC: + case WP11_INIT_AES_ECB_DEC: + case WP11_INIT_AES_CTS_DEC: + case WP11_INIT_AES_CTR_DEC: + case WP11_INIT_RSA_X_509_DEC: + case WP11_INIT_RSA_PKCS_DEC: + case WP11_INIT_RSA_PKCS_OAEP_DEC: + case WP11_INIT_AES_KEYWRAP_DEC: + return WP11_OP_DECRYPT; + + case WP11_INIT_DIGEST: + return WP11_OP_DIGEST; + + case WP11_INIT_HMAC_SIGN: + case WP11_INIT_RSA_PKCS_SIGN: + case WP11_INIT_RSA_PKCS_PSS_SIGN: + case WP11_INIT_RSA_X_509_SIGN: + case WP11_INIT_ECDSA_SIGN: + case WP11_INIT_AES_CMAC_SIGN: + case WP11_INIT_TLS_MAC_SIGN: + case WP11_INIT_MLDSA_SIGN: + return WP11_OP_SIGN; + + case WP11_INIT_HMAC_VERIFY: + case WP11_INIT_RSA_PKCS_VERIFY: + case WP11_INIT_RSA_PKCS_PSS_VERIFY: + case WP11_INIT_RSA_X_509_VERIFY: + case WP11_INIT_RSA_PKCS_VERIFY_RECOVER: + case WP11_INIT_RSA_X_509_VERIFY_RECOVER: + case WP11_INIT_ECDSA_VERIFY: + case WP11_INIT_AES_CMAC_VERIFY: + case WP11_INIT_TLS_MAC_VERIFY: + case WP11_INIT_MLDSA_VERIFY: + return WP11_OP_VERIFY; + + default: + return -1; + } +} + +/** + * Check whether the session has an active operation of the given category. + * Per PKCS#11 spec, only operations of the same type block re-initialization. + * + * @param session [in] Session object. + * @param opCategory [in] Operation category (WP11_OP_*). + * @return 1 when an operation of the same category is active. + * 0 otherwise. + */ +int WP11_Session_IsOpCategoryActive(WP11_Session* session, int opCategory) +{ + int currentInit; + + if (session->init == 0) + return 0; + + currentInit = session->init & ~WP11_INIT_DIGEST_MASK; + return wp11_init_get_op_category(currentInit) == opCategory; +} + int WP11_Session_UpdateData(WP11_Session *session, byte *data, word32 dataLen) { int ret = 0; @@ -8764,10 +8851,12 @@ int WP11_Object_SetMldsaKey(WP11_Object* object, unsigned char** data, if (seedUsed == 0) { /* Import given public/private key data */ if (object->objClass == CKO_PUBLIC_KEY) { - ret = wc_MlDsaKey_ImportPubRaw(key, data[2], len[2]); + ret = wc_MlDsaKey_ImportPubRaw(key, data[2], + (word32)len[2]); } else { - ret = wc_MlDsaKey_ImportPrivRaw(key, data[2], len[2]); + ret = wc_MlDsaKey_ImportPrivRaw(key, data[2], + (word32)len[2]); } } else { @@ -14802,6 +14891,8 @@ int WP11_SetOperationState(WP11_Session* session, unsigned char* stateData, hashAlg = &session->params.digest.hash.alg; #endif + session->init = WP11_INIT_DIGEST; + switch (session->mechanism) { #ifndef NO_MD5 case CKM_MD5: diff --git a/tests/include.am b/tests/include.am index 725c474c..6cf5eb1f 100644 --- a/tests/include.am +++ b/tests/include.am @@ -56,6 +56,11 @@ noinst_PROGRAMS += tests/ecb_check_value_error_test tests_ecb_check_value_error_test_SOURCES = tests/ecb_check_value_error_test.c tests_ecb_check_value_error_test_LDADD = +check_PROGRAMS += tests/operation_active_test +noinst_PROGRAMS += tests/operation_active_test +tests_operation_active_test_SOURCES = tests/operation_active_test.c +tests_operation_active_test_LDADD = + check_PROGRAMS += tests/pkcs11v3test noinst_PROGRAMS += tests/pkcs11v3test tests_pkcs11v3test_SOURCES = tests/pkcs11v3test.c @@ -73,6 +78,7 @@ tests_empty_pin_store_test_LDADD += src/libwolfpkcs11.la tests_find_objects_null_template_test_LDADD += src/libwolfpkcs11.la tests_aes_cbc_pad_padding_test_LDADD += src/libwolfpkcs11.la tests_ecb_check_value_error_test_LDADD += src/libwolfpkcs11.la +tests_operation_active_test_LDADD += src/libwolfpkcs11.la tests_pkcs11v3test_LDADD += src/libwolfpkcs11.la else tests_object_id_uniqueness_test_LDADD += src/libwolfpkcs11.la @@ -80,6 +86,7 @@ tests_empty_pin_store_test_LDADD += src/libwolfpkcs11.la tests_find_objects_null_template_test_LDADD += src/libwolfpkcs11.la tests_aes_cbc_pad_padding_test_LDADD += src/libwolfpkcs11.la tests_ecb_check_value_error_test_LDADD += src/libwolfpkcs11.la +tests_operation_active_test_LDADD += src/libwolfpkcs11.la endif EXTRA_DIST += tests/unit.h \ diff --git a/tests/operation_active_test.c b/tests/operation_active_test.c new file mode 100644 index 00000000..94216013 --- /dev/null +++ b/tests/operation_active_test.c @@ -0,0 +1,790 @@ +/* operation_active_test.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfPKCS11. + * + * wolfPKCS11 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfPKCS11 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + * + * Test for bug #1616: C_EncryptInit, C_DecryptInit, C_DigestInit, C_SignInit, + * and C_VerifyInit must return CKR_OPERATION_ACTIVE when an operation of the + * same type is already active on the session. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include + +#ifndef WOLFPKCS11_USER_SETTINGS + #include +#endif +#include + +#ifndef HAVE_PKCS11_STATIC +#include +#endif + +#include "testdata.h" + +#if !defined(NO_AES) && !defined(NO_AES_CBC) + +#define OP_ACTIVE_TEST_DIR "./store/operation_active_test" +#define WOLFPKCS11_TOKEN_FILENAME "wp11_token_0000000000000001" + +static int test_passed = 0; +static int test_failed = 0; + +#define CHECK_CKR(rv, op, expected) do { \ + if (rv != expected) { \ + fprintf(stderr, "FAIL: %s: expected %ld, got %ld\n", op, (long)expected, (long)rv); \ + test_failed++; \ + result = -1; \ + goto cleanup; \ + } else { \ + printf("PASS: %s\n", op); \ + test_passed++; \ + } \ +} while(0) + +#ifndef HAVE_PKCS11_STATIC +static void* dlib; +#endif +static CK_FUNCTION_LIST* funcList; +static CK_SLOT_ID slot = 0; +static const char* tokenName = "wolfpkcs11"; +static byte* soPin = (byte*)"password123456"; +static int soPinLen = 14; +static byte* userPin = (byte*)"someUserPin"; +static int userPinLen = 11; + +static CK_OBJECT_CLASS secretKeyClass = CKO_SECRET_KEY; +static CK_BBOOL ckTrue = CK_TRUE; +static CK_KEY_TYPE aesKeyType = CKK_AES; +#ifndef NO_HMAC +static CK_KEY_TYPE genericKeyType = CKK_GENERIC_SECRET; +#endif + +static CK_RV pkcs11_init(void) +{ + CK_RV ret; + CK_C_INITIALIZE_ARGS args; + CK_INFO info; + CK_SLOT_ID slotList[16]; + CK_ULONG slotCount = sizeof(slotList) / sizeof(slotList[0]); + +#ifndef HAVE_PKCS11_STATIC + CK_C_GetFunctionList func; + + dlib = dlopen(WOLFPKCS11_DLL_FILENAME, RTLD_NOW | RTLD_LOCAL); + if (dlib == NULL) { + fprintf(stderr, "dlopen error: %s\n", dlerror()); + return -1; + } + + func = (CK_C_GetFunctionList)dlsym(dlib, "C_GetFunctionList"); + if (func == NULL) { + fprintf(stderr, "Failed to get function list function\n"); + dlclose(dlib); + return -1; + } + + ret = func(&funcList); + if (ret != CKR_OK) { + fprintf(stderr, "Failed to get function list: 0x%lx\n", + (unsigned long)ret); + dlclose(dlib); + return ret; + } +#else + ret = C_GetFunctionList(&funcList); + if (ret != CKR_OK) { + fprintf(stderr, "Failed to get function list: 0x%lx\n", + (unsigned long)ret); + return ret; + } +#endif + + XMEMSET(&args, 0, sizeof(args)); + args.flags = CKF_OS_LOCKING_OK; + ret = funcList->C_Initialize(&args); + if (ret != CKR_OK) + return ret; + + ret = funcList->C_GetInfo(&info); + if (ret != CKR_OK) + return ret; + + ret = funcList->C_GetSlotList(CK_TRUE, slotList, &slotCount); + if (ret != CKR_OK) + return ret; + + if (slotCount > 0) { + slot = slotList[0]; + } else { + fprintf(stderr, "No slots available\n"); + return CKR_GENERAL_ERROR; + } + + return ret; +} + +static CK_RV pkcs11_final(void) +{ + if (funcList != NULL) { + funcList->C_Finalize(NULL); + funcList = NULL; + } +#ifndef HAVE_PKCS11_STATIC + if (dlib) { + dlclose(dlib); + dlib = NULL; + } +#endif + return CKR_OK; +} + +static CK_RV pkcs11_init_token(void) +{ + unsigned char label[32]; + + XMEMSET(label, ' ', sizeof(label)); + XMEMCPY(label, tokenName, XSTRLEN(tokenName)); + + return funcList->C_InitToken(slot, soPin, soPinLen, label); +} + +static CK_RV pkcs11_open_session(CK_SESSION_HANDLE* session) +{ + CK_RV ret; + int sessFlags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + + ret = funcList->C_OpenSession(slot, sessFlags, NULL, NULL, session); + if (ret != CKR_OK) + return ret; + + ret = funcList->C_Login(*session, CKU_USER, userPin, userPinLen); + if (ret != CKR_OK) { + funcList->C_CloseSession(*session); + return ret; + } + + return CKR_OK; +} + +static CK_RV pkcs11_close_session(CK_SESSION_HANDLE session) +{ + funcList->C_Logout(session); + return funcList->C_CloseSession(session); +} + +static void cleanup_test_files(const char* dir) +{ + char filepath[512]; + + snprintf(filepath, sizeof(filepath), "%s" PATH_SEP "%s", dir, + WOLFPKCS11_TOKEN_FILENAME); + (void)remove(filepath); +} + +static CK_RV create_aes_128_key(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE* key) +{ + CK_ATTRIBUTE tmpl[] = { + { CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) }, + { CKA_KEY_TYPE, &aesKeyType, sizeof(aesKeyType) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE, aes_128_key, sizeof(aes_128_key) }, + { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + + return funcList->C_CreateObject(session, tmpl, tmplCnt, key); +} + +#ifndef NO_HMAC +static CK_RV create_hmac_key(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE* key) +{ + CK_ATTRIBUTE tmpl[] = { + { CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) }, + { CKA_KEY_TYPE, &genericKeyType, sizeof(genericKeyType) }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE, (void*)hmac_key, sizeof(hmac_key) }, + { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + + return funcList->C_CreateObject(session, tmpl, tmplCnt, key); +} +#endif /* !NO_HMAC */ + +/* + * C_EncryptInit called twice without completing the operation. + * Second call must return CKR_OPERATION_ACTIVE. + */ +static int test_encrypt_init_double(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE aesKey) +{ + CK_RV ret; + CK_MECHANISM mech; + byte iv[16]; + byte buf[16]; + CK_ULONG bufSz; + int result = 0; + + XMEMSET(iv, 0, sizeof(iv)); + + mech.mechanism = CKM_AES_CBC; + mech.pParameter = iv; + mech.ulParameterLen = sizeof(iv); + + /* First init should succeed */ + ret = funcList->C_EncryptInit(session, &mech, aesKey); + CHECK_CKR(ret, "EncryptInit double: first C_EncryptInit", CKR_OK); + + /* Second init should return CKR_OPERATION_ACTIVE */ + ret = funcList->C_EncryptInit(session, &mech, aesKey); + CHECK_CKR(ret, "EncryptInit double: second C_EncryptInit", + CKR_OPERATION_ACTIVE); + +cleanup: + /* Clean up active operation */ + bufSz = sizeof(buf); + XMEMSET(buf, 0, sizeof(buf)); + (void)funcList->C_Encrypt(session, buf, sizeof(buf), buf, &bufSz); + return result; +} + +/* + * After a rejected second C_EncryptInit, the first operation must + * still be usable. + */ +static int test_encrypt_survives_rejected_reinit(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE aesKey) +{ + CK_RV ret; + CK_MECHANISM mech; + byte iv[16]; + byte plaintext[16]; + byte ciphertext[16]; + CK_ULONG ciphertextLen; + int result = 0; + + XMEMSET(iv, 0, sizeof(iv)); + XMEMSET(plaintext, 0xAA, sizeof(plaintext)); + + mech.mechanism = CKM_AES_CBC; + mech.pParameter = iv; + mech.ulParameterLen = sizeof(iv); + + /* First init should succeed */ + ret = funcList->C_EncryptInit(session, &mech, aesKey); + CHECK_CKR(ret, "Encrypt survives: first C_EncryptInit", CKR_OK); + + /* Second init should be rejected */ + ret = funcList->C_EncryptInit(session, &mech, aesKey); + CHECK_CKR(ret, "Encrypt survives: second C_EncryptInit", + CKR_OPERATION_ACTIVE); + + /* First operation should still complete successfully */ + ciphertextLen = sizeof(ciphertext); + ret = funcList->C_Encrypt(session, plaintext, sizeof(plaintext), + ciphertext, &ciphertextLen); + CHECK_CKR(ret, "Encrypt survives: C_Encrypt after rejected reinit", + CKR_OK); + +cleanup: + return result; +} + +#ifdef HAVE_AESECB +/* + * C_EncryptInit with AES-CBC active, then C_EncryptInit with AES-ECB. + * Cross-mechanism double init must return CKR_OPERATION_ACTIVE. + */ +static int test_encrypt_cross_mechanism(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE aesKey) +{ + CK_RV ret; + CK_MECHANISM mechCbc, mechEcb; + byte iv[16]; + byte buf[16]; + CK_ULONG bufSz; + int result = 0; + + XMEMSET(iv, 0, sizeof(iv)); + + mechCbc.mechanism = CKM_AES_CBC; + mechCbc.pParameter = iv; + mechCbc.ulParameterLen = sizeof(iv); + + mechEcb.mechanism = CKM_AES_ECB; + mechEcb.pParameter = NULL; + mechEcb.ulParameterLen = 0; + + /* Init with AES-CBC */ + ret = funcList->C_EncryptInit(session, &mechCbc, aesKey); + CHECK_CKR(ret, "Cross-mech encrypt: first C_EncryptInit (CBC)", CKR_OK); + + /* Init with AES-ECB must fail */ + ret = funcList->C_EncryptInit(session, &mechEcb, aesKey); + CHECK_CKR(ret, "Cross-mech encrypt: second C_EncryptInit (ECB)", + CKR_OPERATION_ACTIVE); + +cleanup: + /* Clean up active operation */ + bufSz = sizeof(buf); + XMEMSET(buf, 0, sizeof(buf)); + (void)funcList->C_Encrypt(session, buf, sizeof(buf), buf, &bufSz); + return result; +} +#endif /* HAVE_AESECB */ + +/* + * C_DecryptInit called twice without completing the operation. + * Second call must return CKR_OPERATION_ACTIVE. + */ +static int test_decrypt_init_double(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE aesKey) +{ + CK_RV ret; + CK_MECHANISM mech; + byte iv[16]; + byte buf[16]; + CK_ULONG bufSz; + int result = 0; + + XMEMSET(iv, 0, sizeof(iv)); + + mech.mechanism = CKM_AES_CBC; + mech.pParameter = iv; + mech.ulParameterLen = sizeof(iv); + + ret = funcList->C_DecryptInit(session, &mech, aesKey); + CHECK_CKR(ret, "DecryptInit double: first C_DecryptInit", CKR_OK); + + ret = funcList->C_DecryptInit(session, &mech, aesKey); + CHECK_CKR(ret, "DecryptInit double: second C_DecryptInit", + CKR_OPERATION_ACTIVE); + +cleanup: + bufSz = sizeof(buf); + XMEMSET(buf, 0, sizeof(buf)); + (void)funcList->C_Decrypt(session, buf, sizeof(buf), buf, &bufSz); + return result; +} + +/* + * C_DigestInit called twice without completing the operation. + * Second call must return CKR_OPERATION_ACTIVE. + */ +static int test_digest_init_double(CK_SESSION_HANDLE session) +{ + CK_RV ret; + CK_MECHANISM mech; + byte buf[32]; + CK_ULONG bufSz; + int result = 0; + + mech.mechanism = CKM_SHA256; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + ret = funcList->C_DigestInit(session, &mech); + CHECK_CKR(ret, "DigestInit double: first C_DigestInit", CKR_OK); + + ret = funcList->C_DigestInit(session, &mech); + CHECK_CKR(ret, "DigestInit double: second C_DigestInit", + CKR_OPERATION_ACTIVE); + +cleanup: + bufSz = sizeof(buf); + (void)funcList->C_Digest(session, (CK_BYTE_PTR)"abc", 3, buf, &bufSz); + return result; +} + +/* + * Test: Multi-part encrypt completes, then re-init must succeed. + * Verifies C_EncryptFinal clears the active operation state. + */ +static int test_encrypt_multipart_reinit(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE aesKey) +{ + CK_RV ret; + CK_MECHANISM mech; + byte iv[16]; + byte plain[16], cipher[32], lastPart[16]; + CK_ULONG cipherLen, lastPartLen; + byte buf[16]; + CK_ULONG bufSz; + int result = 0; + + XMEMSET(iv, 0, sizeof(iv)); + XMEMSET(plain, 0xBB, sizeof(plain)); + + mech.mechanism = CKM_AES_CBC; + mech.pParameter = iv; + mech.ulParameterLen = sizeof(iv); + + /* First multi-part encrypt */ + ret = funcList->C_EncryptInit(session, &mech, aesKey); + CHECK_CKR(ret, "Multi-part encrypt: C_EncryptInit", CKR_OK); + + cipherLen = sizeof(cipher); + ret = funcList->C_EncryptUpdate(session, plain, sizeof(plain), + cipher, &cipherLen); + CHECK_CKR(ret, "Multi-part encrypt: C_EncryptUpdate", CKR_OK); + + lastPartLen = sizeof(lastPart); + ret = funcList->C_EncryptFinal(session, lastPart, &lastPartLen); + CHECK_CKR(ret, "Multi-part encrypt: C_EncryptFinal", CKR_OK); + + /* Re-init must succeed — operation was completed */ + ret = funcList->C_EncryptInit(session, &mech, aesKey); + CHECK_CKR(ret, "Multi-part encrypt: re-C_EncryptInit after Final", CKR_OK); + +cleanup: + /* Clean up active operation */ + bufSz = sizeof(buf); + XMEMSET(buf, 0, sizeof(buf)); + (void)funcList->C_Encrypt(session, buf, sizeof(buf), buf, &bufSz); + return result; +} + +#ifndef NO_HMAC +/* + * Test: Multi-part sign completes, then re-init must succeed. + * Verifies C_SignFinal clears the active operation state. + */ +static int test_sign_multipart_reinit(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE hmacKey) +{ + CK_RV ret; + CK_MECHANISM mech; + byte data[16], sig[64]; + CK_ULONG sigLen; + int result = 0; + + XMEMSET(data, 0xCC, sizeof(data)); + + mech.mechanism = CKM_SHA256_HMAC; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + /* First multi-part sign */ + ret = funcList->C_SignInit(session, &mech, hmacKey); + CHECK_CKR(ret, "Multi-part sign: C_SignInit", CKR_OK); + + ret = funcList->C_SignUpdate(session, data, sizeof(data)); + CHECK_CKR(ret, "Multi-part sign: C_SignUpdate", CKR_OK); + + sigLen = sizeof(sig); + ret = funcList->C_SignFinal(session, sig, &sigLen); + CHECK_CKR(ret, "Multi-part sign: C_SignFinal", CKR_OK); + + /* Re-init must succeed — operation was completed */ + ret = funcList->C_SignInit(session, &mech, hmacKey); + CHECK_CKR(ret, "Multi-part sign: re-C_SignInit after Final", CKR_OK); + +cleanup: + sigLen = sizeof(sig); + (void)funcList->C_Sign(session, data, sizeof(data), sig, &sigLen); + return result; +} + +/* + * C_SignInit called twice without completing the operation. + * Second call must return CKR_OPERATION_ACTIVE. + */ +static int test_sign_init_double(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE hmacKey) +{ + CK_RV ret; + CK_MECHANISM mech; + byte buf[32]; + CK_ULONG bufSz; + int result = 0; + + mech.mechanism = CKM_SHA256_HMAC; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + ret = funcList->C_SignInit(session, &mech, hmacKey); + CHECK_CKR(ret, "SignInit double: first C_SignInit", CKR_OK); + + ret = funcList->C_SignInit(session, &mech, hmacKey); + CHECK_CKR(ret, "SignInit double: second C_SignInit", + CKR_OPERATION_ACTIVE); + +cleanup: + bufSz = sizeof(buf); + (void)funcList->C_Sign(session, (CK_BYTE_PTR)"abc", 3, buf, &bufSz); + return result; +} + +/* + * C_VerifyInit called twice without completing the operation. + * Second call must return CKR_OPERATION_ACTIVE. + */ +static int test_verify_init_double(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE hmacKey) +{ + CK_RV ret; + CK_MECHANISM mech; + byte buf[32]; + int result = 0; + + mech.mechanism = CKM_SHA256_HMAC; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + ret = funcList->C_VerifyInit(session, &mech, hmacKey); + CHECK_CKR(ret, "VerifyInit double: first C_VerifyInit", CKR_OK); + + ret = funcList->C_VerifyInit(session, &mech, hmacKey); + CHECK_CKR(ret, "VerifyInit double: second C_VerifyInit", + CKR_OPERATION_ACTIVE); + +cleanup: + XMEMSET(buf, 0, sizeof(buf)); + (void)funcList->C_Verify(session, (CK_BYTE_PTR)"abc", 3, buf, sizeof(buf)); + return result; +} +#endif /* !NO_HMAC */ + +static int operation_active_test(void) +{ + CK_RV ret; + CK_SESSION_HANDLE session = 0; + CK_OBJECT_HANDLE aesKey; +#ifndef NO_HMAC + CK_OBJECT_HANDLE hmacKey; +#endif + int result = 0; + + printf("\n=== Testing Init double-call returns CKR_OPERATION_ACTIVE ===\n"); + + cleanup_test_files(OP_ACTIVE_TEST_DIR); + + ret = pkcs11_init(); + if (ret != CKR_OK) { + fprintf(stderr, "FAIL: pkcs11_init: 0x%lx\n", (unsigned long)ret); + test_failed++; + return -1; + } + + ret = pkcs11_init_token(); + if (ret != CKR_OK) { + fprintf(stderr, "FAIL: C_InitToken: 0x%lx\n", (unsigned long)ret); + test_failed++; + pkcs11_final(); + return -1; + } + + /* Set user PIN via SO session */ + { + CK_SESSION_HANDLE soSession; + int sessFlags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + + ret = funcList->C_OpenSession(slot, sessFlags, NULL, NULL, &soSession); + if (ret != CKR_OK) { + fprintf(stderr, "FAIL: C_OpenSession (SO): 0x%lx\n", + (unsigned long)ret); + test_failed++; + pkcs11_final(); + return -1; + } + + ret = funcList->C_Login(soSession, CKU_SO, soPin, soPinLen); + if (ret != CKR_OK) { + fprintf(stderr, "FAIL: C_Login (SO): 0x%lx\n", + (unsigned long)ret); + test_failed++; + funcList->C_CloseSession(soSession); + pkcs11_final(); + return -1; + } + + ret = funcList->C_InitPIN(soSession, userPin, userPinLen); + if (ret != CKR_OK) { + fprintf(stderr, "FAIL: C_InitPIN: 0x%lx\n", (unsigned long)ret); + test_failed++; + funcList->C_Logout(soSession); + funcList->C_CloseSession(soSession); + pkcs11_final(); + return -1; + } + + funcList->C_Logout(soSession); + funcList->C_CloseSession(soSession); + } + + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) { + fprintf(stderr, "FAIL: pkcs11_open_session: 0x%lx\n", + (unsigned long)ret); + test_failed++; + pkcs11_final(); + return -1; + } + + /* Create keys */ + ret = create_aes_128_key(session, &aesKey); + if (ret != CKR_OK) { + fprintf(stderr, "FAIL: create_aes_128_key: 0x%lx\n", + (unsigned long)ret); + test_failed++; + pkcs11_close_session(session); + pkcs11_final(); + return -1; + } + +#ifndef NO_HMAC + ret = create_hmac_key(session, &hmacKey); + if (ret != CKR_OK) { + fprintf(stderr, "FAIL: create_hmac_key: 0x%lx\n", + (unsigned long)ret); + test_failed++; + pkcs11_close_session(session); + pkcs11_final(); + return -1; + } +#endif + + /* Run tests -- close and reopen the session between each test + * to ensure no leftover operation state leaks between tests. */ + if (test_encrypt_init_double(session, aesKey) != 0) + result = -1; + pkcs11_close_session(session); + session = CK_INVALID_HANDLE; + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) goto done; + + if (test_encrypt_survives_rejected_reinit(session, aesKey) != 0) + result = -1; + pkcs11_close_session(session); + session = CK_INVALID_HANDLE; + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) goto done; + +#ifdef HAVE_AESECB + if (test_encrypt_cross_mechanism(session, aesKey) != 0) + result = -1; + pkcs11_close_session(session); + session = CK_INVALID_HANDLE; + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) goto done; +#endif + + if (test_encrypt_multipart_reinit(session, aesKey) != 0) + result = -1; + pkcs11_close_session(session); + session = CK_INVALID_HANDLE; + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) goto done; + + if (test_decrypt_init_double(session, aesKey) != 0) + result = -1; + pkcs11_close_session(session); + session = CK_INVALID_HANDLE; + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) goto done; + + if (test_digest_init_double(session) != 0) + result = -1; + pkcs11_close_session(session); + session = CK_INVALID_HANDLE; + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) goto done; + +#ifndef NO_HMAC + if (test_sign_multipart_reinit(session, hmacKey) != 0) + result = -1; + pkcs11_close_session(session); + session = CK_INVALID_HANDLE; + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) goto done; + + if (test_sign_init_double(session, hmacKey) != 0) + result = -1; + pkcs11_close_session(session); + session = CK_INVALID_HANDLE; + ret = pkcs11_open_session(&session); + if (ret != CKR_OK) goto done; + + if (test_verify_init_double(session, hmacKey) != 0) + result = -1; +#endif + +done: + if (session != CK_INVALID_HANDLE) + pkcs11_close_session(session); + pkcs11_final(); + return result; +} + +static void print_results(void) +{ + printf("\n=== Test Results ===\n"); + printf("Tests passed: %d\n", test_passed); + printf("Tests failed: %d\n", test_failed); + + if (test_failed == 0) { + printf("ALL TESTS PASSED!\n"); + } else { + printf("SOME TESTS FAILED!\n"); + } +} + +int main(int argc, char* argv[]) +{ +#ifndef WOLFPKCS11_NO_ENV + XSETENV("WOLFPKCS11_TOKEN_PATH", OP_ACTIVE_TEST_DIR, 1); +#endif + + (void)argc; + (void)argv; + + printf("=== wolfPKCS11 Operation Active Test (bug #1616) ===\n"); + + (void)operation_active_test(); + + print_results(); + + return (test_failed == 0) ? 0 : 1; +} + +#else /* NO_AES || NO_AES_CBC */ + +int main(int argc, char* argv[]) +{ + (void)argc; + (void)argv; + + printf("AES-CBC not available, skipping operation active test\n"); + return 0; +} + +#endif /* !NO_AES && !NO_AES_CBC */ diff --git a/tests/pkcs11mtt.c b/tests/pkcs11mtt.c index c3099e51..5adae2ea 100644 --- a/tests/pkcs11mtt.c +++ b/tests/pkcs11mtt.c @@ -2038,6 +2038,8 @@ static CK_RV test_pubkey_sig_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech, ret = funcList->C_Sign(session, hash, hashSz, out, &outSz); CHECK_CKR_FAIL(ret, CKR_OPERATION_NOT_INITIALIZED, "Sign wrong init"); } + /* Clean up active verify operation from cross-type testing */ + (void)funcList->C_Verify(session, hash, hashSz, out, outSz); funcList->C_DestroyObject(session, key); @@ -2638,6 +2640,10 @@ static CK_RV rsa_pkcs15_sig_test(CK_SESSION_HANDLE session, ret = funcList->C_Verify(session, hash, hashSz, out, outSz); CHECK_CKR(ret, "RSA PKCS#1.5 Verify"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pub); + CHECK_CKR(ret, "RSA PKCS#1.5 Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, badHash, sizeof(badHash), out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, @@ -2698,6 +2704,10 @@ static CK_RV rsa_pss_test(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE priv, ret = funcList->C_Verify(session, hash, hashSz, out, outSz); CHECK_CKR(ret, "RSA PKCS#1 PSS Verify"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pub); + CHECK_CKR(ret, "RSA PKCS#1 PSS Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, badHash, hashSz, out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, @@ -2714,6 +2724,10 @@ static CK_RV rsa_pss_test(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE priv, "RSA PKCS#1 PSS Sign out size too small"); outSz = sizeof(out); } + if (ret == CKR_OK) { + ret = funcList->C_Sign(session, hash, hashSz, out, &outSz); + CHECK_CKR(ret, "RSA PKCS#1 PSS Sign cleanup"); + } return ret; } @@ -2972,6 +2986,9 @@ static CK_RV rsa_encdec_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech, CHECK_CKR_FAIL(ret, CKR_OPERATION_NOT_INITIALIZED, "RSA Encrypt wrong init"); } + /* Clean up active decrypt operation from cross-type testing */ + decSz = sizeof(dec); + (void)funcList->C_Decrypt(session, enc, encSz, dec, &decSz); funcList->C_DestroyObject(session, key); @@ -3816,10 +3833,18 @@ static CK_RV ecdsa_test(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE privKey, ret = funcList->C_Verify(session, hash, hashSz, out, outSz); CHECK_CKR(ret, "ECDSA Verify"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pubKey); + CHECK_CKR(ret, "ECDSA Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, hash, hashSz - 1, out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, "ECDSA Verify bad hash"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pubKey); + CHECK_CKR(ret, "ECDSA Verify Init bad sig"); + } if (ret == CKR_OK) { outSz = 1; ret = funcList->C_Verify(session, hash, hashSz, out, outSz); @@ -5020,6 +5045,10 @@ static CK_RV test_aes_cbc_fail(void* args) "AES-CBC Encrypt Final wrong init"); } + /* Clean up active decrypt operation from cross-type testing */ + decSz = sizeof(dec); + (void)funcList->C_Decrypt(session, enc, encSz, dec, &decSz); + funcList->C_DestroyObject(session, key); funcList->C_DestroyObject(session, generic); @@ -5470,6 +5499,10 @@ static CK_RV test_aes_gcm_fail(void* args) "AES-GCM Encrypt Final wrong init"); } + /* Clean up active decrypt operation from cross-type testing */ + decSz = sizeof(dec); + (void)funcList->C_Decrypt(session, enc, encSz, dec, &decSz); + funcList->C_DestroyObject(session, key); funcList->C_DestroyObject(session, generic); @@ -5962,6 +5995,10 @@ static CK_RV test_hmac_update(CK_SESSION_HANDLE session, int mechanism, "HMAC Sign Final out size too small"); outSz = sizeof(out); } + if (ret == CKR_OK) { + ret = funcList->C_SignFinal(session, out, &outSz); + CHECK_CKR(ret, "HMAC Sign Final cleanup"); + } return ret; } @@ -6051,6 +6088,9 @@ static CK_RV test_hmac_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech, "HMAC Sign Final wrong init"); } + /* Clean up active verify operation from cross-type testing */ + (void)funcList->C_Verify(session, data, dataSz, out, outSz); + funcList->C_DestroyObject(session, key); funcList->C_DestroyObject(session, aesKey); diff --git a/tests/pkcs11test.c b/tests/pkcs11test.c index 2606cdb7..ce7685fb 100644 --- a/tests/pkcs11test.c +++ b/tests/pkcs11test.c @@ -6307,6 +6307,8 @@ static CK_RV test_pubkey_sig_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech, ret = funcList->C_Sign(session, hash, hashSz, out, &outSz); CHECK_CKR_FAIL(ret, CKR_OPERATION_NOT_INITIALIZED, "Sign wrong init"); } + /* Clean up active verify operation from cross-type testing */ + (void)funcList->C_Verify(session, hash, hashSz, out, outSz); return ret; } @@ -7227,6 +7229,10 @@ static CK_RV rsa_x_509_sig_test(CK_SESSION_HANDLE session, ret = funcList->C_Verify(session, hash, hashSz, out, outSz); CHECK_CKR(ret, "RSA X_509 Verify"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pub); + CHECK_CKR(ret, "RSA X_509 Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, badHash, sizeof(badHash), out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, "RSA X_509 Verify bad hash"); @@ -7282,6 +7288,10 @@ static CK_RV rsa_pkcs15_sig_test(CK_SESSION_HANDLE session, ret = funcList->C_Verify(session, hash, hashSz, out, outSz); CHECK_CKR(ret, "RSA PKCS#1.5 Verify"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pub); + CHECK_CKR(ret, "RSA PKCS#1.5 Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, badHash, sizeof(badHash), out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, @@ -7415,6 +7425,10 @@ static CK_RV sha256_rsa_pkcs15_sig_test(CK_SESSION_HANDLE session, ret = funcList->C_Verify(session, hash, hashSz, out, outSz); CHECK_CKR(ret, "RSA PKCS#1.5 Verify"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pub); + CHECK_CKR(ret, "RSA PKCS#1.5 Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, badHash, sizeof(badHash), out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, @@ -7476,6 +7490,10 @@ static CK_RV rsa_pss_test(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE priv, ret = funcList->C_Verify(session, hash, hashSz, out, outSz); CHECK_CKR(ret, "RSA PKCS#1 PSS Verify"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pub); + CHECK_CKR(ret, "RSA PKCS#1 PSS Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, badHash, hashSz, out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, @@ -7492,6 +7510,10 @@ static CK_RV rsa_pss_test(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE priv, "RSA PKCS#1 PSS Sign out size too small"); outSz = sizeof(out); } + if (ret == CKR_OK) { + ret = funcList->C_Sign(session, hash, hashSz, out, &outSz); + CHECK_CKR(ret, "RSA PKCS#1 PSS Sign cleanup"); + } return ret; } @@ -7548,6 +7570,10 @@ static CK_RV sha256_rsa_pss_test(CK_SESSION_HANDLE session, ret = funcList->C_Verify(session, hash, hashSz, out, outSz); CHECK_CKR(ret, "RSA PKCS#1 PSS Verify"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pub); + CHECK_CKR(ret, "RSA PKCS#1 PSS Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, badHash, hashSz, out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, @@ -7564,6 +7590,10 @@ static CK_RV sha256_rsa_pss_test(CK_SESSION_HANDLE session, "RSA PKCS#1 PSS Sign out size too small"); outSz = sizeof(out); } + if (ret == CKR_OK) { + ret = funcList->C_Sign(session, hash, hashSz, out, &outSz); + CHECK_CKR(ret, "RSA PKCS#1 PSS Sign cleanup"); + } return ret; } @@ -7961,6 +7991,9 @@ static CK_RV test_rsa_encdec_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech, CHECK_CKR_FAIL(ret, CKR_OPERATION_NOT_INITIALIZED, "RSA Encrypt wrong init"); } + /* Clean up active decrypt operation from cross-type testing */ + decSz = sizeof(dec); + (void)funcList->C_Decrypt(session, enc, encSz, dec, &decSz); return ret; } @@ -8850,10 +8883,18 @@ static CK_RV ecdsa_test(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE privKey, CHECK_CKR(ret, "ECDSA Verify"); } #endif + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pubKey); + CHECK_CKR(ret, "ECDSA Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, hash, hashSz - 1, out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, "ECDSA Verify bad hash"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pubKey); + CHECK_CKR(ret, "ECDSA Verify Init bad sig"); + } if (ret == CKR_OK) { outSz = 1; ret = funcList->C_Verify(session, hash, hashSz, out, outSz); @@ -8908,10 +8949,18 @@ static CK_RV ecdsa_test(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE privKey, CHECK_CKR(ret, "ECDSA Verify"); } #endif + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pubKey); + CHECK_CKR(ret, "ECDSA Verify Init bad hash"); + } if (ret == CKR_OK) { ret = funcList->C_Verify(session, data, dataSz - 1, out, outSz); CHECK_CKR_FAIL(ret, CKR_SIGNATURE_INVALID, "ECDSA Verify bad hash"); } + if (ret == CKR_OK) { + ret = funcList->C_VerifyInit(session, &mech, pubKey); + CHECK_CKR(ret, "ECDSA Verify Init bad sig"); + } if (ret == CKR_OK) { outSz = 1; ret = funcList->C_Verify(session, data, dataSz, out, outSz); @@ -10370,6 +10419,10 @@ static CK_RV test_aes_cbc_fail(void* args) "AES-CBC Encrypt Final wrong init"); } + /* Clean up active decrypt operation from cross-type testing */ + decSz = sizeof(dec); + (void)funcList->C_Decrypt(session, enc, encSz, dec, &decSz); + return ret; } @@ -11710,6 +11763,10 @@ static CK_RV test_aes_gcm_fail(void* args) "AES-GCM Encrypt Final wrong init"); } + /* Clean up active decrypt operation from cross-type testing */ + decSz = sizeof(dec); + (void)funcList->C_Decrypt(session, enc, encSz, dec, &decSz); + return ret; } @@ -12411,6 +12468,10 @@ static CK_RV test_aes_cmac_update(CK_SESSION_HANDLE session, unsigned char* exp, "AES-CMAC Sign Final out size too small"); outSz = sizeof(out); } + if (ret == CKR_OK) { + ret = funcList->C_SignFinal(session, out, &outSz); + CHECK_CKR(ret, "AES-CMAC Sign Final cleanup"); + } return ret; } @@ -12583,6 +12644,10 @@ static CK_RV test_aes_cmac_general_update(CK_SESSION_HANDLE session, "AES-CMAC Sign Final out size too small"); outSz = sizeof(out); } + if (ret == CKR_OK) { + ret = funcList->C_SignFinal(session, out, &outSz); + CHECK_CKR(ret, "AES-CMAC Sign Final cleanup"); + } return ret; } @@ -12930,6 +12995,10 @@ static CK_RV test_hmac_update(CK_SESSION_HANDLE session, int mechanism, "HMAC Sign Final out size too small"); outSz = sizeof(out); } + if (ret == CKR_OK) { + ret = funcList->C_SignFinal(session, out, &outSz); + CHECK_CKR(ret, "HMAC Sign Final cleanup"); + } return ret; } @@ -13019,6 +13088,9 @@ static CK_RV test_hmac_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech, "HMAC Sign Final wrong init"); } + /* Clean up active verify operation from cross-type testing */ + (void)funcList->C_Verify(session, data, dataSz, out, outSz); + return ret; } #ifndef NO_MD5 @@ -16494,16 +16566,22 @@ static CK_RV test_oaep_reinit(void* args) ret = funcList->C_EncryptInit(session, &mech, pub); CHECK_CKR(ret, "OAEP Encrypt Init #1 with label"); } + /* Complete the first operation to release session state */ + if (ret == CKR_OK) { + memset(plain, 9, sizeof(plain)); + ret = funcList->C_Encrypt(session, plain, plainSz, enc, &encSz); + CHECK_CKR(ret, "OAEP Encrypt #1"); + } /* Second init with label2 — old label must be freed, not leaked */ if (ret == CKR_OK) { params.pSourceData = label2; params.ulSourceDataLen = sizeof(label2); + encSz = sizeof(enc); ret = funcList->C_EncryptInit(session, &mech, pub); CHECK_CKR(ret, "OAEP Encrypt Init #2 with different label (reinit)"); } - /* Complete the operation so session state is clean */ + /* Complete the second operation */ if (ret == CKR_OK) { - memset(plain, 9, sizeof(plain)); ret = funcList->C_Encrypt(session, plain, plainSz, enc, &encSz); CHECK_CKR(ret, "OAEP Encrypt after reinit"); } @@ -16548,14 +16626,20 @@ static CK_RV test_gcm_reinit(void* args) ret = funcList->C_EncryptInit(session, &mech, key); CHECK_CKR(ret, "AES-GCM Encrypt Init #1 with AAD"); } + /* Complete the first operation to release session state */ + if (ret == CKR_OK) { + ret = funcList->C_Encrypt(session, plain, plainSz, enc, &encSz); + CHECK_CKR(ret, "AES-GCM Encrypt #1"); + } /* Second init with aad2 — old AAD must be freed, not leaked */ if (ret == CKR_OK) { gcmParams.pAAD = aad2; gcmParams.ulAADLen = sizeof(aad2); + encSz = sizeof(enc); ret = funcList->C_EncryptInit(session, &mech, key); CHECK_CKR(ret, "AES-GCM Encrypt Init #2 with different AAD (reinit)"); } - /* Complete the operation */ + /* Complete the second operation */ if (ret == CKR_OK) { ret = funcList->C_Encrypt(session, plain, plainSz, enc, &encSz); CHECK_CKR(ret, "AES-GCM Encrypt after reinit"); @@ -16600,14 +16684,20 @@ static CK_RV test_ccm_reinit(void* args) ret = funcList->C_EncryptInit(session, &mech, key); CHECK_CKR(ret, "AES-CCM Encrypt Init #1 with AAD"); } + /* Complete the first operation to release session state */ + if (ret == CKR_OK) { + ret = funcList->C_Encrypt(session, plain, plainSz, enc, &encSz); + CHECK_CKR(ret, "AES-CCM Encrypt #1"); + } /* Second init with aad2 — old AAD must be freed, not leaked */ if (ret == CKR_OK) { ccmParams.pAAD = aad2; ccmParams.ulAADLen = sizeof(aad2); + encSz = sizeof(enc); ret = funcList->C_EncryptInit(session, &mech, key); CHECK_CKR(ret, "AES-CCM Encrypt Init #2 with different AAD (reinit)"); } - /* Complete the operation */ + /* Complete the second operation */ if (ret == CKR_OK) { ret = funcList->C_Encrypt(session, plain, plainSz, enc, &encSz); CHECK_CKR(ret, "AES-CCM Encrypt after reinit"); @@ -16648,6 +16738,14 @@ static CK_RV test_verify_recover_init_double(void* args) CHECK_CKR_FAIL(ret, CKR_OPERATION_ACTIVE, "Second C_VerifyRecoverInit without completing first"); } + /* Clean up active verify-recover operation */ + { + byte sig[256], data[256]; + CK_ULONG dataLen = sizeof(data); + XMEMSET(sig, 0, sizeof(sig)); + (void)funcList->C_VerifyRecover(session, sig, sizeof(sig), + data, &dataLen); + } return ret; } diff --git a/wolfpkcs11/internal.h b/wolfpkcs11/internal.h index 66d357fe..f1e15d44 100644 --- a/wolfpkcs11/internal.h +++ b/wolfpkcs11/internal.h @@ -259,6 +259,14 @@ C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT" #define WP11_INIT_TLS_MAC_VERIFY 0x0071 #define WP11_INIT_MLDSA_SIGN 0x0080 #define WP11_INIT_MLDSA_VERIFY 0x0081 + +/* Operation categories for CKR_OPERATION_ACTIVE checks */ +#define WP11_OP_ENCRYPT 0 +#define WP11_OP_DECRYPT 1 +#define WP11_OP_DIGEST 2 +#define WP11_OP_SIGN 3 +#define WP11_OP_VERIFY 4 + /* Some operations can have an additional hashing step before the sign/verify */ #define WP11_INIT_DIGEST_SHIFT 12 #define WP11_INIT_DIGEST_MASK (0xF << WP11_INIT_DIGEST_SHIFT) @@ -369,6 +377,8 @@ WP11_LOCAL int WP11_Session_Get(CK_SESSION_HANDLE sessionHandle, WP11_Session** WP11_LOCAL int WP11_Session_GetState(WP11_Session* session); WP11_LOCAL int WP11_Session_IsRW(WP11_Session* session); WP11_LOCAL int WP11_Session_IsOpInitialized(WP11_Session* session, int init); +WP11_LOCAL int WP11_Session_IsOpCategoryActive(WP11_Session* session, + int opCategory); WP11_LOCAL int WP11_Session_UpdateData(WP11_Session *session, byte *data, word32 dataLen); WP11_LOCAL void WP11_Session_GetData(WP11_Session *session, byte** data, word32* dataLen); WP11_LOCAL void WP11_Session_FreeData(WP11_Session *session);