diff --git a/README.md b/README.md index b6b46c0..7ed2cf0 100644 --- a/README.md +++ b/README.md @@ -32,11 +32,6 @@ cd wolfPKCS11 make make check ``` -### Optional: AES-CCM Support - -To have AES-CCM support in wolfPKCS11, simiply configure wolfSSL with the -addition of `--enable-aesccm` - ### TPM support with wolfTPM Enables using a TPM for cryptography and keystore. @@ -44,6 +39,20 @@ Tested using `./configure --enable-singlethreaded --enable-wolftpm --disable-dh Note: The TPM does not support DH, so only RSA and ECC are supported. +### Optional: AES-CCM Support + +To have AES-CCM support in wolfPKCS11, simiply configure both wolfSSL and +wolfPKCS11 with the addition of `--enable-aesccm` + +### Optional: AES-ECB Support + +To have AES-ECB support in wolfPKCS11, simiply configure wolfSSL with the C +macro `HAVE_AES_ECB` defined. For example, `CFLAGS="-DHAVE_AES_ECB`. Then +enable it in wolfPKCS11 with the addition of `--enable-aesccm` during the +configure step. + +WARNING: ECB (Electronic Code Book) mode AES is generally considered to be +insecure. Please consider using a different mode of AES. ### Build options and defines diff --git a/configure.ac b/configure.ac index 88d02f8..937f27a 100644 --- a/configure.ac +++ b/configure.ac @@ -250,6 +250,18 @@ else DISABLE_DEFS="$DISABLE_DEFS -DHAVE_AESCCM" fi +AC_ARG_ENABLE([aesecb], + [AS_HELP_STRING([--enable-aesecb],[Enable AES-ECB (default: disabled)])], + [ ENABLED_AESECB=$enableval ], + [ ENABLED_AESECB=no ] + ) +if test "$ENABLED_AES" = "yes" && test "$ENABLED_AESECB" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_AESECB" +else + DISABLE_DEFS="$DISABLE_DEFS -DHAVE_AESECB" +fi + AC_ARG_ENABLE([hmac], [AS_HELP_STRING([--enable-hmac],[Enable HMAC (default: enabled)])], [ ENABLED_HMAC=$enableval ], @@ -514,6 +526,7 @@ echo " * AES: $ENABLED_AES" echo " * AES-CBC: $ENABLED_AESCBC" echo " * AES-GCM: $ENABLED_AESGCM" echo " * AES-CCM: $ENABLED_AESCCM" +echo " * AES-ECB: $ENABLED_AESECB" echo " * MD5: $ENABLED_MD5" echo " * SHA: $ENABLED_SHA1" echo " * SHA-224: $ENABLED_SHA224" diff --git a/src/crypto.c b/src/crypto.c index 563b523..314f2b2 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -1312,6 +1312,20 @@ CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, break; } #endif + + #ifdef HAVE_AESECB + case CKM_AES_ECB: { + if (type != CKK_AES) + return CKR_KEY_TYPE_INCONSISTENT; + if (pMechanism->pParameter != NULL) + return CKR_MECHANISM_PARAM_INVALID; + if (pMechanism->ulParameterLen != 0) + return CKR_MECHANISM_PARAM_INVALID; + + init = WP11_INIT_AES_ECB_ENC; + break; + } + #endif #endif default: (void)type; @@ -1516,6 +1530,26 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, *pulEncryptedDataLen = encDataLen; break; #endif + #ifdef HAVE_AESECB + case CKM_AES_ECB: + if (!WP11_Session_IsOpInitialized(session, WP11_INIT_AES_ECB_ENC)) + return CKR_OPERATION_NOT_INITIALIZED; + + encDataLen = (word32)ulDataLen; + if (pEncryptedData == NULL) { + *pulEncryptedDataLen = encDataLen; + return CKR_OK; + } + if (encDataLen > (word32)*pulEncryptedDataLen) + return CKR_BUFFER_TOO_SMALL; + + ret = WP11_AesEcb_Encrypt(pData, (int)ulDataLen, pEncryptedData, + &encDataLen, obj, session); + if (ret < 0) + return CKR_FUNCTION_FAILED; + *pulEncryptedDataLen = encDataLen; + break; + #endif #endif default: (void)ret; @@ -1926,6 +1960,19 @@ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, break; } #endif + #ifdef HAVE_AESECB + case CKM_AES_ECB: { + if (type != CKK_AES) + return CKR_KEY_TYPE_INCONSISTENT; + if (pMechanism->pParameter != NULL) + return CKR_MECHANISM_PARAM_INVALID; + if (pMechanism->ulParameterLen != 0) + return CKR_MECHANISM_PARAM_INVALID; + + init = WP11_INIT_AES_ECB_DEC; + break; + } + #endif #endif default: (void)type; @@ -2131,6 +2178,26 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, *pulDataLen = decDataLen; break; #endif + #ifdef HAVE_AESECB + case CKM_AES_ECB: + if (!WP11_Session_IsOpInitialized(session, WP11_INIT_AES_ECB_DEC)) + return CKR_OPERATION_NOT_INITIALIZED; + + decDataLen = (word32)ulEncryptedDataLen; + if (pData == NULL) { + *pulDataLen = decDataLen; + return CKR_OK; + } + if (decDataLen > (word32)*pulDataLen) + return CKR_BUFFER_TOO_SMALL; + + ret = WP11_AesEcb_Decrypt(pEncryptedData, (int)ulEncryptedDataLen, + pData, &decDataLen, obj, session); + if (ret < 0) + return CKR_FUNCTION_FAILED; + *pulDataLen = decDataLen; + break; + #endif #endif default: (void)decDataLen; diff --git a/src/internal.c b/src/internal.c index 43ef2a7..321d2cd 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4832,7 +4832,7 @@ int WP11_Session_SetCcmParams(WP11_Session* session, int dataSz, return ret; } -#endif /* HAVE_AESGCM */ +#endif /* HAVE_AESCCM */ #endif /* !NO_AES */ /** @@ -8660,6 +8660,94 @@ int WP11_AesCcm_Decrypt(unsigned char* enc, word32 encSz, unsigned char* dec, return ret; } #endif /* HAVE_AESCCM */ + +#ifdef HAVE_AESECB +/** + * Encrypt plain text with AES-ECB. + * Output buffer must be large enough to hold all data. + * + * @param plain [in] Plain text. + * @param plainSz [in] Length of plain text in bytes. + * @param enc [in] Buffer to hold encrypted data. + * @param encSz [in,out] On in, length of buffer in bytes. + * On out, length of encrypted data including + * authentication tag in bytes. + * @param secret [in] Secret key object. + * @param session [in] Session object. + * @return -ve on encryption failure. + * 0 on success. + */ +int WP11_AesEcb_Encrypt(unsigned char* plain, word32 plainSz, + unsigned char* enc, word32* encSz, WP11_Object* secret, + WP11_Session* session) +{ + int ret; + Aes aes; + WP11_Data* key; + + ret = wc_AesInit(&aes, NULL, session->devId); + if (ret == 0) { + if (secret->onToken) + WP11_Lock_LockRO(secret->lock); + key = &secret->data.symmKey; + ret = wc_AesSetKey(&aes, key->data, key->len, NULL, AES_ENCRYPTION); + if (secret->onToken) + WP11_Lock_UnlockRO(secret->lock); + + if (ret == 0) + ret = wc_AesEcbEncrypt(&aes, enc, plain, plainSz); + if (ret == 0) + *encSz = plainSz; + + wc_AesFree(&aes); + } + + return ret; +} + +/** + * Decrypt data with AES-ECB. + * Output buffer must be large enough to hold all decrypted data. + * + * @param enc [in] Encrypted data. + * @param encSz [in] Length of encrypted data in bytes. + * @param dec [in] Buffer to hold decrypted data. + * @param decSz [in,out] On in, length of buffer in bytes. + * On out, length of decrypted data in bytes. + * @param session [in] Session object holding Aes object. + * @return -ve on decryption failure. + * 0 on success. + */ +int WP11_AesEcb_Decrypt(unsigned char* enc, word32 encSz, unsigned char* dec, + word32* decSz, WP11_Object* secret, + WP11_Session* session) +{ + int ret; + Aes aes; + WP11_Data* key; + + ret = wc_AesInit(&aes, NULL, session->devId); + if (ret == 0) { + if (secret->onToken) + WP11_Lock_LockRO(secret->lock); + key = &secret->data.symmKey; + ret = wc_AesSetKey(&aes, key->data, key->len, NULL, AES_DECRYPTION); + if (secret->onToken) + WP11_Lock_UnlockRO(secret->lock); + + if (ret == 0) + ret = wc_AesEcbDecrypt(&aes, dec, enc, encSz); + + if (ret == 0) { + *decSz = encSz; + } + + wc_AesFree(&aes); + } + + return ret; +} +#endif /* HAVE_AESECB */ #endif /* !NO_AES */ #ifndef NO_HMAC diff --git a/src/slot.c b/src/slot.c index 16cee00..417b409 100644 --- a/src/slot.c +++ b/src/slot.c @@ -249,6 +249,9 @@ static CK_MECHANISM_TYPE mechanismList[] = { #ifdef HAVE_AESCCM CKM_AES_CCM, #endif +#ifdef HAVE_AESECB + CKM_AES_ECB, +#endif #endif #ifndef NO_HMAC #ifndef NO_MD5 @@ -390,6 +393,12 @@ static CK_MECHANISM_INFO aesCcmMechInfo = { 16, 32, CKF_ENCRYPT | CKF_DECRYPT }; #endif +#ifdef HAVE_AESECB +/* Info on AES-ECB mechanism. */ +static CK_MECHANISM_INFO aesEcbMechInfo = { + 16, 32, CKF_ENCRYPT | CKF_DECRYPT +}; +#endif #endif #ifndef NO_HMAC #ifndef NO_MD5 @@ -512,6 +521,11 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, XMEMCPY(pInfo, &aesCcmMechInfo, sizeof(CK_MECHANISM_INFO)); break; #endif +#ifdef HAVE_AESECB + case CKM_AES_ECB: + XMEMCPY(pInfo, &aesEcbMechInfo, sizeof(CK_MECHANISM_INFO)); + break; +#endif #endif #ifndef NO_HMAC #ifndef NO_MD5 diff --git a/tests/pkcs11test.c b/tests/pkcs11test.c index 619d604..65158de 100644 --- a/tests/pkcs11test.c +++ b/tests/pkcs11test.c @@ -7138,6 +7138,99 @@ static CK_RV test_aes_ccm_gen_key(void* args) } #endif /* HAVE_AESCCM */ + +#ifdef HAVE_AESECB +static CK_RV test_aes_ecb_encdec(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE key) +{ + CK_RV ret; + byte plain[32]; + byte enc[32]; + byte dec[32]; + CK_ULONG plainSz, encSz, decSz; + CK_MECHANISM mech; + + memset(plain, 9, sizeof(plain)); + plainSz = sizeof(plain); + encSz = sizeof(enc); + decSz = sizeof(dec); + + mech.mechanism = CKM_AES_ECB; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + ret = funcList->C_EncryptInit(session, &mech, key); + CHECK_CKR(ret, "AES-ECB Encrypt Init"); + if (ret == CKR_OK) { + encSz = 0; + ret = funcList->C_Encrypt(session, plain, plainSz, NULL, &encSz); + CHECK_CKR(ret, "AES-ECB Encrypt"); + } + if (ret == CKR_OK && encSz != plainSz) { + ret = -1; + CHECK_CKR(ret, "AES-ECB Encrypt encrypted length"); + } + if (ret == CKR_OK) { + encSz = 0; + ret = funcList->C_Encrypt(session, plain, plainSz, enc, &encSz); + CHECK_CKR_FAIL(ret, CKR_BUFFER_TOO_SMALL, "AES-ECB Encrypt"); + encSz = sizeof(enc); + } + if (ret == CKR_OK) { + ret = funcList->C_Encrypt(session, plain, plainSz, enc, &encSz); + CHECK_CKR(ret, "AES-ECB Encrypt"); + } + if (ret == CKR_OK && encSz != plainSz) { + ret = -1; + CHECK_CKR(ret, "AES-ECB Encrypt Result not correct length"); + } + if (ret == CKR_OK) { + ret = funcList->C_DecryptInit(session, &mech, key); + CHECK_CKR(ret, "AES-ECB Decrypt Init"); + } + if (ret == CKR_OK) { + decSz = 0; + ret = funcList->C_Decrypt(session, enc, encSz, NULL, &decSz); + CHECK_CKR(ret, "AES-ECB Decrypt"); + } + if (ret == CKR_OK && decSz != plainSz) { + ret = -1; + CHECK_CKR(ret, "AES-ECB Decrypt decrypted length"); + } + if (ret == CKR_OK) { + decSz = 0; + ret = funcList->C_Decrypt(session, enc, encSz, dec, &decSz); + CHECK_CKR_FAIL(ret, CKR_BUFFER_TOO_SMALL, "AES-ECB Decrypt"); + decSz = sizeof(dec); + } + if (ret == CKR_OK) { + ret = funcList->C_Decrypt(session, enc, encSz, dec, &decSz); + CHECK_CKR(ret, "AES-ECB Decrypt"); + } + if (ret == CKR_OK) { + if (decSz != plainSz || XMEMCMP(plain, dec, decSz) != 0) { + ret = -1; + CHECK_CKR(ret, "AES-ECB Decrypted data match plain text"); + } + } + + return ret; +} + +static CK_RV test_aes_ecb_gen_key(void* args) +{ + CK_SESSION_HANDLE session = *(CK_SESSION_HANDLE*)args; + CK_RV ret; + CK_OBJECT_HANDLE key; + + ret = gen_aes_key(session, 16, NULL, 0, 0, &key); + if (ret == CKR_OK) + ret = test_aes_ecb_encdec(session, key); + + return ret; +} + +#endif /* HAVE_AESECB */ #endif #ifndef NO_HMAC @@ -8198,6 +8291,9 @@ static TEST_FUNC testFunc[] = { #ifdef HAVE_AESCCM PKCS11TEST_FUNC_SESS_DECL(test_aes_ccm_gen_key), #endif +#ifdef HAVE_AESECB + PKCS11TEST_FUNC_SESS_DECL(test_aes_ecb_gen_key), +#endif #endif /* !NO_AES */ #ifndef NO_HMAC #ifndef NO_MD5 diff --git a/wolfpkcs11/internal.h b/wolfpkcs11/internal.h index ca2bfc9..40f1ffb 100644 --- a/wolfpkcs11/internal.h +++ b/wolfpkcs11/internal.h @@ -118,6 +118,8 @@ extern "C" { #define WP11_INIT_AES_CBC_PAD_DEC 0x0006 #define WP11_INIT_AES_CCM_ENC 0x0007 #define WP11_INIT_AES_CCM_DEC 0x0008 +#define WP11_INIT_AES_ECB_ENC 0x0009 +#define WP11_INIT_AES_ECB_DEC 0x000A #define WP11_INIT_HMAC_SIGN 0x0010 #define WP11_INIT_HMAC_VERIFY 0x0011 #define WP11_INIT_RSA_X_509_ENC 0x0020 @@ -403,6 +405,12 @@ int WP11_AesCcm_Encrypt(unsigned char* plain, word32 plainSz, int WP11_AesCcm_Decrypt(unsigned char* enc, word32 encSz, unsigned char* dec, word32* decSz, WP11_Object* secret, WP11_Session* session); +int WP11_AesEcb_Encrypt(unsigned char* plain, word32 plainSz, + unsigned char* enc, word32* encSz, WP11_Object* secret, + WP11_Session* session); +int WP11_AesEcb_Decrypt(unsigned char* enc, word32 encSz, unsigned char* dec, + word32* decSz, WP11_Object* secret, + WP11_Session* session); int WP11_Hmac_SigLen(WP11_Session* session); int WP11_Hmac_Init(CK_MECHANISM_TYPE mechanism, WP11_Object* secret, diff --git a/wolfpkcs11/pkcs11.h b/wolfpkcs11/pkcs11.h index b046f78..5c7a2a7 100644 --- a/wolfpkcs11/pkcs11.h +++ b/wolfpkcs11/pkcs11.h @@ -236,6 +236,7 @@ extern "C" { #define CKM_AES_CBC_PAD 0x00001085UL #define CKM_AES_GCM 0x00001087UL #define CKM_AES_CCM 0x00001088UL +#define CKM_AES_ECB 0x000001081L #define CKR_OK 0x00000000UL #define CKR_CANCEL 0x00000001UL