summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2004-06-30 16:43:53 +0000
committerDaniel Veillard <veillard@src.gnome.org>2004-06-30 16:43:53 +0000
commit1bc6a1a495c2acec0fa2c46783a4dc0adefc1860 (patch)
tree803d776b536c44194efbb353452da2652334ad2d
parent19739dbd5fd3449b0cdae8984f3dd8b787d18ad2 (diff)
downloadlibxslt-1bc6a1a495c2acec0fa2c46783a4dc0adefc1860.tar.gz
libxslt-1bc6a1a495c2acec0fa2c46783a4dc0adefc1860.tar.bz2
libxslt-1bc6a1a495c2acec0fa2c46783a4dc0adefc1860.zip
applied patch from Joel Reed to get EXSLT crypto extensions based on
* win32/Makefile.msvc win32/Makefile.mingw libexslt/Makefile.am libexslt/exslt.c libexslt/exslt.h config.h.in configure.in libexslt/crypto.c: applied patch from Joel Reed to get EXSLT crypto extensions based on libgcrypt if found at configure time. * tests/namespaces/Makefile.am: fixed a small breakage Daniel
-rw-r--r--ChangeLog8
-rw-r--r--config.h.in3
-rw-r--r--configure.in19
-rw-r--r--libexslt/Makefile.am4
-rw-r--r--libexslt/crypto.c714
-rw-r--r--libexslt/exslt.c1
-rw-r--r--libexslt/exslt.h7
-rw-r--r--tests/namespaces/Makefile.am2
-rw-r--r--win32/Makefile.mingw2
-rw-r--r--win32/Makefile.msvc2
-rw-r--r--xsltproc/Makefile.am6
11 files changed, 764 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 52ba3657..995535a4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Wed Jun 30 18:41:20 CEST 2004 Daniel Veillard <daniel@veillard.com>
+
+ * win32/Makefile.msvc win32/Makefile.mingw libexslt/Makefile.am
+ libexslt/exslt.c libexslt/exslt.h config.h.in configure.in
+ libexslt/crypto.c: applied patch from Joel Reed to get EXSLT
+ crypto extensions based on libgcrypt if found at configure time.
+ * tests/namespaces/Makefile.am: fixed a small breakage
+
Wed Jun 30 12:28:34 HKT 2004 William Brack <wbrack@mmm.com.hk>
* libxslt/namespaces: some enhancement for fixing bug 142768
diff --git a/config.h.in b/config.h.in
index 3388df5e..1f36e2c3 100644
--- a/config.h.in
+++ b/config.h.in
@@ -27,6 +27,9 @@
/* Define to 1 if you have the `ftime' function. */
#undef HAVE_FTIME
+/* Define if gcrypt library is available. */
+#undef HAVE_GCRYPT
+
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
diff --git a/configure.in b/configure.in
index 5395eba4..770cf3cc 100644
--- a/configure.in
+++ b/configure.in
@@ -200,6 +200,23 @@ AC_SUBST(pythondir)
AC_SUBST(PYTHON_SUBDIR)
dnl
+dnl check for gcrypt
+dnl
+AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no)
+if test "$LIBGCRYPT_CONFIG" != "no" ; then
+ LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --cflags`
+ LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --libs`
+ AC_DEFINE(HAVE_GCRYPT, 1, [Define if gcrypt library is available.])
+ AC_MSG_NOTICE([Crypto extensions will be available.])
+else
+ LIBGCRYPT_CFLAGS=""
+ LIBGCRYPT_LIBS=""
+ AC_MSG_NOTICE([Crypto extensions will not be available. Install libgcrypt and reconfigure to make available.])
+fi
+
+AC_SUBST(LIBGCRYPT_CFLAGS)
+AC_SUBST(LIBGCRYPT_LIBS)
+dnl
dnl Debug for DV (-Wunreachable-code)
dnl
if [[ "${LOGNAME}" = "veillard" -a "`pwd`" = "/u/veillard/XSLT" ]] || \
@@ -408,7 +425,7 @@ AC_SUBST(XSLT_LIBS)
EXSLT_LIBDIR='-L${libdir}'
EXSLT_INCLUDEDIR='-I${includedir}'
-EXSLT_LIBS="-lexslt $XSLT_LIBS"
+EXSLT_LIBS="-lexslt $XSLT_LIBS $LIBGCRYPT_LIBS"
AC_SUBST(EXSLT_LIBDIR)
AC_SUBST(EXSLT_INCLUDEDIR)
AC_SUBST(EXSLT_LIBS)
diff --git a/libexslt/Makefile.am b/libexslt/Makefile.am
index ac540991..50fe8af8 100644
--- a/libexslt/Makefile.am
+++ b/libexslt/Makefile.am
@@ -2,6 +2,9 @@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/libxslt -I$(top_srcdir)/libexslt \
-I$(top_builddir) -I$(top_builddir)/libxslt \
-I$(top_builddir)/libexslt $(LIBXML_CFLAGS) $(CFLAGS)
+AM_CFLAGS = $(LIBGCRYPT_CFLAGS)
+AM_LDFLAGS = $(LIBGCRYPT_LIBS)
+
lib_LTLIBRARIES = libexslt.la
exsltincdir = $(includedir)/libexslt
@@ -16,6 +19,7 @@ exsltinc_HEADERS = \
libexslt_la_SOURCES = \
exslt.c \
common.c \
+ crypto.c \
math.c \
sets.c \
functions.c \
diff --git a/libexslt/crypto.c b/libexslt/crypto.c
new file mode 100644
index 00000000..218e38a0
--- /dev/null
+++ b/libexslt/crypto.c
@@ -0,0 +1,714 @@
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/parser.h>
+#include <libxml/encoding.h>
+#include <libxml/uri.h>
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+
+#include "exslt.h"
+
+#define HASH_DIGEST_LENGTH 32
+#define MD5_DIGEST_LENGTH 16
+#define SHA1_DIGEST_LENGTH 20
+
+/* gcrypt rc4 can do 256 bit keys, but cryptoapi limit
+ seems to be 128 for the default provider */
+#define RC4_KEY_LENGTH 128
+
+/**
+ * exsltCryptoBin2Hex:
+ * @bin: binary blob to convert
+ * @binlen: length of binary blob
+ * @hex: buffer to store hex version of blob
+ * @hexlen: length of buffer to store hex version of blob
+ *
+ * Helper function which encodes a binary blob as hex.
+ */
+void exsltCryptoBin2Hex(const unsigned char* bin, int binlen,
+ unsigned char* hex, int hexlen)
+{
+ static const char bin2hex[] = { '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f' };
+
+ unsigned char lo, hi;
+ int i, pos;
+ for (i = 0, pos = 0; (i < binlen && pos < hexlen); i++)
+ {
+ lo = bin[i] & 0xf;
+ hi = bin[i] >> 4;
+ hex[pos++] = bin2hex[hi];
+ hex[pos++] = bin2hex[lo];
+ }
+
+ hex[pos] = '\0';
+}
+
+/**
+ * exsltCryptoHex2Bin:
+ * @hex: hex version of blob to convert
+ * @hexlen: length of hex buffer
+ * @bin: destination binary buffer
+ * @binlen: length of binary buffer
+ *
+ * Helper function which decodes a hex blob to binary
+ */
+int exsltCryptoHex2Bin(const unsigned char* hex, int hexlen,
+ unsigned char* bin, int binlen)
+{
+ int i = 0, j = 0;
+ unsigned char lo, hi, result, tmp;
+
+ while (i<hexlen && j<binlen)
+ {
+ hi = lo = 0;
+
+ tmp = hex[i++];
+ if (tmp >= '0' && tmp <= '9') hi = tmp - '0';
+ else if (tmp >= 'a' && tmp <= 'f') hi = 10 + (tmp - 'a');
+
+ tmp = hex[i++];
+ if (tmp >= '0' && tmp <= '9') lo = tmp - '0';
+ else if (tmp >= 'a' && tmp <= 'f') lo = 10 + (tmp - 'a');
+
+ result = hi << 4;
+ result += lo;
+ bin[j++] = result;
+ }
+
+ return j;
+}
+
+#if defined(WIN32)
+
+#define HAVE_CRYPTO
+#define PLATFORM_HASH exsltCryptoCryptoApiHash
+#define PLATFORM_RC4_ENCRYPT exsltCryptoCryptoApiRc4Encrypt
+#define PLATFORM_RC4_DECRYPT exsltCryptoCryptoApiRc4Decrypt
+#define PLATFORM_MD4 CALG_MD4
+#define PLATFORM_MD5 CALG_MD5
+#define PLATFORM_SHA1 CALG_SHA1
+
+#include <windows.h>
+#include <wincrypt.h>
+#pragma comment(lib, "advapi32.lib")
+
+void exsltCryptoCryptoApiReportError(xmlXPathParserContextPtr ctxt, int line)
+{
+ LPVOID lpMsgBuf;
+ DWORD dw = GetLastError();
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf, 0, NULL );
+
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto error (line %d). %s", line, lpMsgBuf);
+ LocalFree(lpMsgBuf);
+}
+
+HCRYPTHASH exsltCryptoCryptoApiCreateHash(xmlXPathParserContextPtr ctxt,
+ HCRYPTPROV hCryptProv, ALG_ID algorithm,
+ const char* msg, unsigned int msglen,
+ char* dest, unsigned int destlen)
+{
+ HCRYPTHASH hHash = 0;
+ DWORD dwHashLen = destlen;
+
+ if (!CryptCreateHash(hCryptProv, algorithm, 0, 0, &hHash))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ return 0;
+ }
+
+ if(!CryptHashData(hHash, (const BYTE*)msg, msglen, 0))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ goto fail;
+ }
+
+ if (!CryptGetHashParam(hHash, HP_HASHVAL, dest, &dwHashLen, 0))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ goto fail;
+ }
+
+fail:
+ return hHash;
+}
+
+/**
+ * exsltCryptoCryptoApiHash:
+ * @ctxt: an XPath parser context
+ * @algorithm: hashing algorithm to use
+ * @msg: text to be hashed
+ * @msglen: length of text to be hashed
+ * @dest: buffer to place hash result
+ *
+ * Helper function which hashes a message using MD4, MD5, or SHA1.
+ * Uses Win32 CryptoAPI.
+ */
+void exsltCryptoCryptoApiHash(xmlXPathParserContextPtr ctxt, ALG_ID algorithm,
+ const char* msg, unsigned long msglen, char dest[HASH_DIGEST_LENGTH])
+{
+ HCRYPTPROV hCryptProv;
+ HCRYPTHASH hHash;
+
+ if(! CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ return;
+ }
+
+ hHash = exsltCryptoCryptoApiCreateHash(ctxt, hCryptProv,
+ algorithm, msg, msglen,
+ dest, HASH_DIGEST_LENGTH);
+ if (0 != hHash)
+ {
+ CryptDestroyHash(hHash);
+ }
+
+ CryptReleaseContext(hCryptProv, 0);
+}
+
+void exsltCryptoCryptoApiRc4Encrypt(xmlXPathParserContextPtr ctxt,
+ const unsigned char* key,
+ const unsigned char* msg, int msglen,
+ unsigned char* dest, int destlen)
+{
+ HCRYPTPROV hCryptProv;
+ HCRYPTKEY hKey;
+ HCRYPTHASH hHash;
+ DWORD dwDataLen;
+ unsigned char hash[HASH_DIGEST_LENGTH];
+
+ if (msglen > destlen)
+ {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto : internal error exsltCryptoCryptoApiRc4Encrypt dest buffer too small.\n");
+ return;
+ }
+
+ if(! CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ return;
+ }
+
+ hHash = exsltCryptoCryptoApiCreateHash(ctxt, hCryptProv,
+ CALG_SHA1, key, RC4_KEY_LENGTH,
+ hash, HASH_DIGEST_LENGTH);
+
+ if (!CryptDeriveKey(hCryptProv, CALG_RC4, hHash, 0x00800000, &hKey))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ goto fail;
+ }
+
+// Now encrypt data.
+ dwDataLen = msglen;
+ memcpy(dest, msg, msglen);
+ if (!CryptEncrypt(hKey, 0, TRUE, 0, dest, &dwDataLen, msglen))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ goto fail;
+ }
+
+fail:
+ if (0 != hHash)
+ {
+ CryptDestroyHash(hHash);
+ }
+
+ CryptDestroyKey(hKey);
+ CryptReleaseContext(hCryptProv, 0);
+}
+
+void exsltCryptoCryptoApiRc4Decrypt(xmlXPathParserContextPtr ctxt,
+ const unsigned char* key,
+ const unsigned char* msg, int msglen,
+ unsigned char* dest, int destlen)
+{
+ HCRYPTPROV hCryptProv;
+ HCRYPTKEY hKey;
+ HCRYPTHASH hHash;
+ DWORD dwDataLen;
+ unsigned char hash[HASH_DIGEST_LENGTH];
+
+ if (msglen > destlen)
+ {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto : internal error exsltCryptoCryptoApiRc4Encrypt dest buffer too small.\n");
+ return;
+ }
+
+ if(! CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ return;
+ }
+
+ hHash = exsltCryptoCryptoApiCreateHash(ctxt, hCryptProv,
+ CALG_SHA1, key, RC4_KEY_LENGTH,
+ hash, HASH_DIGEST_LENGTH);
+
+ if (!CryptDeriveKey(hCryptProv, CALG_RC4, hHash, 0x00800000, &hKey))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ goto fail;
+ }
+
+// Now encrypt data.
+ dwDataLen = msglen;
+ memcpy(dest, msg, msglen);
+ if (!CryptDecrypt(hKey, 0, TRUE, 0, dest, &dwDataLen))
+ {
+ exsltCryptoCryptoApiReportError(ctxt, __LINE__);
+ goto fail;
+ }
+
+fail:
+ if (0 != hHash)
+ {
+ CryptDestroyHash(hHash);
+ }
+
+ CryptDestroyKey(hKey);
+ CryptReleaseContext(hCryptProv, 0);
+}
+
+#endif /* defined(WIN32) */
+
+#if defined(HAVE_GCRYPT)
+
+#define HAVE_CRYPTO
+#define PLATFORM_HASH exsltCryptoGcryptHash
+#define PLATFORM_RC4_ENCRYPT exsltCryptoGcryptRc4Encrypt
+#define PLATFORM_RC4_DECRYPT exsltCryptoGcryptRc4Decrypt
+#define PLATFORM_MD4 GCRY_MD_MD4
+#define PLATFORM_MD5 GCRY_MD_MD5
+#define PLATFORM_SHA1 GCRY_MD_SHA1
+
+#include <gcrypt.h>
+
+void exsltCryptoGcryptInit (void)
+{
+ static int gcrypt_init;
+ xmlLockLibrary();
+
+ if (! gcrypt_init)
+ {
+/* The function `gcry_check_version' must be called before any other
+ function in the library, because it initializes the thread support
+ subsystem in Libgcrypt. To achieve this in all generality, it is
+ necessary to synchronize the call to this function with all other calls
+ to functions in the library, using the synchronization mechanisms
+ available in your thread library. (from gcrypt.info)
+*/
+ gcry_check_version(GCRYPT_VERSION);
+ gcrypt_init=1;
+ }
+
+ xmlUnlockLibrary();
+}
+
+/**
+ * exsltCryptoGcryptHash:
+ * @ctxt: an XPath parser context
+ * @algorithm: hashing algorithm to use
+ * @msg: text to be hashed
+ * @msglen: length of text to be hashed
+ * @dest: buffer to place hash result
+ *
+ * Helper function which hashes a message using MD4, MD5, or SHA1.
+ * using gcrypt
+ */
+void exsltCryptoGcryptHash(xmlXPathParserContextPtr ctxt, enum gcry_md_algos algorithm,
+ const char* msg, unsigned long msglen, char dest[HASH_DIGEST_LENGTH])
+{
+ exsltCryptoGcryptInit();
+ gcry_md_hash_buffer(algorithm, dest, msg, msglen);
+}
+
+void exsltCryptoGcryptRc4Encrypt(xmlXPathParserContextPtr ctxt,
+ const unsigned char* key,
+ const unsigned char* msg, int msglen,
+ unsigned char* dest, int destlen)
+{
+ gcry_cipher_hd_t cipher;
+ gcry_error_t rc = 0;
+
+ exsltCryptoGcryptInit();
+
+ rc = gcry_cipher_open(&cipher, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
+ if (rc)
+ {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto internal error %s (gcry_cipher_open)\n",
+ gcry_strerror(rc));
+ }
+
+ rc = gcry_cipher_setkey(cipher, key, RC4_KEY_LENGTH);
+ if (rc)
+ {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto internal error %s (gcry_cipher_setkey)\n",
+ gcry_strerror(rc));
+ }
+
+ rc = gcry_cipher_encrypt(cipher, (unsigned char*)dest, destlen,
+ (const unsigned char*)msg, msglen);
+ if (rc)
+ {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto internal error %s (gcry_cipher_encrypt)\n",
+ gcry_strerror(rc));
+ }
+
+ gcry_cipher_close(cipher);
+}
+
+void exsltCryptoGcryptRc4Decrypt(xmlXPathParserContextPtr ctxt,
+ const unsigned char* key,
+ const unsigned char* msg, int msglen,
+ unsigned char* dest, int destlen)
+{
+ gcry_cipher_hd_t cipher;
+ gcry_error_t rc = 0;
+
+ exsltCryptoGcryptInit();
+
+ rc = gcry_cipher_open(&cipher, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
+ if (rc)
+ {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto internal error %s (gcry_cipher_open)\n",
+ gcry_strerror(rc));
+ }
+
+ rc = gcry_cipher_setkey(cipher, key, RC4_KEY_LENGTH);
+ if (rc)
+ {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto internal error %s (gcry_cipher_setkey)\n",
+ gcry_strerror(rc));
+ }
+
+ rc = gcry_cipher_decrypt(cipher, (unsigned char*)dest, destlen,
+ (const unsigned char*)msg, msglen);
+ if (rc)
+ {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:crypto internal error %s (gcry_cipher_decrypt)\n",
+ gcry_strerror(rc));
+ }
+
+ gcry_cipher_close(cipher);
+}
+
+#endif /* defined(HAVE_GCRYPT) */
+
+#if defined(HAVE_CRYPTO)
+
+/**
+ * exsltCryptoPopString:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Helper function which checks for and returns first string argument and its length
+ */
+static int
+exsltCryptoPopString (xmlXPathParserContextPtr ctxt, int nargs, xmlChar **str) {
+
+ int str_len = 0;
+
+ if ((nargs < 1) || (nargs > 2)) {
+ xmlXPathSetArityError(ctxt);
+ return 0;
+ }
+
+ *str = xmlXPathPopString(ctxt);
+ str_len = xmlUTF8Strlen(*str);
+
+ if (str_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(*str);
+ return 0;
+ }
+
+ return str_len;
+}
+
+/**
+ * exsltCryptoMd4Function:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * computes the md4 hash of a string and returns as hex
+ */
+static void
+exsltCryptoMd4Function (xmlXPathParserContextPtr ctxt, int nargs) {
+
+ int str_len = 0;
+ xmlChar *str = NULL, *ret = NULL;
+ unsigned char hash[HASH_DIGEST_LENGTH];
+ unsigned char hex[MD5_DIGEST_LENGTH*2+1];
+
+ str_len = exsltCryptoPopString(ctxt, nargs, &str);
+ if (str_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ return;
+ }
+
+ PLATFORM_HASH(ctxt, PLATFORM_MD4, str, str_len, hash);
+ exsltCryptoBin2Hex(hash, sizeof(hash)-1, hex, sizeof(hex)-1);
+
+ ret = xmlStrdup((xmlChar *)hex);
+ xmlXPathReturnString(ctxt, ret);
+
+ if (str != NULL)
+ xmlFree(str);
+}
+
+/**
+ * exsltCryptoMd5Function:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * computes the md5 hash of a string and returns as hex
+ */
+static void
+exsltCryptoMd5Function (xmlXPathParserContextPtr ctxt, int nargs) {
+
+ int str_len = 0;
+ xmlChar *str = NULL, *ret = NULL;
+ unsigned char hash[HASH_DIGEST_LENGTH];
+ unsigned char hex[MD5_DIGEST_LENGTH*2+1];
+
+ str_len = exsltCryptoPopString(ctxt, nargs, &str);
+ if (str_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ return;
+ }
+
+ PLATFORM_HASH(ctxt, PLATFORM_MD5, str, str_len, hash);
+ exsltCryptoBin2Hex(hash, sizeof(hash)-1, hex, sizeof(hex)-1);
+
+ ret = xmlStrdup((xmlChar *)hex);
+ xmlXPathReturnString(ctxt, ret);
+
+ if (str != NULL)
+ xmlFree(str);
+}
+
+/**
+ * exsltCryptoSha1Function:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * computes the sha1 hash of a string and returns as hex
+ */
+static void
+exsltCryptoSha1Function (xmlXPathParserContextPtr ctxt, int nargs) {
+
+ int str_len = 0;
+ xmlChar *str = NULL, *ret = NULL;
+ unsigned char hash[HASH_DIGEST_LENGTH];
+ unsigned char hex[SHA1_DIGEST_LENGTH*2+1];
+
+ str_len = exsltCryptoPopString(ctxt, nargs, &str);
+ if (str_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ return;
+ }
+
+ PLATFORM_HASH(ctxt, PLATFORM_SHA1, str, str_len, hash);
+ exsltCryptoBin2Hex(hash, sizeof(hash)-1, hex, sizeof(hex)-1);
+
+ ret = xmlStrdup((xmlChar *)hex);
+ xmlXPathReturnString(ctxt, ret);
+
+ if (str != NULL)
+ xmlFree(str);
+}
+
+/**
+ * exsltCryptoRc4EncryptFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * computes the sha1 hash of a string and returns as hex
+ */
+static void
+exsltCryptoRc4EncryptFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+
+ int key_len = 0, key_size = 0;
+ int str_len = 0, bin_len = 0, hex_len = 0;
+ xmlChar *key = NULL, *str = NULL, *padkey = NULL;
+ xmlChar *bin = NULL, *hex = NULL;
+
+ if ((nargs < 1) || (nargs > 3)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ str = xmlXPathPopString(ctxt);
+ str_len = xmlUTF8Strlen(str);
+
+ if (str_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ return;
+ }
+
+ key = xmlXPathPopString(ctxt);
+ key_len = xmlUTF8Strlen(str);
+
+ if (key_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(key);
+ xmlFree(str);
+ return;
+ }
+
+ padkey = xmlMallocAtomic(RC4_KEY_LENGTH);
+ key_size = xmlUTF8Strsize(key, key_len);
+ memcpy(padkey, key, key_size);
+ memset(padkey+key_size, '\0', sizeof(padkey));
+
+/* encrypt it */
+ bin_len = str_len;
+ bin = xmlStrdup(str);
+ PLATFORM_RC4_ENCRYPT(ctxt, padkey, str, str_len, bin, bin_len);
+
+/* encode it */
+ hex_len = str_len*2+1;
+ hex = xmlMallocAtomic(hex_len);
+
+ exsltCryptoBin2Hex(bin, str_len, hex, hex_len);
+ xmlXPathReturnString(ctxt, hex);
+
+ if (key != NULL)
+ xmlFree(key);
+ if (str != NULL)
+ xmlFree(str);
+ if (padkey != NULL)
+ xmlFree(padkey);
+ if (bin != NULL)
+ xmlFree(bin);
+}
+
+/**
+ * exsltCryptoRc4DecryptFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * computes the sha1 hash of a string and returns as hex
+ */
+static void
+exsltCryptoRc4DecryptFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+
+ int key_len = 0, key_size = 0;
+ int str_len = 0, bin_len = 0, ret_len = 0;
+ xmlChar *key = NULL, *str = NULL, *padkey = NULL, *bin = NULL, *ret = NULL;
+
+ if ((nargs < 1) || (nargs > 3)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ str = xmlXPathPopString(ctxt);
+ str_len = xmlUTF8Strlen(str);
+
+ if (str_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ return;
+ }
+
+ key = xmlXPathPopString(ctxt);
+ key_len = xmlUTF8Strlen(str);
+
+ if (key_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(key);
+ xmlFree(str);
+ return;
+ }
+
+ padkey = xmlMallocAtomic(RC4_KEY_LENGTH);
+ key_size = xmlUTF8Strsize(key, key_len);
+ memcpy(padkey, key, key_size);
+ memset(padkey+key_size, '\0', sizeof(padkey));
+
+/* decode hex to binary */
+ bin_len = str_len;
+ bin = xmlMallocAtomic(bin_len);
+ ret_len = exsltCryptoHex2Bin(str, str_len, bin, bin_len);
+
+/* decrypt the binary blob */
+ ret = xmlMallocAtomic(ret_len);
+ PLATFORM_RC4_DECRYPT(ctxt, padkey, bin, ret_len, ret, ret_len);
+
+ xmlXPathReturnString(ctxt, ret);
+
+ if (key != NULL)
+ xmlFree(key);
+ if (str != NULL)
+ xmlFree(str);
+ if (padkey != NULL)
+ xmlFree(padkey);
+ if (bin != NULL)
+ xmlFree(bin);
+}
+
+/**
+ * exsltCryptoRegister:
+ *
+ * Registers the EXSLT - Crypto module
+ */
+
+void
+exsltCryptoRegister (void) {
+ xsltRegisterExtModuleFunction ((const xmlChar *) "md4",
+ EXSLT_CRYPTO_NAMESPACE,
+ exsltCryptoMd4Function);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "md5",
+ EXSLT_CRYPTO_NAMESPACE,
+ exsltCryptoMd5Function);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "sha1",
+ EXSLT_CRYPTO_NAMESPACE,
+ exsltCryptoSha1Function);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_encrypt",
+ EXSLT_CRYPTO_NAMESPACE,
+ exsltCryptoRc4EncryptFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_decrypt",
+ EXSLT_CRYPTO_NAMESPACE,
+ exsltCryptoRc4DecryptFunction);
+}
+
+#else
+void exsltCryptoRegister (void) { }
+
+#endif /* defined(HAVE_CRYPTO) */
diff --git a/libexslt/exslt.c b/libexslt/exslt.c
index 6f419135..9b6a6ac1 100644
--- a/libexslt/exslt.c
+++ b/libexslt/exslt.c
@@ -32,6 +32,7 @@ const int exsltLibxmlVersion = LIBXML_VERSION;
void
exsltRegisterAll (void) {
exsltCommonRegister();
+ exsltCryptoRegister();
exsltMathRegister();
exsltSetsRegister();
exsltFuncRegister();
diff --git a/libexslt/exslt.h b/libexslt/exslt.h
index dca38233..9cdaaa02 100644
--- a/libexslt/exslt.h
+++ b/libexslt/exslt.h
@@ -22,6 +22,12 @@ EXSLTPUBVAR const int exsltLibxmlVersion;
*/
#define EXSLT_COMMON_NAMESPACE ((const xmlChar *) "http://exslt.org/common")
/**
+ * EXSLT_CRYPTO_NAMESPACE:
+ *
+ * Namespace for EXSLT crypto functions
+ */
+#define EXSLT_CRYPTO_NAMESPACE ((const xmlChar *) "http://exslt.org/crypto")
+/**
* EXSLT_MATH_NAMESPACE:
*
* Namespace for EXSLT math functions
@@ -66,6 +72,7 @@ EXSLTPUBVAR const int exsltLibxmlVersion;
#define SAXON_NAMESPACE ((const xmlChar *) "http://icl.com/saxon")
EXSLTPUBFUN void EXSLTCALL exsltCommonRegister (void);
+EXSLTPUBFUN void EXSLTCALL exsltCryptoRegister (void);
EXSLTPUBFUN void EXSLTCALL exsltMathRegister (void);
EXSLTPUBFUN void EXSLTCALL exsltSetsRegister (void);
EXSLTPUBFUN void EXSLTCALL exsltFuncRegister (void);
diff --git a/tests/namespaces/Makefile.am b/tests/namespaces/Makefile.am
index 229e0a11..52fa03db 100644
--- a/tests/namespaces/Makefile.am
+++ b/tests/namespaces/Makefile.am
@@ -10,8 +10,8 @@ EXTRA_DIST = \
tst2.xml tst2.xsl tst2.out \
tst3.xml tst3.xsl tst3.out \
tst4.xml tst4.xsl tst4.out \
-# tst5.xml tst5.xsl tst5.out
tst6.xml tst6.xsl tst6.out
+# tst5.xml tst5.xsl tst5.out
all:
diff --git a/win32/Makefile.mingw b/win32/Makefile.mingw
index e2353cda..4d4fde0b 100644
--- a/win32/Makefile.mingw
+++ b/win32/Makefile.mingw
@@ -111,6 +111,7 @@ XSLT_OBJS_A = $(XSLT_INTDIR_A)/attributes.o\
# Libexslt object files.
EXSLT_OBJS = $(EXSLT_INTDIR)/common.o\
+ $(EXSLT_INTDIR)/crypto.o\
$(EXSLT_INTDIR)/date.o\
$(EXSLT_INTDIR)/exslt.o\
$(EXSLT_INTDIR)/functions.o\
@@ -123,6 +124,7 @@ EXSLT_SRCS = $(subst .o,.c,$(subst $(EXSLT_INTDIR)/,$(EXSLT_SRCDIR)/,$(EXSLT_OBJ
# Static libexslt object files.
EXSLT_OBJS_A = $(EXSLT_INTDIR_A)/common.o\
+ $(EXSLT_INTDIR_A)/crypto.o\
$(EXSLT_INTDIR_A)/date.o\
$(EXSLT_INTDIR_A)/exslt.o\
$(EXSLT_INTDIR_A)/functions.o\
diff --git a/win32/Makefile.msvc b/win32/Makefile.msvc
index 638df4aa..cf40a8b3 100644
--- a/win32/Makefile.msvc
+++ b/win32/Makefile.msvc
@@ -115,6 +115,7 @@ XSLT_OBJS_A = $(XSLT_INTDIR_A)\attributes.obj\
# Libexslt object files.
EXSLT_OBJS = $(EXSLT_INTDIR)\common.obj\
+ $(EXSLT_INTDIR)\crypto.obj\
$(EXSLT_INTDIR)\date.obj\
$(EXSLT_INTDIR)\exslt.obj\
$(EXSLT_INTDIR)\functions.obj\
@@ -126,6 +127,7 @@ EXSLT_OBJS = $(EXSLT_INTDIR)\common.obj\
# Static libexslt object files.
EXSLT_OBJS_A = $(EXSLT_INTDIR_A)\common.obj\
+ $(EXSLT_INTDIR_A)\crypto.obj\
$(EXSLT_INTDIR_A)\date.obj\
$(EXSLT_INTDIR_A)\exslt.obj\
$(EXSLT_INTDIR_A)\functions.obj\
diff --git a/xsltproc/Makefile.am b/xsltproc/Makefile.am
index a8828de5..44210c89 100644
--- a/xsltproc/Makefile.am
+++ b/xsltproc/Makefile.am
@@ -5,10 +5,12 @@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/libxslt -I$(top_srcdir)/libexslt \
EXTRA_PROGRAMS=
bin_PROGRAMS = xsltproc $(XSLTPROCDV)
+AM_CFLAGS = $(LIBGCRYPT_CFLAGS)
+
xsltproc_SOURCES = xsltproc.c
-xsltproc_LDFLAGS =
+xsltproc_LDFLAGS =
xsltproc_DEPENDENCIES = $(DEPS)
-xsltproc_LDADD = $(LDADDS)
+xsltproc_LDADD = $(LDADDS) $(LIBGCRYPT_LIBS)
DEPS = $(top_builddir)/libxslt/libxslt.la \
$(top_builddir)/libexslt/libexslt.la