aboutsummaryrefslogtreecommitdiffstats
path: root/main/openssl/openssl-0.9.8k-padlock-sha.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/openssl/openssl-0.9.8k-padlock-sha.patch')
-rw-r--r--main/openssl/openssl-0.9.8k-padlock-sha.patch897
1 files changed, 897 insertions, 0 deletions
diff --git a/main/openssl/openssl-0.9.8k-padlock-sha.patch b/main/openssl/openssl-0.9.8k-padlock-sha.patch
new file mode 100644
index 0000000000..63b27cea36
--- /dev/null
+++ b/main/openssl/openssl-0.9.8k-padlock-sha.patch
@@ -0,0 +1,897 @@
+#
+# OpenSSL patch to support VIA C7 hash engine
+# Written by: Timo Teras <timo.teras@iki.fi>
+# based on patch by: Michal Ludvig <michal@logix.cz>
+# http://www.logix.cz/michal/devel/padlock
+#
+Index: openssl-0.9.8k/crypto/engine/eng_padlock.c
+===================================================================
+--- openssl-0.9.8k.orig/crypto/engine/eng_padlock.c 2009-07-12 19:24:42.000000000 +0300
++++ openssl-0.9.8k/crypto/engine/eng_padlock.c 2009-07-13 13:07:26.000000000 +0300
+@@ -1,10 +1,13 @@
+-/*
++/*
+ * Support for VIA PadLock Advanced Cryptography Engine (ACE)
+ * Written by Michal Ludvig <michal@logix.cz>
+ * http://www.logix.cz/michal
+ *
+- * Big thanks to Andy Polyakov for a help with optimization,
+- * assembler fixes, port to MS Windows and a lot of other
++ * SHA support by Timo Teras <timo.teras@iki.fi> based on code
++ * originally by Michal Ludvig.
++ *
++ * Big thanks to Andy Polyakov for a help with optimization,
++ * assembler fixes, port to MS Windows and a lot of other
+ * valuable work on this engine!
+ */
+
+@@ -66,6 +69,13 @@
+ #include <stdio.h>
+ #include <string.h>
+
++#include <signal.h>
++#include <stdint.h>
++#include <unistd.h>
++#include <sys/mman.h>
++#include <sys/ucontext.h>
++#include <arpa/inet.h>
++
+ #include <openssl/opensslconf.h>
+ #include <openssl/crypto.h>
+ #include <openssl/dso.h>
+@@ -74,12 +84,23 @@
+ #ifndef OPENSSL_NO_AES
+ #include <openssl/aes.h>
+ #endif
++#ifndef OPENSSL_NO_SHA
++#include <openssl/sha.h>
++#endif
+ #include <openssl/rand.h>
+ #include <openssl/err.h>
+
+ #ifndef OPENSSL_NO_HW
+ #ifndef OPENSSL_NO_HW_PADLOCK
+
++/* PadLock RNG is disabled by default */
++#define PADLOCK_NO_RNG 1
++
++/* No ASM routines for SHA in MSC yet */
++#ifdef _MSC_VER
++#define OPENSSL_NO_SHA
++#endif
++
+ /* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */
+ #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
+ # ifndef OPENSSL_NO_DYNAMIC_ENGINE
+@@ -96,7 +117,7 @@
+ /* VIA PadLock AES is available *ONLY* on some x86 CPUs.
+ Not only that it doesn't exist elsewhere, but it
+ even can't be compiled on other platforms!
+-
++
+ In addition, because of the heavy use of inline assembler,
+ compiler choice is limited to GCC and Microsoft C. */
+ #undef COMPILE_HW_PADLOCK
+@@ -138,20 +159,42 @@
+ static int padlock_init(ENGINE *e);
+
+ /* RNG Stuff */
++#ifndef PADLOCK_NO_RNG
+ static RAND_METHOD padlock_rand;
++#endif
+
+ /* Cipher Stuff */
+ #ifndef OPENSSL_NO_AES
+ static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+ #endif
+
++/* Digest Stuff */
++#ifndef OPENSSL_NO_SHA
++static int padlock_digests(ENGINE *e, const EVP_MD **digest, const int **nids, int nid);
++static volatile void *padlock_cached_sha_buffer = NULL;
++#endif
++
+ /* Engine names */
+ static const char *padlock_id = "padlock";
+ static char padlock_name[100];
+
+ /* Available features */
+-static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
+-static int padlock_use_rng = 0; /* Random Number Generator */
++enum padlock_flags {
++ PADLOCK_RNG = 0x01,
++ PADLOCK_ACE = 0x02,
++ PADLOCK_ACE2 = 0x04,
++ PADLOCK_PHE = 0x08,
++ PADLOCK_PMM = 0x10
++};
++enum padlock_flags padlock_flags;
++
++#define PADLOCK_HAVE_RNG (padlock_flags & PADLOCK_RNG)
++#define PADLOCK_HAVE_ACE (padlock_flags & (PADLOCK_ACE|PADLOCK_ACE2))
++#define PADLOCK_HAVE_ACE1 (padlock_flags & PADLOCK_ACE)
++#define PADLOCK_HAVE_ACE2 (padlock_flags & PADLOCK_ACE2)
++#define PADLOCK_HAVE_PHE (padlock_flags & PADLOCK_PHE)
++#define PADLOCK_HAVE_PMM (padlock_flags & PADLOCK_PMM)
++
+ #ifndef OPENSSL_NO_AES
+ static int padlock_aes_align_required = 1;
+ #endif
+@@ -165,25 +208,30 @@
+ /* Check available features */
+ padlock_available();
+
+-#if 1 /* disable RNG for now, see commentary in vicinity of RNG code */
+- padlock_use_rng=0;
+-#endif
+-
+ /* Generate a nice engine name with available features */
+ BIO_snprintf(padlock_name, sizeof(padlock_name),
+- "VIA PadLock (%s, %s)",
+- padlock_use_rng ? "RNG" : "no-RNG",
+- padlock_use_ace ? "ACE" : "no-ACE");
++ "VIA PadLock: %s%s%s%s%s",
++ padlock_flags ? "" : "not supported",
++ PADLOCK_HAVE_RNG ? "RNG " : "",
++ PADLOCK_HAVE_ACE ? (PADLOCK_HAVE_ACE2 ? "ACE2 " : "ACE ") : "",
++ PADLOCK_HAVE_PHE ? "PHE " : "",
++ PADLOCK_HAVE_PMM ? "PMM " : "");
+
+- /* Register everything or return with an error */
++ /* Register everything or return with an error */
+ if (!ENGINE_set_id(e, padlock_id) ||
+ !ENGINE_set_name(e, padlock_name) ||
+
+- !ENGINE_set_init_function(e, padlock_init) ||
++ !ENGINE_set_init_function(e, padlock_init)
+ #ifndef OPENSSL_NO_AES
+- (padlock_use_ace && !ENGINE_set_ciphers (e, padlock_ciphers)) ||
++ || (PADLOCK_HAVE_ACE && !ENGINE_set_ciphers (e, padlock_ciphers))
++#endif
++#ifndef OPENSSL_NO_SHA
++ || (PADLOCK_HAVE_PHE && !ENGINE_set_digests (e, padlock_digests))
++#endif
++#ifndef PADLOCK_NO_RNG
++ || (PADLOCK_HAVE_RNG && !ENGINE_set_RAND (e, &padlock_rand))
+ #endif
+- (padlock_use_rng && !ENGINE_set_RAND (e, &padlock_rand))) {
++ ) {
+ return 0;
+ }
+
+@@ -213,7 +261,7 @@
+ static int
+ padlock_init(ENGINE *e)
+ {
+- return (padlock_use_rng || padlock_use_ace);
++ return (padlock_flags);
+ }
+
+ /* This stuff is needed if this ENGINE is being compiled into a self-contained
+@@ -247,7 +295,7 @@
+ #define AES_KEY_SIZE_192 24
+ #define AES_KEY_SIZE_256 32
+
+-/* Here we store the status information relevant to the
++/* Here we store the status information relevant to the
+ current context. */
+ /* BIG FAT WARNING:
+ * Inline assembler in PADLOCK_XCRYPT_ASM()
+@@ -306,7 +354,7 @@
+ {
+ int result = -1;
+
+- /* We're checking if the bit #21 of EFLAGS
++ /* We're checking if the bit #21 of EFLAGS
+ can be toggled. If yes = CPUID is available. */
+ asm volatile (
+ "pushf\n"
+@@ -322,7 +370,7 @@
+ "xorl %%eax, %%ecx\n"
+ "movl %%ecx, %0\n"
+ : "=r" (result) : : "eax", "ecx");
+-
++
+ return (result == 0);
+ }
+
+@@ -365,10 +413,22 @@
+ : "+a"(eax), "=d"(edx) : : "ecx");
+
+ /* Fill up some flags */
+- padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
+- padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
++ padlock_flags |= ((edx & (0x3<<3)) ? PADLOCK_RNG : 0);
++ padlock_flags |= ((edx & (0x3<<7)) ? PADLOCK_ACE : 0);
++ padlock_flags |= ((edx & (0x3<<9)) ? PADLOCK_ACE2 : 0);
++ padlock_flags |= ((edx & (0x3<<11)) ? PADLOCK_PHE : 0);
++ padlock_flags |= ((edx & (0x3<<13)) ? PADLOCK_PMM : 0);
++
++ return padlock_flags;
++}
+
+- return padlock_use_ace + padlock_use_rng;
++static inline void
++padlock_htonl_block(uint32_t *data, size_t count)
++{
++ while (count--) {
++ asm volatile ("bswapl %0" : "+r"(*data));
++ data++;
++ }
+ }
+
+ #ifndef OPENSSL_NO_AES
+@@ -377,17 +437,14 @@
+ padlock_bswapl(AES_KEY *ks)
+ {
+ size_t i = sizeof(ks->rd_key)/sizeof(ks->rd_key[0]);
+- unsigned int *key = ks->rd_key;
++ uint32_t *key = (uint32_t*) ks->rd_key;
+
+- while (i--) {
+- asm volatile ("bswapl %0" : "+r"(*key));
+- key++;
+- }
++ padlock_htonl_block(key, i);
+ }
+ #endif
+
+ /* Force key reload from memory to the CPU microcode.
+- Loading EFLAGS from the stack clears EFLAGS[30]
++ Loading EFLAGS from the stack clears EFLAGS[30]
+ which does the trick. */
+ static inline void
+ padlock_reload_key(void)
+@@ -423,7 +480,7 @@
+ }
+
+ /* Template for padlock_xcrypt_* modes */
+-/* BIG FAT WARNING:
++/* BIG FAT WARNING:
+ * The offsets used with 'leal' instructions
+ * describe items of the 'padlock_cipher_data'
+ * structure.
+@@ -475,7 +532,7 @@
+ * In case you wonder 'rep xcrypt*' instructions above are *not*
+ * affected by the Direction Flag and pointers advance toward
+ * larger addresses unconditionally.
+- */
++ */
+ static inline unsigned char *
+ padlock_memcpy(void *dst,const void *src,size_t n)
+ {
+@@ -501,7 +558,7 @@
+ _asm _emit 0x0f _asm _emit 0xa7 \
+ _asm _emit code
+
+-/* BIG FAT WARNING:
++/* BIG FAT WARNING:
+ * The offsets used with 'lea' instructions
+ * describe items of the 'padlock_cipher_data'
+ * structure.
+@@ -840,7 +897,7 @@
+ return 1;
+ }
+
+-/*
++/*
+ * Simplified version of padlock_aes_cipher() used when
+ * 1) both input and output buffers are at aligned addresses.
+ * or when
+@@ -895,7 +952,7 @@
+ # error "insane PADLOCK_CHUNK..."
+ #endif
+
+-/* Re-align the arguments to 16-Bytes boundaries and run the
++/* Re-align the arguments to 16-Bytes boundaries and run the
+ encryption function itself. This function is not AES-specific. */
+ static int
+ padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
+@@ -1157,6 +1214,470 @@
+
+ #endif /* OPENSSL_NO_AES */
+
++#ifndef OPENSSL_NO_SHA
++
++struct padlock_digest_data {
++ unsigned char output[128+16];
++ uint64_t total;
++
++ unsigned char *buffer;
++ size_t used;
++ size_t size;
++
++ void (*hash)(struct padlock_digest_data *data,
++ const void *buf, size_t len);
++ int (*update)(EVP_MD_CTX *ctx,
++ const void *buffer, size_t len);
++ int (*final)(EVP_MD_CTX *ctx, unsigned char *buffer);
++};
++
++#define DIGEST_DATA(ctx) ((struct padlock_digest_data *)(ctx->md_data))
++#define DIGEST_DATA_OUTPUT(dd) (uint32_t*)(((uintptr_t)(dd->output) + 15) & ~15)
++#define PADLOCK_BUFFER_PAGES 14
++
++static inline void *
++padlock_atomic_xchg(volatile void **mem, void *fixed)
++{
++ /* No lock prefix due the xchg asserts it anyway, and the
++ * funny unsigned long* cast is required to workaround some gcc
++ * problems if compiling in PIC mode */
++ asm volatile (
++ "xchg %0, %1"
++ : "=r"(fixed)
++ : "m"(*(unsigned long*)mem), "0"(fixed)
++ : "memory");
++ return fixed;
++}
++
++static void
++padlock_do_sha1(struct padlock_digest_data *data, const void *buf, size_t len)
++{
++ uint32_t *output = DIGEST_DATA_OUTPUT(data);
++ asm volatile (
++ "xsha1"
++ : "+S"(buf), "+D"(output)
++ : "c"(len), "a"(0));
++}
++
++static void
++padlock_do_sha256(struct padlock_digest_data *data, const void *buf, size_t len)
++{
++ uint32_t *output = DIGEST_DATA_OUTPUT(data);
++ asm volatile (
++ "xsha256"
++ : "+S"(buf), "+D"(output)
++ : "c"(len), "a"(0));
++}
++
++static void
++handle_sigsegv(int sig, siginfo_t *info, void *uctxp)
++{
++ ucontext_t *uctx = uctxp;
++
++ uctx->uc_mcontext.gregs[14] += 4;
++}
++
++static void
++padlock_sha_nonfinalizing(struct padlock_digest_data *data)
++{
++ struct sigaction act, oldact;
++ size_t bofs = 0;
++
++ if (data->used != data->size) {
++ bofs = data->size - data->used;
++ memmove(&data->buffer[bofs], data->buffer, data->used);
++ }
++
++ memset(&act, 0, sizeof(act));
++ act.sa_sigaction = handle_sigsegv;
++ act.sa_flags = SA_SIGINFO;
++ sigaction(SIGSEGV, &act, &oldact);
++ data->hash(data, &data->buffer[bofs], data->used + 64);
++ sigaction(SIGSEGV, &oldact, NULL);
++}
++
++static void
++padlock_free_buffer(void *buf)
++{
++ buf = padlock_atomic_xchg(&padlock_cached_sha_buffer, buf);
++ if (buf != NULL)
++ munmap(buf, (PADLOCK_BUFFER_PAGES + 1) * getpagesize());
++}
++
++static void *
++padlock_allocate_buffer(size_t *maxsize)
++{
++ void *buf;
++ size_t size, page;
++
++ page = getpagesize();
++ buf = padlock_atomic_xchg(&padlock_cached_sha_buffer, NULL);
++ if (buf != NULL)
++ goto ret;
++
++ size = (PADLOCK_BUFFER_PAGES + 1) * page;
++ buf = mmap(0, size, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
++ if (buf == NULL)
++ return NULL;
++
++ /* Try locking the pages to avoid swapping, but don't fail if
++ * we are over quota. */
++ mlock(buf, size);
++
++ if (mprotect(buf + PADLOCK_BUFFER_PAGES * page, page, PROT_NONE) < 0) {
++ munmap(buf, size);
++ return NULL;
++ }
++
++ret:
++ *maxsize = PADLOCK_BUFFER_PAGES * page - 64;
++
++ return buf;
++}
++
++static int
++padlock_multi_update(EVP_MD_CTX *ctx, const void *data, size_t len)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ size_t chunk_size;
++
++ if (ddata->buffer == NULL) {
++ ddata->buffer = padlock_allocate_buffer(&ddata->size);
++ }
++
++ while (len) {
++ if (ddata->used + len < ddata->size) {
++ memcpy(&ddata->buffer[ddata->used], data, len);
++ ddata->used += len;
++ ddata->total += len;
++ return 1;
++ }
++
++ chunk_size = ddata->size - ddata->used;
++ memcpy(&ddata->buffer[ddata->used], data, chunk_size);
++
++ data += chunk_size;
++ len -= chunk_size;
++ ddata->used = ddata->size;
++ ddata->total += chunk_size;
++ padlock_sha_nonfinalizing(ddata);
++ ddata->used = 0;
++ }
++
++ return 1;
++}
++
++static int
++padlock_oneshot_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ size_t size = EVP_MD_CTX_size(ctx);
++ uint32_t *output = DIGEST_DATA_OUTPUT(ddata);
++
++ padlock_htonl_block(output, size / sizeof(uint32_t));
++ memcpy(md, output, size);
++
++ return 1;
++}
++
++static int
++padlock_multi_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++ static const char padding[64] = { 0x80, };
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++
++ if (ddata->used == ddata->total) {
++ /* Sweet, everything fits in one buffer. */
++ ddata->hash(ddata, ddata->buffer, ddata->used);
++ } else {
++ /* Hardware already hashed some buffers.
++ * Do finalizing manually */
++ union {
++ uint64_t u64;
++ uint32_t u32[2];
++ } bits_le, bits;
++ size_t lastblocklen, padlen;
++
++ /* BigEndianise the length. */
++ bits_le.u64 = ddata->total * 8;
++ bits.u32[1] = htonl(bits_le.u32[0]);
++ bits.u32[0] = htonl(bits_le.u32[1]);
++
++ /* Append padding, leave space for length. */
++ lastblocklen = ddata->total & 63;
++ padlen = (lastblocklen < 56) ? (56 - lastblocklen) : ((64+56) - lastblocklen);
++ padlock_multi_update(ctx, padding, padlen);
++
++ /* Length in BigEndian64 */
++ padlock_multi_update(ctx, (const char *) &bits, sizeof(bits));
++
++ /* And finally calculate it */
++ padlock_sha_nonfinalizing(ddata);
++ }
++
++ return padlock_oneshot_final(ctx, md);
++}
++
++static int
++padlock_oneshot_update(EVP_MD_CTX *ctx, const void *data, size_t length)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++
++ /* Oneshot update is only possible if context flags indicate so */
++ if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) {
++ ddata->update = padlock_multi_update;
++ ddata->final = padlock_multi_final;
++ return padlock_multi_update(ctx, data, length);
++ }
++
++ ddata->hash(ddata, data, length);
++ return 1;
++}
++
++static void
++padlock_sha_init(struct padlock_digest_data *ddata)
++{
++ ddata->total = 0;
++ ddata->buffer = NULL;
++ ddata->used = 0;
++ ddata->size = 0;
++ ddata->update = padlock_oneshot_update;
++ ddata->final = padlock_oneshot_final;
++}
++
++static int
++padlock_sha1_init(EVP_MD_CTX *ctx)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ uint32_t *output = DIGEST_DATA_OUTPUT(ddata);
++
++ output[0] = 0x67452301;
++ output[1] = 0xEFCDAB89;
++ output[2] = 0x98BADCFE;
++ output[3] = 0x10325476;
++ output[4] = 0xC3D2E1F0;
++
++ padlock_sha_init(ddata);
++ ddata->hash = padlock_do_sha1;
++
++ return 1;
++}
++
++static int
++padlock_sha224_init(EVP_MD_CTX *ctx)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ uint32_t *output = DIGEST_DATA_OUTPUT(ddata);
++
++ output[0] = 0xC1059ED8UL;
++ output[1] = 0x367CD507UL;
++ output[2] = 0x3070DD17UL;
++ output[3] = 0xF70E5939UL;
++ output[4] = 0xFFC00B31UL;
++ output[5] = 0x68581511UL;
++ output[6] = 0x64F98FA7UL;
++ output[7] = 0xBEFA4FA4UL;
++
++ padlock_sha_init(ddata);
++ ddata->hash = padlock_do_sha256;
++
++ return 1;
++}
++
++static int
++padlock_sha256_init(EVP_MD_CTX *ctx)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ uint32_t *output = DIGEST_DATA_OUTPUT(ddata);
++
++ output[0] = 0x6A09E667;
++ output[1] = 0xBB67AE85;
++ output[2] = 0x3C6EF372;
++ output[3] = 0xA54FF53A;
++ output[4] = 0x510E527F;
++ output[5] = 0x9B05688C;
++ output[6] = 0x1F83D9AB;
++ output[7] = 0x5BE0CD19;
++
++ padlock_sha_init(ddata);
++ ddata->hash = padlock_do_sha256;
++
++ return 1;
++}
++
++static int
++padlock_sha_update(EVP_MD_CTX *ctx, const void *data, size_t length)
++{
++ return DIGEST_DATA(ctx)->update(ctx, data, length);
++}
++
++static int
++padlock_sha_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++ return DIGEST_DATA(ctx)->final(ctx, md);
++}
++
++static int
++padlock_sha_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
++{
++ struct padlock_digest_data *dfrom = DIGEST_DATA(from);
++ struct padlock_digest_data *dto = DIGEST_DATA(to);
++
++ /* Copy the internal state */
++ memcpy(DIGEST_DATA_OUTPUT(dto), DIGEST_DATA_OUTPUT(dfrom), 128);
++ dto->total = dfrom->total - dfrom->used;
++ dto->hash = dfrom->hash;
++ dto->used = 0;
++
++ /* Try using oneshot update if possible */
++ if (dfrom->used == dfrom->total) {
++ dto->update = padlock_oneshot_update;
++ dto->final = padlock_oneshot_final;
++ } else {
++ dto->update = padlock_multi_update;
++ dto->final = padlock_multi_final;
++ }
++
++ /* Copy pending data - one oneshot destination, this means finalizing
++ * the contents if we are still on the first iteration. */
++ if (dfrom->buffer != NULL)
++ padlock_sha_update(to, dfrom->buffer, dfrom->used);
++
++ return 1;
++}
++
++static int
++padlock_sha_cleanup(EVP_MD_CTX *ctx)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++
++ if (ddata->buffer != NULL)
++ padlock_free_buffer(ddata->buffer);
++ ddata->buffer = NULL;
++
++ return 1;
++}
++
++static const EVP_MD padlock_sha1_md = {
++ NID_sha1,
++ NID_sha1WithRSAEncryption,
++ SHA_DIGEST_LENGTH,
++ 0,
++ padlock_sha1_init,
++ padlock_sha_update,
++ padlock_sha_final,
++ padlock_sha_copy,
++ padlock_sha_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(struct padlock_digest_data),
++};
++
++static const EVP_MD padlock_dss1_md = {
++ NID_dsa,
++ NID_dsaWithSHA1,
++ SHA_DIGEST_LENGTH,
++ 0,
++ padlock_sha1_init,
++ padlock_sha_update,
++ padlock_sha_final,
++ padlock_sha_copy,
++ padlock_sha_cleanup,
++ EVP_PKEY_DSA_method,
++ SHA_CBLOCK,
++ sizeof(struct padlock_digest_data),
++};
++
++static const EVP_MD padlock_sha224_md = {
++ NID_sha224,
++ NID_sha224WithRSAEncryption,
++ SHA224_DIGEST_LENGTH,
++ 0,
++ padlock_sha224_init,
++ padlock_sha_update,
++ padlock_sha_final,
++ padlock_sha_copy,
++ padlock_sha_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(struct padlock_digest_data),
++};
++
++static const EVP_MD padlock_sha256_md = {
++ NID_sha256,
++ NID_sha256WithRSAEncryption,
++ SHA256_DIGEST_LENGTH,
++ 0,
++ padlock_sha256_init,
++ padlock_sha_update,
++ padlock_sha_final,
++ padlock_sha_copy,
++ padlock_sha_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(struct padlock_digest_data),
++};
++
++static int padlock_digest_nids[] = {
++#if !defined(OPENSSL_NO_SHA)
++ NID_sha1,
++ NID_dsa,
++#endif
++#if !defined(OPENSSL_NO_SHA256)
++#if !defined(OPENSSL_NO_SHA224)
++ NID_sha224,
++#endif
++ NID_sha256,
++#endif
++};
++
++static int padlock_digest_nids_num = sizeof(padlock_digest_nids)/sizeof(padlock_digest_nids[0]);
++
++static int
++padlock_digests (ENGINE *e, const EVP_MD **digest, const int **nids, int nid)
++{
++ /* No specific digest => return a list of supported nids ... */
++ if (!digest) {
++ *nids = padlock_digest_nids;
++ return padlock_digest_nids_num;
++ }
++
++ /* ... or the requested "digest" otherwise */
++ switch (nid) {
++#if !defined(OPENSSL_NO_SHA)
++ case NID_sha1:
++ *digest = &padlock_sha1_md;
++ break;
++ case NID_dsa:
++ *digest = &padlock_dss1_md;
++ break;
++#endif
++
++#if !defined(OPENSSL_NO_SHA256)
++#if !defined(OPENSSL_NO_SHA224)
++ case NID_sha224:
++ *digest = &padlock_sha224_md;
++ break;
++#endif /* OPENSSL_NO_SHA224 */
++
++ case NID_sha256:
++ *digest = &padlock_sha256_md;
++ break;
++#endif /* OPENSSL_NO_SHA256 */
++
++ default:
++ /* Sorry, we don't support this NID */
++ *digest = NULL;
++ return 0;
++ }
++
++ return 1;
++}
++
++#endif /* OPENSSL_NO_SHA */
++
++#ifndef PADLOCK_NO_RNG
+ /* ===== Random Number Generator ===== */
+ /*
+ * This code is not engaged. The reason is that it does not comply
+@@ -1164,7 +1685,7 @@
+ * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
+ * provide meaningful error control...
+ */
+-/* Wrapper that provides an interface between the API and
++/* Wrapper that provides an interface between the API and
+ the raw PadLock RNG */
+ static int
+ padlock_rand_bytes(unsigned char *output, int count)
+@@ -1212,6 +1733,7 @@
+ padlock_rand_bytes, /* pseudorand */
+ padlock_rand_status, /* rand status */
+ };
++#endif /* PADLOCK_NO_RNG */
+
+ #endif /* COMPILE_HW_PADLOCK */
+
+Index: openssl-0.9.8k/crypto/evp/p_sign.c
+===================================================================
+--- openssl-0.9.8k.orig/crypto/evp/p_sign.c 2009-07-13 11:01:02.000000000 +0300
++++ openssl-0.9.8k/crypto/evp/p_sign.c 2009-07-13 11:01:45.000000000 +0300
+@@ -5,21 +5,21 @@
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+- *
++ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+- *
++ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+- *
++ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+@@ -34,10 +34,10 @@
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+- * 4. If you include any Windows specific code (or a derivative thereof) from
++ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+- *
++ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@@ -49,7 +49,7 @@
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+- *
++ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+@@ -105,6 +105,7 @@
+ return(0);
+ }
+ EVP_MD_CTX_init(&tmp_ctx);
++ M_EVP_MD_CTX_set_flags(&tmp_ctx,EVP_MD_CTX_FLAG_ONESHOT);
+ EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+ if (ctx->digest->flags & EVP_MD_FLAG_SVCTX)
+ {
+Index: openssl-0.9.8k/crypto/evp/p_verify.c
+===================================================================
+--- openssl-0.9.8k.orig/crypto/evp/p_verify.c 2009-07-13 11:01:06.000000000 +0300
++++ openssl-0.9.8k/crypto/evp/p_verify.c 2009-07-13 11:02:11.000000000 +0300
+@@ -5,21 +5,21 @@
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+- *
++ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+- *
++ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+- *
++ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+@@ -34,10 +34,10 @@
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+- * 4. If you include any Windows specific code (or a derivative thereof) from
++ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+- *
++ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@@ -49,7 +49,7 @@
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+- *
++ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+@@ -92,7 +92,8 @@
+ }
+
+ EVP_MD_CTX_init(&tmp_ctx);
+- EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
++ M_EVP_MD_CTX_set_flags(&tmp_ctx,EVP_MD_CTX_FLAG_ONESHOT);
++ EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+ if (ctx->digest->flags & EVP_MD_FLAG_SVCTX)
+ {
+ EVP_MD_SVCTX sctmp;