summaryrefslogtreecommitdiff
path: root/libexslt/crypto.c
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 /libexslt/crypto.c
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
Diffstat (limited to 'libexslt/crypto.c')
-rw-r--r--libexslt/crypto.c714
1 files changed, 714 insertions, 0 deletions
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) */