diff -Naur softhsm-2.0.0b1-orig/aes_wrap_key_with_pad/openssl-diff softhsm-2.0.0b1/aes_wrap_key_with_pad/openssl-diff --- softhsm-2.0.0b1-orig/aes_wrap_key_with_pad/openssl-diff 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/aes_wrap_key_with_pad/openssl-diff 1969-12-31 19:00:00.000000000 -0500 @@ -1,297 +0,0 @@ ---- aes.h-dist 2013-02-05 12:58:59.000000000 +0100 -+++ aes.h 2013-12-21 23:23:32.000000000 +0100 -@@ -140,6 +140,12 @@ - int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, - unsigned char *out, - const unsigned char *in, unsigned int inlen); -+int AES_wrap_key_withpad(AES_KEY *key, const unsigned char *icv, -+ unsigned char *out, -+ const unsigned char *in, unsigned int inlen); -+int AES_unwrap_key_withpad(AES_KEY *key, const unsigned char *icv, -+ unsigned char *out, -+ const unsigned char *in, unsigned int inlen); - - #ifdef __cplusplus - } ---- aes_wrap.c-dist 2013-02-05 00:40:11.000000000 +0100 -+++ aes_wrap.c 2013-12-21 23:41:48.000000000 +0100 -@@ -54,11 +54,99 @@ - #include "cryptlib.h" - #include - #include -+#include - - static const unsigned char default_iv[] = { - 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, - }; - -+/* Added RFC 5649 support from OpenSSL #2204 contribution by Attaullah Baig */ -+ -+static const unsigned char alternate_iv[] = { -+ 0xA6, 0x59, 0x59, 0xA6, -+}; -+ -+static int aes_unwrap_key(AES_KEY *key, const unsigned char *iv, -+ unsigned char *out, -+ const unsigned char *in, unsigned int inlen, unsigned char *a_iv); -+ -+int AES_wrap_key_withpad(AES_KEY *key, const unsigned char *icv, -+ unsigned char *out, -+ const unsigned char *in, unsigned int inlen) -+ { -+ int len, nlen, ret = -1; -+ unsigned char *input, iv[8]; -+ -+ if (!inlen) -+ return -1; -+ len = inlen + (inlen % 8 == 0 ? 0 : (8 - inlen % 8)); -+ nlen = htonl(inlen); -+ -+ input = OPENSSL_malloc(len + 8); -+ if (!input) -+ return -1; -+ memset(input, 0, len + 8); -+ if (!icv) -+ icv = alternate_iv; -+ memcpy(iv, icv, 4); -+ memcpy(iv + 4, (unsigned char *) &nlen, 4); -+ -+ if (len == 8) { -+ memcpy(input, iv, 8); -+ memcpy(input + 8, in, inlen); -+ AES_encrypt(input, out, key); -+ ret = 8 + 8; -+ } else { -+ memcpy(input, in, inlen); -+ ret = AES_wrap_key(key, iv, out, input, len); -+ } -+ OPENSSL_cleanse(input, len); -+ OPENSSL_free(input); -+ return ret; -+} -+ -+int AES_unwrap_key_withpad(AES_KEY *key, const unsigned char *icv, -+ unsigned char *out, -+ const unsigned char *in, unsigned int inlen) -+ { -+ int len, padlen; -+ unsigned char a_iv[8], zero_iv[8]; -+ -+ if (inlen & 0x7) -+ return -1; -+ if (inlen < 16) -+ return -1; -+ -+ if (inlen == 16) { -+ AES_decrypt(in, out, key); -+ memcpy(a_iv, out, 8); -+ memmove(out, out + 8, 8); -+ } else { -+ if (aes_unwrap_key(key, NULL, out, in, inlen, a_iv) <= 0) -+ return -1; -+ } -+ -+ if (!icv) -+ icv = alternate_iv; -+ if (memcmp(a_iv, icv, 4)) -+ return -1; -+ -+ memcpy((unsigned char *) &len, a_iv + 4, 4); -+ len = ntohl(len); -+ inlen -= 8; -+ -+ if (len > inlen || len <= (inlen - 8)) -+ return -1; -+ -+ padlen = inlen - len; -+ -+ memset(zero_iv, 0, 8); -+ if (padlen && memcmp(zero_iv, out + len, padlen)) -+ return -1; -+ -+ return len; -+} -+ - int AES_wrap_key(AES_KEY *key, const unsigned char *iv, - unsigned char *out, - const unsigned char *in, unsigned int inlen) -@@ -96,17 +184,18 @@ - return inlen + 8; - } - --int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, -+static int aes_unwrap_key(AES_KEY *key, const unsigned char *iv, - unsigned char *out, -- const unsigned char *in, unsigned int inlen) -+ const unsigned char *in, unsigned int inlen, unsigned char *a_iv) - { - unsigned char *A, B[16], *R; - unsigned int i, j, t; -- inlen -= 8; -+ - if (inlen & 0x7) - return -1; -- if (inlen < 8) -+ if (inlen < 16) - return -1; -+ inlen -= 8; - A = B; - t = 6 * (inlen >> 3); - memcpy(A, in, 8); -@@ -128,16 +217,27 @@ - memcpy(R, B + 8, 8); - } - } -- if (!iv) -- iv = default_iv; -- if (memcmp(A, iv, 8)) -+ if (a_iv) -+ memcpy(a_iv, A, 8); -+ else { -+ if (!iv) -+ iv = default_iv; -+ if (memcmp(A, iv, 8)) - { -- OPENSSL_cleanse(out, inlen); -- return 0; -+ OPENSSL_cleanse(out, inlen); -+ return 0; - } -+ } - return inlen; - } - -+int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, -+ unsigned char *out, -+ const unsigned char *in, unsigned int inlen) -+ { -+ return aes_unwrap_key(key, iv, out, in, inlen, NULL); -+ } -+ - #ifdef AES_WRAP_TEST - - int AES_wrap_unwrap_test(const unsigned char *kek, int keybits, -@@ -147,23 +247,31 @@ - { - unsigned char *otmp = NULL, *ptmp = NULL; - int r, ret = 0; -- AES_KEY wctx; -- otmp = OPENSSL_malloc(keylen + 8); -- ptmp = OPENSSL_malloc(keylen); -+ AES_KEY ectx, dctx; -+ -+ otmp = OPENSSL_malloc(keylen + 16); -+ ptmp = OPENSSL_malloc(keylen + 16); - if (!otmp || !ptmp) - return 0; -- if (AES_set_encrypt_key(kek, keybits, &wctx)) -+ -+ if (AES_set_encrypt_key(kek, keybits, &ectx)) - goto err; -- r = AES_wrap_key(&wctx, iv, otmp, key, keylen); -+ if (eout && keylen % 8 == 0) -+ r = AES_wrap_key(&ectx, iv, otmp, key, keylen); -+ else -+ r = AES_wrap_key_withpad(&ectx, iv, otmp, key, keylen); - if (r <= 0) - goto err; - - if (eout && memcmp(eout, otmp, keylen)) - goto err; - -- if (AES_set_decrypt_key(kek, keybits, &wctx)) -+ if (AES_set_decrypt_key(kek, keybits, &dctx)) - goto err; -- r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r); -+ if (eout && keylen % 8 == 0) -+ r = AES_unwrap_key(&dctx, iv, ptmp, otmp, r); -+ else -+ r = AES_unwrap_key_withpad(&dctx, iv, ptmp, otmp, r); - - if (memcmp(key, ptmp, keylen)) - goto err; -@@ -182,6 +290,8 @@ - - - -+static const char rnd_seed[] = "string to make the random number generator think it has entropy"; -+ - int main(int argc, char **argv) - { - -@@ -192,6 +302,12 @@ - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - }; - -+static const unsigned char kek1[] = { -+ 0x58, 0x40, 0xdf, 0x6e, 0x29, 0xb0, 0x2a, 0xf1, -+ 0xab, 0x49, 0x3b, 0x70, 0x5b, 0xf1, 0x6e, 0xa1, -+ 0xae, 0x83, 0x38, 0xf4, 0xdc, 0xc1, 0x76, 0xa8 -+}; -+ - static const unsigned char key[] = { - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, -@@ -199,6 +315,28 @@ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - }; - -+static const unsigned char key1[] = { -+ 0xc3, 0x7b, 0x7e, 0x64, 0x92, 0x58, 0x43, 0x40, -+ 0xbe, 0xd1, 0x22, 0x07, 0x80, 0x89, 0x41, 0x15, -+ 0x50, 0x68, 0xf7, 0x38 -+}; -+ -+static const unsigned char key2[] = { -+ 0x46, 0x6f, 0x72, 0x50, 0x61, 0x73, 0x69 -+}; -+ -+static const unsigned char ewrap1[] = { -+ 0x13, 0x8b, 0xde, 0xaa, 0x9b, 0x8f, 0xa7, 0xfc, -+ 0x61, 0xf9, 0x77, 0x42, 0xe7, 0x22, 0x48, 0xee, -+ 0x5a, 0xe6, 0xae, 0x53, 0x60, 0xd1, 0xae, 0x6a, -+ 0x5f, 0x54, 0xf3, 0x73, 0xfa, 0x54, 0x3b, 0x6a -+}; -+ -+static const unsigned char ewrap2[] = { -+ 0xaf, 0xbe, 0xb0, 0xf0, 0x7d, 0xfb, 0xf5, 0x41, -+ 0x92, 0x00, 0xf2, 0xcc, 0xb5, 0x0b, 0xb2, 0x4f -+}; -+ - static const unsigned char e1[] = { - 0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47, - 0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82, -@@ -240,7 +378,21 @@ - }; - - AES_KEY wctx, xctx; -- int ret; -+ int ret, i; -+ unsigned char *sample; -+ int rounds = 100; -+ -+ sample = OPENSSL_malloc(rounds); -+ RAND_seed(rnd_seed, sizeof rnd_seed); -+ RAND_pseudo_bytes(sample, rounds); -+ -+ for (i = 1; i < rounds; i++) -+ { -+ ret = AES_wrap_unwrap_test(kek, 128, NULL, NULL, sample, i); -+ printf("Key test result for %d byte key %d\n", i, ret); -+ } -+ OPENSSL_free(sample); -+ - ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16); - fprintf(stderr, "Key test result %d\n", ret); - ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16); -@@ -253,6 +405,10 @@ - fprintf(stderr, "Key test result %d\n", ret); - ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32); - fprintf(stderr, "Key test result %d\n", ret); -+ ret = AES_wrap_unwrap_test(kek1, 192, NULL, ewrap1, key1, 20); -+ fprintf(stderr, "Key test result %d\n", ret); -+ ret = AES_wrap_unwrap_test(kek1, 192, NULL, ewrap2, key2, 7); -+ fprintf(stderr, "Key test result %d\n", ret); - } - - diff -Naur softhsm-2.0.0b1-orig/aes_wrap_key_with_pad/README softhsm-2.0.0b1/aes_wrap_key_with_pad/README --- softhsm-2.0.0b1-orig/aes_wrap_key_with_pad/README 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/aes_wrap_key_with_pad/README 2014-10-07 13:56:04.278954898 -0400 @@ -1,4 +1,7 @@ Here are the patches to add advanced AES key wrap *with pad*, aka RFC 5649, -to OpenSSL (from 0.9.8 to 1.0.1 but not the git repository) or to Botan -(1.10, not 1.11 even it should be easy). +to Botan (1.10, not 1.11 even it should be easy). PS: standardized (and approved) under the KWP name in NIST SP 800-38F. + +OpenSSL added support for RFC 5649 in commit +d31fed73e25391cd71a0de488d88724db78f6f8a and it is waiting for nearest release. +Some distributions backported the interface, e.g. Fedora and RHEL. diff -Naur softhsm-2.0.0b1-orig/m4/acx_botan_rfc5649.m4 softhsm-2.0.0b1/m4/acx_botan_rfc5649.m4 --- softhsm-2.0.0b1-orig/m4/acx_botan_rfc5649.m4 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/m4/acx_botan_rfc5649.m4 2014-10-07 13:56:04.280954950 -0400 @@ -7,6 +7,8 @@ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES" LIBS="$LIBS $CRYPTO_LIBS" + AC_DEFINE([HAVE_AES_KEY_WRAP], [1], + [Define if advanced AES key wrap without pad is supported]) AC_LANG_PUSH([C++]) AC_LINK_IFELSE([ AC_LANG_SOURCE([[ diff -Naur softhsm-2.0.0b1-orig/m4/acx_crypto_backend.m4 softhsm-2.0.0b1/m4/acx_crypto_backend.m4 --- softhsm-2.0.0b1-orig/m4/acx_crypto_backend.m4 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/m4/acx_crypto_backend.m4 2014-10-07 13:56:04.280954950 -0400 @@ -70,7 +70,7 @@ ACX_OPENSSL_GOST fi - ACX_OPENSSL_RFC5649 + ACX_OPENSSL_EVPAESWRAP AC_DEFINE_UNQUOTED( [WITH_OPENSSL], diff -Naur softhsm-2.0.0b1-orig/m4/acx_openssl_rfc5649.m4 softhsm-2.0.0b1/m4/acx_openssl_rfc5649.m4 --- softhsm-2.0.0b1-orig/m4/acx_openssl_rfc5649.m4 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/m4/acx_openssl_rfc5649.m4 2014-10-07 13:56:04.281954977 -0400 @@ -1,5 +1,5 @@ -AC_DEFUN([ACX_OPENSSL_RFC5649],[ - AC_MSG_CHECKING(for OpenSSL RFC5649 support) +AC_DEFUN([ACX_OPENSSL_EVPAESWRAP],[ + AC_MSG_CHECKING(OpenSSL EVP interface for AES key wrapping) tmp_CPPFLAGS=$CPPFLAGS tmp_LIBS=$LIBS @@ -8,22 +8,42 @@ LIBS="$LIBS $CRYPTO_LIBS" AC_LANG_PUSH([C]) + AC_LINK_IFELSE([ AC_LANG_SOURCE([[ - #include + #include int main() { - AES_wrap_key_withpad(NULL, NULL, NULL, NULL, 0); + EVP_aes_128_wrap(); return 1; } ]]) ],[ - AC_MSG_RESULT([Found AES key wrap with pad]) + AC_MSG_RESULT([RFC 3349 is supported]) + AC_DEFINE([HAVE_AES_KEY_WRAP], [1], + [Define if advanced AES key wrap without pad is supported in EVP interface]) + ],[ + AC_MSG_RESULT([RFC 3349 is not supported]) + ]) + + AC_MSG_CHECKING(OpenSSL EVP interface for AES key wrapping) + AC_LINK_IFELSE([ + AC_LANG_SOURCE([[ + #include + int main() + { + EVP_aes_128_wrap_pad(); + return 1; + } + ]]) + ],[ + AC_MSG_RESULT([RFC 5649 is supported]) AC_DEFINE([HAVE_AES_KEY_WRAP_PAD], [1], - [Define if advanced AES key wrap with pad is supported]) + [Define if advanced AES key wrap with pad is supported in EVP interface]) ],[ - AC_MSG_RESULT([Cannot find AES key wrap with pad]) + AC_MSG_RESULT([RFC 5649 is not supported]) ]) + AC_LANG_POP([C]) CPPFLAGS=$tmp_CPPFLAGS diff -Naur softhsm-2.0.0b1-orig/src/lib/crypto/OSSLAES.cpp softhsm-2.0.0b1/src/lib/crypto/OSSLAES.cpp --- softhsm-2.0.0b1-orig/src/lib/crypto/OSSLAES.cpp 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/src/lib/crypto/OSSLAES.cpp 2014-10-07 13:56:04.286955108 -0400 @@ -39,180 +39,159 @@ // Wrap/Unwrap keys bool OSSLAES::wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) { - // Check key bit length; AES only supports 128, 192 or 256 bit keys - if ((key->getBitLen() != 128) && - (key->getBitLen() != 192) && - (key->getBitLen() != 256)) - { - ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen()); - +#ifdef HAVE_AES_KEY_WRAP + // RFC 3394 input length checks do not apply to RFC 5649 mode with padding + if (mode == SymWrap::AES_KEYWRAP && !checkLength(in.size(), 16, "wrap")) return false; - } - // Determine the wrapping mode - if (mode == SymWrap::AES_KEYWRAP) - { - // RFC 3394 AES key wrap - if (in.size() < 16) - { - ERROR_MSG("key data to wrap too small"); - - return false; - } - if ((in.size() % 8) != 0) - { - ERROR_MSG("key data to wrap not aligned"); - - return false; - } - - AES_KEY aesKey; - if (AES_set_encrypt_key(key->getKeyBits().const_byte_str(), - key->getBitLen(), &aesKey)) - { - ERROR_MSG("fail to setup AES wrapping key"); - - return false; - } - out.resize(in.size() + 8); - if (AES_wrap_key(&aesKey, NULL, &out[0], in.const_byte_str(), in.size()) != (int)out.size()) - { - ERROR_MSG("AES key wrap failed"); + return wrapUnwrapKey(key, mode, in, out, 1); +#else + return false; +#endif +} - out.wipe(); - return false; - } +bool OSSLAES::unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) +{ +#ifdef HAVE_AES_KEY_WRAP + // RFC 3394 algorithm produce at least 3 blocks of data + if ((mode == SymWrap::AES_KEYWRAP && !checkLength(in.size(), 24, "unwrap")) || + // RFC 5649 algorithm produce at least 2 blocks of data + (mode == SymWrap::AES_KEYWRAP_PAD && !checkLength(in.size(), 16, "unwrap"))) + return false; + return wrapUnwrapKey(key, mode, in, out, 0); +#else + return false; +#endif +} - return true; - } -#ifdef HAVE_AES_KEY_WRAP_PAD - else if (mode == SymWrap::AES_KEYWRAP_PAD) +#ifdef HAVE_AES_KEY_WRAP +// RFC 3349 wrapping and all unwrapping algorithms require aligned blocks +bool OSSLAES::checkLength(const int insize, const int minsize, const char * const operation) const +{ + if (insize < minsize) { - // RFC 5649 AES key wrap with pad - AES_KEY aesKey; - if (AES_set_encrypt_key(key->getKeyBits().const_byte_str(), - key->getBitLen(), &aesKey)) - { - ERROR_MSG("fail to setup AES wrapping key"); - - return false; - } - out.resize(in.size() + 16); - int ret = AES_wrap_key_withpad(&aesKey, NULL, &out[0], in.const_byte_str(), in.size()); - if (ret <= 0) - { - ERROR_MSG("AES key wrap failed"); - - out.wipe(); - return false; - } - out.resize(ret); - - return true; + ERROR_MSG("key data to %s too small", operation); + return false; } -#endif - else + if ((insize % 8) != 0) { - ERROR_MSG("unknown AES key wrap mode %i", mode); - + ERROR_MSG("key data to %s not aligned", operation); return false; } + return true; } -bool OSSLAES::unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) +const EVP_CIPHER* OSSLAES::getWrapCipher(const SymWrap::Type mode, const SymmetricKey* key) const { - // Check key bit length; AES only supports 128, 192 or 256 bit keys + if (key == NULL) + return NULL; + + // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys if ((key->getBitLen() != 128) && (key->getBitLen() != 192) && (key->getBitLen() != 256)) { ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen()); - return false; + return NULL; } - // Determine the unwrapping mode + // Determine the un/wrapping mode if (mode == SymWrap::AES_KEYWRAP) { // RFC 3394 AES key wrap - if (in.size() < 24) - { - ERROR_MSG("key data to unwrap too small"); - - return false; - } - if ((in.size() % 8) != 0) - { - ERROR_MSG("key data to unwrap not aligned"); - - return false; - } - - AES_KEY aesKey; - if (AES_set_decrypt_key(key->getKeyBits().const_byte_str(), - key->getBitLen(), &aesKey)) - { - ERROR_MSG("fail to setup AES unwrapping key"); - - return false; - } - out.resize(in.size() - 8); - if (AES_unwrap_key(&aesKey, NULL, &out[0], in.const_byte_str(), in.size()) != (int)out.size()) + switch(key->getBitLen()) { - ERROR_MSG("AES key unwrap failed"); - - out.wipe(); - return false; - } - - return true; + case 128: + return EVP_aes_128_wrap(); + case 192: + return EVP_aes_192_wrap(); + case 256: + return EVP_aes_256_wrap(); + }; } #ifdef HAVE_AES_KEY_WRAP_PAD else if (mode == SymWrap::AES_KEYWRAP_PAD) { // RFC 5649 AES key wrap with pad - if (in.size() < 16) + switch(key->getBitLen()) { - ERROR_MSG("key data to unwrap too small"); + case 128: + return EVP_aes_128_wrap_pad(); + case 192: + return EVP_aes_192_wrap_pad(); + case 256: + return EVP_aes_256_wrap_pad(); + }; + } +#endif - return false; - } - if ((in.size() % 8) != 0) - { - ERROR_MSG("key data to unwrap not aligned"); + ERROR_MSG("unknown AES key wrap mode %i", mode); + return NULL; +} - return false; - } +// EVP wrapping/unwrapping +// wrap = 1 -> wrapping +// wrap = 0 -> unwrapping +bool OSSLAES::wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out, const int wrap) const +{ + const char *prefix = ""; + if (wrap == 0) + prefix = "un"; + + // Determine the cipher method + const EVP_CIPHER* cipher = getWrapCipher(mode, key); + if (cipher == NULL) + { + ERROR_MSG("Failed to get EVP %swrap cipher", prefix); + return false; + } - AES_KEY aesKey; - if (AES_set_decrypt_key(key->getKeyBits().const_byte_str(), - key->getBitLen(), &aesKey)) - { - ERROR_MSG("fail to setup AES unwrapping key"); + // Allocate the EVP context + EVP_CIPHER_CTX* pWrapCTX = (EVP_CIPHER_CTX*) salloc(sizeof(EVP_CIPHER_CTX)); + if (pWrapCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX"); + return false; + } + EVP_CIPHER_CTX_init(pWrapCTX); + EVP_CIPHER_CTX_set_flags(pWrapCTX, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); - return false; - } - out.resize(in.size() - 8); - int ret = AES_unwrap_key_withpad(&aesKey, NULL, &out[0], in.const_byte_str(), in.size()); - if (ret <= 0) - { - ERROR_MSG("AES key unwrap failed"); + int rv = EVP_CipherInit_ex(pWrapCTX, cipher, NULL, (unsigned char*) key->getKeyBits().const_byte_str(), NULL, wrap); + if (rv) + // Padding is handled by cipher mode separately + rv = EVP_CIPHER_CTX_set_padding(pWrapCTX, 0); + if (!rv) + { + ERROR_MSG("Failed to initialise EVP cipher %swrap operation", prefix); - out.wipe(); - return false; - } - out.resize(ret); + EVP_CIPHER_CTX_cleanup(pWrapCTX); + sfree(pWrapCTX); + return false; + } - return true; + // 1 input byte could be expanded to two AES blocks + out.resize(in.size() + 2 * EVP_CIPHER_CTX_block_size(pWrapCTX) - 1); + int outLen = 0; + int curBlockLen = 0; + rv = EVP_CipherUpdate(pWrapCTX, &out[0], &curBlockLen, in.const_byte_str(), in.size()); + if (rv == 1) { + outLen = curBlockLen; + rv = EVP_CipherFinal_ex(pWrapCTX, &out[0], &curBlockLen); } -#endif - else + if (rv != 1) { - ERROR_MSG("unknown AES key wrap mode %i", mode); + ERROR_MSG("Failed EVP %swrap operation", prefix); + EVP_CIPHER_CTX_cleanup(pWrapCTX); + sfree(pWrapCTX); return false; } + outLen += curBlockLen; + out.resize(outLen); + return true; } +#endif const EVP_CIPHER* OSSLAES::getCipher() const { @@ -264,4 +243,3 @@ // The block size is 128 bits return 128 >> 3; } - diff -Naur softhsm-2.0.0b1-orig/src/lib/crypto/OSSLAES.h softhsm-2.0.0b1/src/lib/crypto/OSSLAES.h --- softhsm-2.0.0b1-orig/src/lib/crypto/OSSLAES.h 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/src/lib/crypto/OSSLAES.h 2014-10-07 13:56:04.287955134 -0400 @@ -55,6 +55,9 @@ protected: // Return the right EVP cipher for the operation virtual const EVP_CIPHER* getCipher() const; + const EVP_CIPHER* getWrapCipher(const SymWrap::Type mode, const SymmetricKey* key) const; + bool wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out, const int wrap) const; + bool checkLength(const int insize, const int minsize, const char * const operation) const; }; #endif // !_SOFTHSM_V2_OSSLAES_H diff -Naur softhsm-2.0.0b1-orig/src/lib/crypto/test/AESTests.cpp softhsm-2.0.0b1/src/lib/crypto/test/AESTests.cpp --- softhsm-2.0.0b1-orig/src/lib/crypto/test/AESTests.cpp 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/src/lib/crypto/test/AESTests.cpp 2014-10-07 13:56:04.287955134 -0400 @@ -594,36 +594,87 @@ } } -void AESTests::testWrap() +void AESTests::testWrap(const char testKeK[][128], const char testKey[][128], const char testCt[][128], const int testCnt, SymWrap::Type mode) { - char testKeK[33] = "000102030405060708090A0B0C0D0E0F"; - char testKey[33] = "00112233445566778899AABBCCDDEEFF"; + for (int i = 0; i < testCnt; i++) + { + ByteString kekData(testKeK[i]); + ByteString keyData(testKey[i]); + + AESKey aesKeK(kekData.size() * 8); + CPPUNIT_ASSERT(aesKeK.setKeyBits(kekData)); + + ByteString wrapped; + ByteString expectedCt(testCt[i]); + CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, mode, keyData, wrapped)); + CPPUNIT_ASSERT(wrapped.size() == expectedCt.size()); + CPPUNIT_ASSERT(wrapped == expectedCt); + + ByteString unwrapped; + CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, mode, wrapped, unwrapped)); + CPPUNIT_ASSERT(unwrapped.size() == keyData.size()); + CPPUNIT_ASSERT(unwrapped == keyData); +/* + #ifdef HAVE_AES_KEY_WRAP_PAD + keyData.resize(20); + ByteString padwrapped; + CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, keyData, padwrapped)); + CPPUNIT_ASSERT(padwrapped.size() == 32); + + ByteString padunwrapped; + CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, padwrapped, padunwrapped)); + CPPUNIT_ASSERT(padunwrapped == keyData); + #endif +*/ + } +} + +// RFC 3394 tests +void AESTests::testWrapWoPad() +{ + char testKeK[][128] = { + "000102030405060708090A0B0C0D0E0F", // section 4.1 + "000102030405060708090A0B0C0D0E0F1011121314151617", // section 4.2 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.3 + "000102030405060708090A0B0C0D0E0F1011121314151617", // section 4.4 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.5 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.6 + }; + char testKey[][128] = { + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F" + }; + char testCt[][128] = { + "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5", + "96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D", + "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7", + "031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2", + "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1", + "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21" + }; + + testWrap(testKeK, testKey, testCt, sizeof(testKeK) / 128, SymWrap::AES_KEYWRAP); +} + +// RFC 5649 tests +void AESTests::testWrapPad() +{ + char testKeK[][128] = { + "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8", // section 6 example 1 + "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8", // section 6 example 2 + }; + char testKey[][128] = { + "C37B7E6492584340BED12207808941155068F738", + "466F7250617369" + }; + char testCt[][128] = { + "138BDEAA9B8FA7FC61F97742E72248EE5AE6AE5360D1AE6A5F54F373FA543B6A", + "AFBEB0F07DFBF5419200F2CCB50BB24F" + }; - ByteString kekData(testKeK); - ByteString keyData(testKey); - ByteString wrapped; - - AESKey aesKeK(128); - CPPUNIT_ASSERT(aesKeK.setKeyBits(kekData)); - - CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, SymWrap::AES_KEYWRAP, keyData, wrapped)); - CPPUNIT_ASSERT(wrapped.size() == keyData.size() + 8); - - ByteString expected("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5"); - CPPUNIT_ASSERT(wrapped == expected); - - ByteString unwrapped; - CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, SymWrap::AES_KEYWRAP, wrapped, unwrapped)); - CPPUNIT_ASSERT(unwrapped == keyData); - -#ifdef HAVE_AES_KEY_WRAP_PAD - keyData.resize(20); - ByteString padwrapped; - CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, keyData, padwrapped)); - CPPUNIT_ASSERT(padwrapped.size() == 32); - - ByteString padunwrapped; - CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, padwrapped, padunwrapped)); - CPPUNIT_ASSERT(padunwrapped == keyData); -#endif + testWrap(testKeK, testKey, testCt, sizeof(testKeK) / 128, SymWrap::AES_KEYWRAP_PAD); } diff -Naur softhsm-2.0.0b1-orig/src/lib/crypto/test/AESTests.h softhsm-2.0.0b1/src/lib/crypto/test/AESTests.h --- softhsm-2.0.0b1-orig/src/lib/crypto/test/AESTests.h 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/src/lib/crypto/test/AESTests.h 2014-10-07 13:56:04.288955161 -0400 @@ -42,14 +42,20 @@ CPPUNIT_TEST(testBlockSize); CPPUNIT_TEST(testCBC); CPPUNIT_TEST(testECB); - CPPUNIT_TEST(testWrap); +#ifdef HAVE_AES_KEY_WRAP + CPPUNIT_TEST(testWrapWoPad); +#endif +#ifdef HAVE_AES_KEY_WRAP_PAD + CPPUNIT_TEST(testWrapPad); +#endif CPPUNIT_TEST_SUITE_END(); public: void testBlockSize(); void testCBC(); void testECB(); - void testWrap(); + void testWrapWoPad(); + void testWrapPad(); void setUp(); void tearDown(); @@ -57,6 +63,7 @@ private: // AES instance SymmetricAlgorithm* aes; + void testWrap(const char testKeK[][128], const char testKey[][128], const char testCt[][128], const int testCnt, SymWrap::Type mode); }; #endif // !_SOFTHSM_V2_AESTESTS_H diff -Naur softhsm-2.0.0b1-orig/src/lib/SoftHSM.cpp softhsm-2.0.0b1/src/lib/SoftHSM.cpp --- softhsm-2.0.0b1-orig/src/lib/SoftHSM.cpp 2014-09-09 20:05:23.000000000 -0400 +++ softhsm-2.0.0b1/src/lib/SoftHSM.cpp 2014-10-07 13:56:04.284955056 -0400 @@ -4909,12 +4909,14 @@ size_t bb = 8; CK_ULONG wrappedlen = keydata.size(); switch(pMechanism->mechanism) { +#ifdef HAVE_AES_KEY_WRAP case CKM_AES_KEY_WRAP: if ((wrappedlen < 16) || ((wrappedlen % 8) != 0)) return CKR_KEY_SIZE_RANGE; algo = SymAlgo::AES; mode = SymWrap::AES_KEYWRAP; break; +#endif #ifdef HAVE_AES_KEY_WRAP_PAD case CKM_AES_KEY_WRAP_PAD: algo = SymAlgo::AES; @@ -5051,7 +5053,9 @@ // Check the mechanism, only accept advanced AES key wrapping and RSA switch(pMechanism->mechanism) { +#ifdef HAVE_AES_KEY_WRAP case CKM_AES_KEY_WRAP: +#endif #ifdef HAVE_AES_KEY_WRAP_PAD case CKM_AES_KEY_WRAP_PAD: #endif @@ -5272,10 +5276,12 @@ SymWrap::Type mode = SymWrap::Unknown; size_t bb = 8; switch(pMechanism->mechanism) { +#ifdef HAVE_AES_KEY_WRAP case CKM_AES_KEY_WRAP: algo = SymAlgo::AES; mode = SymWrap::AES_KEYWRAP; break; +#endif #ifdef HAVE_AES_KEY_WRAP_PAD case CKM_AES_KEY_WRAP_PAD: algo = SymAlgo::AES; @@ -5395,6 +5401,7 @@ // Check the mechanism switch(pMechanism->mechanism) { +#ifdef HAVE_AES_KEY_WRAP case CKM_AES_KEY_WRAP: if ((ulWrappedKeyLen < 24) || ((ulWrappedKeyLen % 8) != 0)) return CKR_WRAPPED_KEY_LEN_RANGE; @@ -5403,6 +5410,7 @@ pMechanism->ulParameterLen != 0) return CKR_ARGUMENTS_BAD; break; +#endif #ifdef HAVE_AES_KEY_WRAP_PAD case CKM_AES_KEY_WRAP_PAD: if ((ulWrappedKeyLen < 16) || ((ulWrappedKeyLen % 8) != 0)) diff -Naur softhsm-2.0.0b1-orig/src/lib/test/SymmetricAlgorithmTests.h softhsm-2.0.0b1/src/lib/test/SymmetricAlgorithmTests.h --- softhsm-2.0.0b1-orig/src/lib/test/SymmetricAlgorithmTests.h 2014-09-09 20:05:14.000000000 -0400 +++ softhsm-2.0.0b1/src/lib/test/SymmetricAlgorithmTests.h 2014-10-07 13:56:04.288955161 -0400 @@ -41,7 +41,9 @@ CPPUNIT_TEST_SUITE(SymmetricAlgorithmTests); CPPUNIT_TEST(testAesEncryptDecrypt); CPPUNIT_TEST(testDesEncryptDecrypt); +#ifdef HAVE_AES_KEY_WRAP CPPUNIT_TEST(testAesWrapUnwrap); +#endif CPPUNIT_TEST(testNullTemplate); CPPUNIT_TEST_SUITE_END();