From 2ed6e88c52c2461c37cea9df7d8b5e5687c381d4 Mon Sep 17 00:00:00 2001 From: Paul Wouters Date: Wed, 8 Oct 2014 09:03:58 -0400 Subject: [PATCH] added patch files --- softhsm-v2.0.0b1-aes-key-wrap.patch | 935 ++++++++++++++++++ ...-v2.0.0b1-ckm-rsa-pkcs-oaep-key-wrap.patch | 374 +++++++ 2 files changed, 1309 insertions(+) create mode 100644 softhsm-v2.0.0b1-aes-key-wrap.patch create mode 100644 softhsm-v2.0.0b1-ckm-rsa-pkcs-oaep-key-wrap.patch diff --git a/softhsm-v2.0.0b1-aes-key-wrap.patch b/softhsm-v2.0.0b1-aes-key-wrap.patch new file mode 100644 index 0000000..40db611 --- /dev/null +++ b/softhsm-v2.0.0b1-aes-key-wrap.patch @@ -0,0 +1,935 @@ +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(); + diff --git a/softhsm-v2.0.0b1-ckm-rsa-pkcs-oaep-key-wrap.patch b/softhsm-v2.0.0b1-ckm-rsa-pkcs-oaep-key-wrap.patch new file mode 100644 index 0000000..814d336 --- /dev/null +++ b/softhsm-v2.0.0b1-ckm-rsa-pkcs-oaep-key-wrap.patch @@ -0,0 +1,374 @@ +diff -Naur softhsm-2.0.0b1-orig/src/lib/cryptoki_compat/pkcs11.h softhsm-2.0.0b1/src/lib/cryptoki_compat/pkcs11.h +--- softhsm-2.0.0b1-orig/src/lib/cryptoki_compat/pkcs11.h 2014-09-09 20:05:14.000000000 -0400 ++++ softhsm-2.0.0b1/src/lib/cryptoki_compat/pkcs11.h 2014-10-07 13:57:22.460010567 -0400 +@@ -902,6 +902,8 @@ + #define CKG_MGF1_SHA512 (0x00000004) + #define CKG_MGF1_SHA224 (0x00000005) + ++#define CKZ_DATA_SPECIFIED (0x00000001) ++ + struct ck_rsa_pkcs_oaep_params { + ck_mechanism_type_t hash_alg; + unsigned long mgf; +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-10-07 13:56:04.284955056 -0400 ++++ softhsm-2.0.0b1/src/lib/SoftHSM.cpp 2014-10-07 13:57:25.478089923 -0400 +@@ -815,7 +815,7 @@ + case CKM_RSA_PKCS_OAEP: + pInfo->ulMinKeySize = rsaMinSize; + pInfo->ulMaxKeySize = rsaMaxSize; +- pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT; ++ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; + break; + case CKM_DES_KEY_GEN: + case CKM_DES2_KEY_GEN: +@@ -1941,22 +1941,9 @@ + isRSA = true; + break; + case CKM_RSA_PKCS_OAEP: +- if (pMechanism->pParameter == NULL_PTR || +- pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) +- { +- ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS"); +- return CKR_ARGUMENTS_BAD; +- } +- if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1) +- { +- ERROR_MSG("hashAlg must be CKM_SHA_1"); +- return CKR_ARGUMENTS_BAD; +- } +- if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1) +- { +- ERROR_MSG("mgf must be CKG_MGF1_SHA1"); +- return CKR_ARGUMENTS_BAD; +- } ++ rv = MechParamCheckRSAPKCSOAEP(pMechanism); ++ if (rv != CKR_OK) ++ return rv; + + mechanism = AsymMech::RSA_PKCS_OAEP; + isRSA = true; +@@ -4969,25 +4956,42 @@ + ByteString& wrapped + ) + { +- size_t bb = 8; ++ const size_t bb = 8; + AsymAlgo::Type algo = AsymAlgo::Unknown; + AsymMech::Type mech = AsymMech::Unknown; + ++ CK_ULONG modulus_length; + switch(pMechanism->mechanism) { + case CKM_RSA_PKCS: ++ case CKM_RSA_PKCS_OAEP: + algo = AsymAlgo::RSA; +- mech = AsymMech::RSA_PKCS; +- CK_ULONG modulus_length; + if (!wrapKey->attributeExists(CKA_MODULUS_BITS)) + return CKR_GENERAL_ERROR; + modulus_length = wrapKey->getUnsignedLongValue(CKA_MODULUS_BITS, 0); + // adjust key bit length + modulus_length /= bb; ++ break; ++ ++ default: ++ return CKR_MECHANISM_INVALID; ++ } ++ ++ switch(pMechanism->mechanism) { ++ case CKM_RSA_PKCS: ++ mech = AsymMech::RSA_PKCS; + // RFC 3447 section 7.2.1 + if (keydata.size() > modulus_length - 11) + return CKR_KEY_SIZE_RANGE; + break; + ++ case CKM_RSA_PKCS_OAEP: ++ mech = AsymMech::RSA_PKCS_OAEP; ++ // SHA-1 is the only supported option ++ // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen ++ if (keydata.size() > modulus_length - 2 - 2 * 160 / 8) ++ return CKR_KEY_SIZE_RANGE; ++ break; ++ + default: + return CKR_MECHANISM_INVALID; + } +@@ -5004,6 +5008,7 @@ + + switch(pMechanism->mechanism) { + case CKM_RSA_PKCS: ++ case CKM_RSA_PKCS_OAEP: + if (getRSAPublicKey((RSAPublicKey*)publicKey, token, wrapKey) != CKR_OK) + { + cipher->recyclePublicKey(publicKey); +@@ -5050,6 +5055,7 @@ + Session* session = (Session*)handleManager->getSession(hSession); + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; + ++ CK_RV rv; + // Check the mechanism, only accept advanced AES key wrapping and RSA + switch(pMechanism->mechanism) + { +@@ -5065,6 +5071,12 @@ + pMechanism->ulParameterLen != 0) + return CKR_ARGUMENTS_BAD; + break; ++ case CKM_RSA_PKCS_OAEP: ++ rv = MechParamCheckRSAPKCSOAEP(pMechanism); ++ if (rv != CKR_OK) ++ return rv; ++ break; ++ + default: + return CKR_MECHANISM_INVALID; + } +@@ -5081,7 +5093,7 @@ + CK_BBOOL isWrapKeyPrivate = wrapKey->getBooleanValue(CKA_PRIVATE, true); + + // Check user credentials for the wrapping key +- CK_RV rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate); ++ rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate); + if (rv != CKR_OK) + { + if (rv == CKR_USER_NOT_LOGGED_IN) +@@ -5093,13 +5105,13 @@ + // Check wrapping key class and type + if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; +- if (pMechanism->mechanism == CKM_RSA_PKCS && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY) ++ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + if (pMechanism->mechanism == CKM_AES_KEY_WRAP && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; +- if (pMechanism->mechanism == CKM_RSA_PKCS && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) ++ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) + return CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + + // Check if the wrapping key can be used for wrapping +@@ -5133,8 +5145,8 @@ + CK_OBJECT_CLASS keyClass = key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED); + if (keyClass != CKO_SECRET_KEY && keyClass != CKO_PRIVATE_KEY) + return CKR_KEY_NOT_WRAPPABLE; +- // CKM_RSA_PKCS can be used only on SECRET keys: PKCS#11 2.40 draft 2 section 2.1.6 PKCS #1 v1.5 RSA +- if (pMechanism->mechanism == CKM_RSA_PKCS && keyClass != CKO_SECRET_KEY) ++ // CKM_RSA_PKCS and CKM_RSA_PKCS_OAEP can be used only on SECRET keys: PKCS#11 2.40 draft 2 section 2.1.6 PKCS #1 v1.5 RSA & section 2.1.8 PKCS #1 RSA OAEP ++ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && keyClass != CKO_SECRET_KEY) + return CKR_KEY_NOT_WRAPPABLE; + + // Verify the wrap template attribute +@@ -5338,6 +5350,12 @@ + algo = AsymAlgo::RSA; + mode = AsymMech::RSA_PKCS; + break; ++ ++ case CKM_RSA_PKCS_OAEP: ++ algo = AsymAlgo::RSA; ++ mode = AsymMech::RSA_PKCS_OAEP; ++ break; ++ + default: + return CKR_MECHANISM_INVALID; + } +@@ -5353,6 +5371,7 @@ + + switch(pMechanism->mechanism) { + case CKM_RSA_PKCS: ++ case CKM_RSA_PKCS_OAEP: + if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK) + { + cipher->recyclePrivateKey(unwrappingkey); +@@ -5398,6 +5417,7 @@ + Session* session = (Session*)handleManager->getSession(hSession); + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; + ++ CK_RV rv; + // Check the mechanism + switch(pMechanism->mechanism) + { +@@ -5424,6 +5444,11 @@ + case CKM_RSA_PKCS: + // Input length checks needs to be done later when unwrapping key is known + break; ++ case CKM_RSA_PKCS_OAEP: ++ rv = MechParamCheckRSAPKCSOAEP(pMechanism); ++ if (rv != CKR_OK) ++ return rv; ++ break; + + default: + return CKR_MECHANISM_INVALID; +@@ -5441,7 +5466,7 @@ + CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true); + + // Check user credentials +- CK_RV rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate); ++ rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate); + if (rv != CKR_OK) + { + if (rv == CKR_USER_NOT_LOGGED_IN) +@@ -5457,9 +5482,9 @@ + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; +- if (pMechanism->mechanism == CKM_RSA_PKCS && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY) ++ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; +- if (pMechanism->mechanism == CKM_RSA_PKCS && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) ++ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) + return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + + // Check if the unwrapping key can be used for unwrapping +@@ -9152,3 +9177,47 @@ + + return bOK; + } ++ ++CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism) ++{ ++ // This is a programming error ++ if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) { ++ ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism"); ++ return CKR_GENERAL_ERROR; ++ } ++ ++ if (pMechanism->pParameter == NULL_PTR || ++ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) ++ { ++ ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS"); ++ return CKR_ARGUMENTS_BAD; ++ } ++ ++ CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter; ++ if (params->hashAlg != CKM_SHA_1) ++ { ++ ERROR_MSG("hashAlg must be CKM_SHA_1"); ++ return CKR_ARGUMENTS_BAD; ++ } ++ if (params->mgf != CKG_MGF1_SHA1) ++ { ++ ERROR_MSG("mgf must be CKG_MGF1_SHA1"); ++ return CKR_ARGUMENTS_BAD; ++ } ++ if (params->source != CKZ_DATA_SPECIFIED) ++ { ++ ERROR_MSG("source must be CKZ_DATA_SPECIFIED"); ++ return CKR_ARGUMENTS_BAD; ++ } ++ if (params->pSourceData != NULL) ++ { ++ ERROR_MSG("pSourceData must be NULL"); ++ return CKR_ARGUMENTS_BAD; ++ } ++ if (params->ulSourceDataLen != 0) ++ { ++ ERROR_MSG("ulSourceDataLen must be 0"); ++ return CKR_ARGUMENTS_BAD; ++ } ++ return CKR_OK; ++} +diff -Naur softhsm-2.0.0b1-orig/src/lib/SoftHSM.h softhsm-2.0.0b1/src/lib/SoftHSM.h +--- softhsm-2.0.0b1-orig/src/lib/SoftHSM.h 2014-09-09 20:05:23.000000000 -0400 ++++ softhsm-2.0.0b1/src/lib/SoftHSM.h 2014-10-07 13:57:24.178055740 -0400 +@@ -407,5 +407,7 @@ + OSObject *unwrapKey, + ByteString &keydata + ); ++ ++ CK_RV MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism); + }; + +diff -Naur softhsm-2.0.0b1-orig/src/lib/test/AsymEncryptDecryptTests.cpp softhsm-2.0.0b1/src/lib/test/AsymEncryptDecryptTests.cpp +--- softhsm-2.0.0b1-orig/src/lib/test/AsymEncryptDecryptTests.cpp 2014-09-09 20:05:14.000000000 -0400 ++++ softhsm-2.0.0b1/src/lib/test/AsymEncryptDecryptTests.cpp 2014-10-07 13:57:22.461010593 -0400 +@@ -165,6 +165,51 @@ + CPPUNIT_ASSERT(memcmp(plainText, &recoveredText[ulRecoveredTextLen-sizeof(plainText)], sizeof(plainText)) == 0); + } + ++// Check that RSA OAEP mechanism properly validates all input parameters ++void AsymEncryptDecryptTests::rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey) ++{ ++ // This is only supported combination of parameters ++ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, CKZ_DATA_SPECIFIED, NULL_PTR, 0 }; ++ CK_MECHANISM mechanism = { CKM_RSA_PKCS_OAEP, NULL, 0 }; ++ CK_RV rv; ++ ++ rv = C_EncryptInit(hSession,&mechanism,hPublicKey); ++ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); ++ ++ mechanism.pParameter = &oaepParams; ++ rv = C_EncryptInit(hSession,&mechanism,hPublicKey); ++ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); ++ ++ mechanism.ulParameterLen = sizeof(oaepParams); ++ ++ oaepParams.hashAlg = CKM_AES_CBC; ++ rv = C_EncryptInit(hSession,&mechanism,hPublicKey); ++ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); ++ ++ oaepParams.hashAlg = CKM_SHA_1; ++ oaepParams.mgf = CKG_MGF1_SHA256; ++ rv = C_EncryptInit(hSession,&mechanism,hPublicKey); ++ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); ++ ++ oaepParams.mgf = CKG_MGF1_SHA1; ++ oaepParams.source = CKZ_DATA_SPECIFIED - 1; ++ rv = C_EncryptInit(hSession,&mechanism,hPublicKey); ++ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); ++ ++ oaepParams.source = CKZ_DATA_SPECIFIED; ++ oaepParams.pSourceData = &oaepParams; ++ rv = C_EncryptInit(hSession,&mechanism,hPublicKey); ++ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); ++ ++ oaepParams.ulSourceDataLen = sizeof(oaepParams); ++ rv = C_EncryptInit(hSession,&mechanism,hPublicKey); ++ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); ++ ++ oaepParams.pSourceData = NULL; ++ rv = C_EncryptInit(hSession,&mechanism,hPublicKey); ++ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); ++} ++ + void AsymEncryptDecryptTests::testRsaEncryptDecrypt() + { + CK_RV rv; +@@ -203,6 +248,7 @@ + rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPublicKey,hPrivateKey); + CPPUNIT_ASSERT(rv == CKR_OK); + ++ rsaOAEPParams(hSessionRO,hPublicKey); + rsaEncryptDecrypt(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey); + rsaEncryptDecrypt(CKM_RSA_X_509,hSessionRO,hPublicKey,hPrivateKey); + rsaEncryptDecrypt(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey); +diff -Naur softhsm-2.0.0b1-orig/src/lib/test/AsymEncryptDecryptTests.h softhsm-2.0.0b1/src/lib/test/AsymEncryptDecryptTests.h +--- softhsm-2.0.0b1-orig/src/lib/test/AsymEncryptDecryptTests.h 2014-09-09 20:05:14.000000000 -0400 ++++ softhsm-2.0.0b1/src/lib/test/AsymEncryptDecryptTests.h 2014-10-07 13:57:22.462010619 -0400 +@@ -52,6 +52,7 @@ + protected: + CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk); + void rsaEncryptDecrypt(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey); ++ void rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey); + }; + + #endif // !_SOFTHSM_V2_ASYMENCRYPTDECRYPTTESTS_H +diff -Naur softhsm-2.0.0b1-orig/src/lib/test/AsymWrapUnwrapTests.cpp softhsm-2.0.0b1/src/lib/test/AsymWrapUnwrapTests.cpp +--- softhsm-2.0.0b1-orig/src/lib/test/AsymWrapUnwrapTests.cpp 2014-09-09 20:05:23.000000000 -0400 ++++ softhsm-2.0.0b1/src/lib/test/AsymWrapUnwrapTests.cpp 2014-10-07 13:57:25.480089976 -0400 +@@ -155,7 +155,7 @@ + void AsymWrapUnwrapTests::rsaWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey) + { + CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 }; +- CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, 1, NULL_PTR, 0 }; ++ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, CKZ_DATA_SPECIFIED, NULL_PTR, 0 }; + CK_BYTE cipherText[2048]; + CK_ULONG ulCipherTextLen; + CK_BYTE symValue[64]; +@@ -273,4 +273,5 @@ + CPPUNIT_ASSERT(rv == CKR_OK); + + rsaWrapUnwrap(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey); ++ rsaWrapUnwrap(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey); + }