diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-06-19 08:45:21 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-06-19 11:16:21 +0200 |
commit | df68fe8f811fbc2e8fd9ac714ad5e280f0cc7d90 (patch) | |
tree | d0dc2c40c6b356c184ad74e29f719594c5ac0392 | |
parent | b1f23b595e71017e6ba85474b77445145779013a (diff) | |
download | gnutls-df68fe8f811fbc2e8fd9ac714ad5e280f0cc7d90.tar.gz |
tests: backported the safenet always auth PKCS#11 testgnutls_3_3_x-safenet-updates
This adds a unit test for safenet protectserver HSM's PKCS#11 support.
That is, detect whether the absence of C_Login on a token, will result
to C_Sign or C_Decrypt to a login using CKU_USER.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/pkcs11/pkcs11-mock-ext.h | 3 | ||||
-rw-r--r-- | tests/pkcs11/pkcs11-mock.c | 239 | ||||
-rw-r--r-- | tests/pkcs11/pkcs11-mock.h | 2 | ||||
-rw-r--r-- | tests/pkcs11/pkcs11-privkey-safenet-always-auth.c | 184 |
5 files changed, 398 insertions, 36 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 77c4e1d1c6..bafb12ae0b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -111,10 +111,14 @@ pkcs11_import_url_privkey_SOURCES = pkcs11/pkcs11-import-url-privkey.c pkcs11_import_url_privkey_DEPENDENCIES = libpkcs11mock1.la libutils.la pkcs11_import_url_privkey_LDADD = $(LDADD) $(LIBDL) +pkcs11_privkey_safenet_always_auth_SOURCES = pkcs11/pkcs11-privkey-safenet-always-auth.c +pkcs11_privkey_safenet_always_auth_DEPENDENCIES = libpkcs11mock1.la libutils.la +pkcs11_privkey_safenet_always_auth_LDADD = $(LDADD) $(LIBDL) + ctests += pkcs11-cert-import-url-exts pkcs11-get-exts pkcs11-get-raw-issuer-exts \ pkcs11/pkcs11-chainverify pkcs11/pkcs11-get-issuer pkcs11/pkcs11-is-known \ pkcs11/pkcs11-combo pkcs11-import-url-privkey pkcs11/pkcs11-pubkey-import-rsa \ - pkcs11/pkcs11-import-with-pin + pkcs11/pkcs11-import-with-pin pkcs11-privkey-safenet-always-auth endif endif diff --git a/tests/pkcs11/pkcs11-mock-ext.h b/tests/pkcs11/pkcs11-mock-ext.h index 8b66b189bc..277e4a7d8e 100644 --- a/tests/pkcs11/pkcs11-mock-ext.h +++ b/tests/pkcs11/pkcs11-mock-ext.h @@ -26,5 +26,8 @@ /* This flag instructs the module to return CKR_OK on sensitive * objects */ #define MOCK_FLAG_BROKEN_GET_ATTRIBUTES 1 +#define MOCK_FLAG_ALWAYS_AUTH (1<<1) +/* simulate the safenet HSMs always auth behavior */ +#define MOCK_FLAG_SAFENET_ALWAYS_AUTH (1<<2) #endif diff --git a/tests/pkcs11/pkcs11-mock.c b/tests/pkcs11/pkcs11-mock.c index de265bf5d0..daf7d22bd2 100644 --- a/tests/pkcs11/pkcs11-mock.c +++ b/tests/pkcs11/pkcs11-mock.c @@ -15,6 +15,7 @@ #include "pkcs11-mock.h" #include "pkcs11-mock-ext.h" +#include <string.h> #include <stdlib.h> unsigned int pkcs11_mock_flags = 0; @@ -112,9 +113,33 @@ const char mock_pubkey[] = "\x3f\x66\x62\x92\xfd\x41\x20\xb6\x2c\x00\xf0\x52\xca\x26\x06\x2d" "\x7c\xcf\x7a\x50\x7d\x0f\xcb\xdd\x97\x20\xc8\x6f\xe4\xe0\x50\xf4" "\xe3\x02\x03\x01\x00\x01"; +const char mock_public_exponent[] = "\x01\x00\x01"; +const char mock_modulus[] = + "\xDD\xCF\x97\xD2\xA5\x1D\x95\xDD\x86\x18\xD8\xC4\xB9\xAD\xA6\x0C" + "\xB4\x9D\xB6\xDC\xFA\xDC\x21\xE1\x3A\x62\x34\x07\xE8\x33\xB2\xE8" + "\x97\xEE\x2C\x41\xD2\x12\xF1\x5F\xED\xE4\x76\xFF\x65\x26\x1E\x0C" + "\xC7\x41\x15\x69\x5F\x0D\xF9\xAD\x89\x14\x8D\xEA\xD7\x16\x52\x9A" + "\x47\xC1\xBB\x00\x02\xE4\x88\x45\x73\x78\xA4\xAE\xDB\x38\xC3\xC6" + "\x07\xD2\x64\x0E\x87\xED\x74\x8C\x6B\xC4\xC0\x02\x50\x7C\x4E\xA6" + "\xD1\x58\xE9\xE5\x13\x09\xA9\xDB\x5A\xEA\xEB\x0F\x06\x80\x5C\x09" + "\xEF\x94\xC8\xE9\xFB\x37\x2E\x75\xE1\xAC\x93\xAD\x9B\x37\x13\x4B" + "\x66\x3A\x76\x33\xD8\xC4\xD7\x4C\xFB\x61\xC8\x92\x21\x07\xFC\xDF" + "\xA9\x88\x54\xE4\xA3\xA9\x47\xD2\x6C\xB8\xE3\x39\x89\x11\x88\x38" + "\x2D\xA2\xDC\x3E\x5E\x4A\xA9\xA4\x8E\xD5\x1F\xB2\xD0\xDD\x41\x3C" + "\xDA\x10\x68\x9E\x47\x1B\x65\x02\xA2\xC5\x28\x73\x02\x83\x03\x09" + "\xFD\xF5\x29\x7E\x97\xDC\x2A\x4E\x4B\xAA\x79\x46\x46\x70\x86\x1B" + "\x9B\xB8\xF6\x8A\xBE\x29\x87\x7D\x5F\xDA\xA5\x97\x6B\xEF\xC8\x43" + "\x09\x43\xE2\x1F\x8A\x16\x7E\x1D\x50\x5D\xF5\xDA\x02\xEE\xF2\xC3" + "\x2A\x48\xE6\x6B\x30\xEA\x02\xD7\xEF\xAC\x8B\x0C\xB8\xC1\x85\xD8" + "\xBF\x7C\x85\xA8\x1E\x83\xBE\x5C\x26\x2E\x79\x7B\x47\xF5\x4A\x3F" + "\x66\x62\x92\xFD\x41\x20\xB6\x2C\x00\xF0\x52\xCA\x26\x06\x2D\x7C" + "\xCF\x7A\x50\x7D\x0F\xCB\xDD\x97\x20\xC8\x6F\xE4\xE0\x50\xF4\xE3"; +const char mock_subject[] = + "DN: C=US, O=Test Government, OU=Test Department, OU=Test Agency/serialNumber="; CK_BBOOL pkcs11_mock_initialized = CK_FALSE; CK_BBOOL pkcs11_mock_session_opened = CK_FALSE; +CK_BBOOL pkcs11_mock_session_reauth = CK_FALSE; static session_ptr_st *mock_session = NULL; @@ -191,6 +216,25 @@ CK_FUNCTION_LIST pkcs11_mock_functions = &C_WaitForSlotEvent }; +#if defined(HAVE___REGISTER_ATFORK) +extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); +extern void *__dso_handle; +static unsigned registered_fork_handler = 0; + +static void fork_handler(void) +{ + pkcs11_mock_initialized = CK_FALSE; + pkcs11_mock_session_opened = CK_FALSE; + if (mock_session) { + mock_session->state = CKS_RO_PUBLIC_SESSION; + mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE; + free(mock_session->find_label); + } + free(mock_session); + mock_session = NULL; +} +#endif + CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) { @@ -198,7 +242,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) return CKR_CRYPTOKI_ALREADY_INITIALIZED; IGNORE(pInitArgs); - +#if defined(HAVE___REGISTER_ATFORK) + if (registered_fork_handler == 0) { + __register_atfork(NULL, NULL, fork_handler, __dso_handle); + registered_fork_handler = 1; + } +#endif pkcs11_mock_initialized = CK_TRUE; return CKR_OK; @@ -323,6 +372,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR p memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber)); memcpy(pInfo->serialNumber, PKCS11_MOCK_CK_TOKEN_INFO_SERIAL_NUMBER, strlen(PKCS11_MOCK_CK_TOKEN_INFO_SERIAL_NUMBER)); pInfo->flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; + + if (pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) + pInfo->flags &= ~CKF_LOGIN_REQUIRED; + pInfo->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE; pInfo->ulSessionCount = (CK_TRUE == pkcs11_mock_session_opened) ? 1 : 0; pInfo->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE; @@ -534,7 +587,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_V { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (CK_TRUE == pkcs11_mock_session_opened) return CKR_SESSION_COUNT; @@ -583,6 +635,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)(CK_SESSION_HANDLE hSession) mock_session->find_op.active_operation = PKCS11_MOCK_CK_OPERATION_NONE; free(mock_session->find_label); free(mock_session); + mock_session = NULL; return CKR_OK; } @@ -676,8 +729,16 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE user if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; - if ((CKU_SO != userType) && (CKU_USER != userType)) + if ((pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) && userType == CKU_CONTEXT_SPECIFIC) { + return CKR_USER_TYPE_INVALID; + } + + if ((pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH) || (pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH)) { + if ((CKU_CONTEXT_SPECIFIC != userType) && (CKU_SO != userType) && (CKU_USER != userType)) + return CKR_USER_TYPE_INVALID; + } else if ((CKU_SO != userType) && (CKU_USER != userType)) { return CKR_USER_TYPE_INVALID; + } if (NULL == pPin) return CKR_ARGUMENTS_BAD; @@ -716,6 +777,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE user break; } + if ((pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) && rv == CKR_USER_ALREADY_LOGGED_IN) { + rv = 0; + } + + pkcs11_mock_session_reauth = 1; return rv; } @@ -883,6 +949,56 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OB pTemplate[i].ulValueLen = (CK_ULONG) sizeof(mock_pubkey)-1; memcpy(pTemplate[i].pValue, mock_pubkey, pTemplate[i].ulValueLen); } + else if (CKA_CLASS == pTemplate[i].type) + { + if (NULL != pTemplate[i].pValue) + { + if (pTemplate[i].ulValueLen < sizeof(hObject)) + return CKR_BUFFER_TOO_SMALL; + else + memcpy(pTemplate[i].pValue, &hObject, sizeof(hObject)); + } + + pTemplate[i].ulValueLen = sizeof(hObject); + } + else if (CKA_PUBLIC_EXPONENT == pTemplate[i].type && + (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY == hObject || PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY == hObject)) + { + if (NULL != pTemplate[i].pValue) + { + if (pTemplate[i].ulValueLen < sizeof(mock_public_exponent)-1) + return CKR_BUFFER_TOO_SMALL; + else + memcpy(pTemplate[i].pValue, mock_public_exponent, sizeof(mock_public_exponent)-1); + } + + pTemplate[i].ulValueLen = sizeof(mock_public_exponent)-1; + } + else if (CKA_MODULUS == pTemplate[i].type && + (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY == hObject || PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY == hObject)) + { + if (NULL != pTemplate[i].pValue) + { + if (pTemplate[i].ulValueLen < sizeof(mock_modulus)-1) + return CKR_BUFFER_TOO_SMALL; + else + memcpy(pTemplate[i].pValue, mock_modulus, sizeof(mock_modulus)-1); + } + + pTemplate[i].ulValueLen = sizeof(mock_modulus)-1; + } + else if (CKA_SUBJECT == pTemplate[i].type && PKCS11_MOCK_CK_OBJECT_HANDLE_CERTIFICATE == hObject) + { + if (NULL != pTemplate[i].pValue) + { + if (pTemplate[i].ulValueLen < strlen(mock_subject)) + return CKR_BUFFER_TOO_SMALL; + else + memcpy(pTemplate[i].pValue, mock_subject, strlen(mock_subject)); + } + + pTemplate[i].ulValueLen = strlen(mock_subject); + } else if (CKA_LABEL == pTemplate[i].type) { if (NULL != pTemplate[i].pValue) @@ -895,6 +1011,31 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OB pTemplate[i].ulValueLen = strlen(PKCS11_MOCK_CK_OBJECT_CKA_LABEL); } + else if (CKA_KEY_TYPE == pTemplate[i].type) + { + CK_KEY_TYPE t; + if (pTemplate[i].ulValueLen != sizeof(CK_KEY_TYPE)) + return CKR_ARGUMENTS_BAD; + + t = CKK_RSA; + memcpy(pTemplate[i].pValue, &t, sizeof(CK_KEY_TYPE)); + } + else if (CKA_ALWAYS_AUTHENTICATE == pTemplate[i].type) + { + CK_BBOOL t; + if (pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) + return CKR_ATTRIBUTE_TYPE_INVALID; + + if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) + return CKR_ARGUMENTS_BAD; + + if (!(pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH)) { + t = CK_FALSE; + } else { + t = CK_TRUE; + } + memcpy(pTemplate[i].pValue, &t, sizeof(CK_BBOOL)); + } else if (CKA_ID == pTemplate[i].type) { if (NULL != pTemplate[i].pValue) @@ -1066,8 +1207,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(CK_SESSION_HANDLE hSession, CK_ATTR if (CKA_LABEL == pTemplate[i].type) { - if (mock_session->find_label) - free(mock_session->find_label); + free(mock_session->find_label); mock_session->find_label = strndup(pTemplate[i].pValue, pTemplate[i].ulValueLen); } else if (CKA_CLASS == pTemplate[i].type) @@ -1403,13 +1543,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANIS if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; + if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) + return CKR_SESSION_HANDLE_INVALID; + if ((PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) && (PKCS11_MOCK_CK_OPERATION_DIGEST != mock_session->find_op.active_operation) && (PKCS11_MOCK_CK_OPERATION_VERIFY != mock_session->find_op.active_operation)) return CKR_OPERATION_ACTIVE; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) - return CKR_SESSION_HANDLE_INVALID; + if (pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) { + mock_session->state = CKS_RO_PUBLIC_SESSION; + pkcs11_mock_session_reauth = 0; + } if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; @@ -1487,11 +1632,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEn if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; + if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) + return CKR_SESSION_HANDLE_INVALID; + if (PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation) return CKR_OPERATION_NOT_INITIALIZED; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) - return CKR_SESSION_HANDLE_INVALID; + if (pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) { + if (!pkcs11_mock_session_reauth) { + return CKR_USER_NOT_LOGGED_IN; + } + if ((pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH) && pData != NULL) { + pkcs11_mock_session_reauth = 0; + } + } if (NULL == pEncryptedData) return CKR_ARGUMENTS_BAD; @@ -1530,12 +1684,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_P if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation) - return CKR_OPERATION_NOT_INITIALIZED; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; + if (PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation) + return CKR_OPERATION_NOT_INITIALIZED; + if (NULL == pEncryptedPart) return CKR_ARGUMENTS_BAD; @@ -1569,14 +1723,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PT if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; + if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) + return CKR_SESSION_HANDLE_INVALID; + if ((PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != mock_session->find_op.active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != mock_session->find_op.active_operation)) return CKR_OPERATION_NOT_INITIALIZED; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) - return CKR_SESSION_HANDLE_INVALID; - if (NULL == pulLastPartLen) return CKR_ARGUMENTS_BAD; @@ -1781,12 +1935,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_P if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; + if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) + return CKR_SESSION_HANDLE_INVALID; + if ((PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) && (PKCS11_MOCK_CK_OPERATION_ENCRYPT != mock_session->find_op.active_operation)) return CKR_OPERATION_ACTIVE; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) - return CKR_SESSION_HANDLE_INVALID; + if (pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) { + mock_session->state = CKS_RO_PUBLIC_SESSION; + pkcs11_mock_session_reauth = 0; + } if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; @@ -1826,6 +1985,16 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; + if (pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH || pkcs11_mock_flags & MOCK_FLAG_SAFENET_ALWAYS_AUTH) { + if (!pkcs11_mock_session_reauth) { + return CKR_USER_NOT_LOGGED_IN; + } + + if ((pkcs11_mock_flags & MOCK_FLAG_ALWAYS_AUTH) && pSignature != NULL) { + pkcs11_mock_session_reauth = 0; + } + } + if (NULL == pData) return CKR_ARGUMENTS_BAD; @@ -1920,12 +2089,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECH if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) - return CKR_OPERATION_ACTIVE; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; + if (PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) + return CKR_OPERATION_ACTIVE; + if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; @@ -1996,13 +2165,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; + if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) + return CKR_SESSION_HANDLE_INVALID; + if ((PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT != mock_session->find_op.active_operation)) return CKR_OPERATION_ACTIVE; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) - return CKR_SESSION_HANDLE_INVALID; - if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; @@ -2126,12 +2295,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession, CK_ME if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) - return CKR_OPERATION_ACTIVE; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; + if (PKCS11_MOCK_CK_OPERATION_NONE != mock_session->find_op.active_operation) + return CKR_OPERATION_ACTIVE; + if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; @@ -2245,12 +2414,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession, CK_ if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != mock_session->find_op.active_operation) - return CKR_OPERATION_NOT_INITIALIZED; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; + if (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != mock_session->find_op.active_operation) + return CKR_OPERATION_NOT_INITIALIZED; + if (NULL == pEncryptedPart) return CKR_ARGUMENTS_BAD; @@ -2286,12 +2455,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BY if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT != mock_session->find_op.active_operation) - return CKR_OPERATION_NOT_INITIALIZED; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; + if (PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT != mock_session->find_op.active_operation) + return CKR_OPERATION_NOT_INITIALIZED; + if (NULL == pPart) return CKR_ARGUMENTS_BAD; @@ -2327,12 +2496,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession, CK_ if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; - if (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != mock_session->find_op.active_operation) - return CKR_OPERATION_NOT_INITIALIZED; - if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; + if (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != mock_session->find_op.active_operation) + return CKR_OPERATION_NOT_INITIALIZED; + if (NULL == pEncryptedPart) return CKR_ARGUMENTS_BAD; diff --git a/tests/pkcs11/pkcs11-mock.h b/tests/pkcs11/pkcs11-mock.h index 6026c41de1..9b2a66bbd0 100644 --- a/tests/pkcs11/pkcs11-mock.h +++ b/tests/pkcs11/pkcs11-mock.h @@ -13,6 +13,8 @@ * Please contact JWC s.r.o. at <info@pkcs11interop.net> for more details. */ + +#define _POSIX_C_SOURCE 200809 #include <config.h> #include <stdio.h> #include <string.h> diff --git a/tests/pkcs11/pkcs11-privkey-safenet-always-auth.c b/tests/pkcs11/pkcs11-privkey-safenet-always-auth.c new file mode 100644 index 0000000000..1b5b34054d --- /dev/null +++ b/tests/pkcs11/pkcs11-privkey-safenet-always-auth.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2017 Nikos Mavrogiannopoulos + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * GnuTLS 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. + * + * GnuTLS 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 GnuTLS; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include <gnutls/abstract.h> +#include <gnutls/pkcs11.h> + +#ifdef _WIN32 + +void doit(void) +{ + exit(77); +} + +#else + +# include "utils.h" +# include "pkcs11-mock-ext.h" + +/* Tests whether a gnutls_privkey_t will work properly with a key marked + * as always authenticate, but on the safenet HSMs where CKA_ALWAYS_AUTHENTICATE + * is not supported */ + +static unsigned pin_called = 0; +static const char *_pin = "1234"; + +# include <dlfcn.h> +# define P11LIB "libpkcs11mock1.so" + + +static void tls_log_func(int level, const char *str) +{ + fprintf(stderr, "|<%d>| %s", level, str); +} + +static +int pin_func(void* userdata, int attempt, const char* url, const char *label, + unsigned flags, char *pin, size_t pin_max) +{ + if (_pin == NULL) + return -1; + + strcpy(pin, _pin); + pin_called++; + return 0; +} + +void doit(void) +{ + int ret; + const char *lib; + gnutls_privkey_t key; + gnutls_datum_t sig = {NULL, 0}, data; + + lib = getenv("P11MOCKLIB1"); + if (lib == NULL) + lib = P11LIB; + + { + void *dl; + unsigned int *pflags; + + dl = dlopen(lib, RTLD_NOW); + if (dl == NULL) { + fail("could not dlopen %s\n", lib); + exit(1); + } + + pflags = dlsym(dl, "pkcs11_mock_flags"); + if (pflags == NULL) { + fail("could find pkcs11_mock_flags\n"); + exit(1); + } + + *pflags = MOCK_FLAG_SAFENET_ALWAYS_AUTH; + } + + data.data = (void*)"\x38\x17\x0c\x08\xcb\x45\x8f\xd4\x87\x9c\x34\xb6\xf6\x08\x29\x4c\x50\x31\x2b\xbb"; + data.size = 20; + + ret = global_init(); + if (ret != 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + gnutls_global_set_log_function(tls_log_func); + if (debug) + gnutls_global_set_log_level(4711); + + ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL); + if (ret != 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + ret = gnutls_pkcs11_add_provider(lib, NULL); + if (ret != 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + ret = gnutls_privkey_init(&key); + assert(ret>=0); + + gnutls_privkey_set_pin_function(key, pin_func, NULL); + + ret = gnutls_privkey_import_url(key, "pkcs11:object=test", GNUTLS_PKCS11_OBJ_FLAG_LOGIN); + if (ret < 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + pin_called = 0; + + ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig); + if (ret < 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + if (pin_called == 0) { + fail("PIN function wasn't called!\n"); + } + pin_called = 0; + + gnutls_free(sig.data); + sig.data = NULL; + + /* call again - should re-authenticate */ + ret = gnutls_privkey_sign_hash(key, GNUTLS_DIG_SHA1, 0, &data, &sig); + if (ret < 0) { + fail("%d: %s\n", ret, gnutls_strerror(ret)); + exit(1); + } + + if (pin_called == 0) { + fail("PIN function wasn't called twice!\n"); + } + pin_called = 0; + + gnutls_free(sig.data); + sig.data = NULL; + + if (debug) + printf("done\n\n\n"); + + gnutls_privkey_deinit(key); + gnutls_pkcs11_deinit(); + gnutls_global_deinit(); +} +#endif |