This source file includes following definitions.
- exsltCryptoBin2Hex
- exsltCryptoHex2Bin
- exsltCryptoCryptoApiReportError
- exsltCryptoCryptoApiCreateHash
- exsltCryptoCryptoApiHash
- exsltCryptoCryptoApiRc4Encrypt
- exsltCryptoCryptoApiRc4Decrypt
- exsltCryptoGcryptInit
- exsltCryptoGcryptHash
- exsltCryptoGcryptRc4Encrypt
- exsltCryptoGcryptRc4Decrypt
- exsltCryptoPopString
- exsltCryptoMd4Function
- exsltCryptoMd5Function
- exsltCryptoSha1Function
- exsltCryptoRc4EncryptFunction
- exsltCryptoRc4DecryptFunction
- exsltCryptoRegister
- exsltCryptoRegister
#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"
#ifdef EXSLT_CRYPTO_ENABLED
#define HASH_DIGEST_LENGTH 32
#define MD5_DIGEST_LENGTH 16
#define SHA1_DIGEST_LENGTH 20
#define RC4_KEY_LENGTH 128
static 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';
}
static 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")
static 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);
}
static 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;
}
static 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);
}
static 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;
}
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);
}
static 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;
}
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
#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
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <gcrypt.h>
static void
exsltCryptoGcryptInit (void) {
static int gcrypt_init;
xmlLockLibrary ();
if (!gcrypt_init) {
gcry_check_version (GCRYPT_VERSION);
gcrypt_init = 1;
}
xmlUnlockLibrary ();
}
static void
exsltCryptoGcryptHash (xmlXPathParserContextPtr ctxt ATTRIBUTE_UNUSED,
int algorithm, const char *msg,
unsigned long msglen,
char dest[HASH_DIGEST_LENGTH]) {
exsltCryptoGcryptInit ();
gcry_md_hash_buffer (algorithm, dest, msg, msglen);
}
static 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);
}
static 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
#if defined(HAVE_CRYPTO)
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;
}
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, (const char *) str, str_len,
(char *) hash);
exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1);
ret = xmlStrdup ((xmlChar *) hex);
xmlXPathReturnString (ctxt, ret);
if (str != NULL)
xmlFree (str);
}
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, (const char *) str, str_len,
(char *) hash);
exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1);
ret = xmlStrdup ((xmlChar *) hex);
xmlXPathReturnString (ctxt, ret);
if (str != NULL)
xmlFree (str);
}
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, (const char *) str, str_len,
(char *) hash);
exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1);
ret = xmlStrdup ((xmlChar *) hex);
xmlXPathReturnString (ctxt, ret);
if (str != NULL)
xmlFree (str);
}
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;
xsltTransformContextPtr tctxt = NULL;
if (nargs != 2) {
xmlXPathSetArityError (ctxt);
return;
}
tctxt = xsltXPathGetTransformContext(ctxt);
str = xmlXPathPopString (ctxt);
str_len = xmlUTF8Strlen (str);
if (str_len == 0) {
xmlXPathReturnEmptyString (ctxt);
xmlFree (str);
return;
}
key = xmlXPathPopString (ctxt);
key_len = xmlUTF8Strlen (key);
if (key_len == 0) {
xmlXPathReturnEmptyString (ctxt);
xmlFree (key);
xmlFree (str);
return;
}
padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1);
if (padkey == NULL) {
xsltTransformError(tctxt, NULL, tctxt->inst,
"exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n");
tctxt->state = XSLT_STATE_STOPPED;
xmlXPathReturnEmptyString (ctxt);
goto done;
}
memset(padkey, 0, RC4_KEY_LENGTH + 1);
key_size = xmlUTF8Strsize (key, key_len);
if ((key_size > RC4_KEY_LENGTH) || (key_size < 0)) {
xsltTransformError(tctxt, NULL, tctxt->inst,
"exsltCryptoRc4EncryptFunction: key size too long or key broken\n");
tctxt->state = XSLT_STATE_STOPPED;
xmlXPathReturnEmptyString (ctxt);
goto done;
}
memcpy (padkey, key, key_size);
bin_len = str_len;
bin = xmlStrdup (str);
if (bin == NULL) {
xsltTransformError(tctxt, NULL, tctxt->inst,
"exsltCryptoRc4EncryptFunction: Failed to allocate string\n");
tctxt->state = XSLT_STATE_STOPPED;
xmlXPathReturnEmptyString (ctxt);
goto done;
}
PLATFORM_RC4_ENCRYPT (ctxt, padkey, str, str_len, bin, bin_len);
hex_len = str_len * 2 + 1;
hex = xmlMallocAtomic (hex_len);
if (hex == NULL) {
xsltTransformError(tctxt, NULL, tctxt->inst,
"exsltCryptoRc4EncryptFunction: Failed to allocate result\n");
tctxt->state = XSLT_STATE_STOPPED;
xmlXPathReturnEmptyString (ctxt);
goto done;
}
exsltCryptoBin2Hex (bin, str_len, hex, hex_len);
xmlXPathReturnString (ctxt, hex);
done:
if (key != NULL)
xmlFree (key);
if (str != NULL)
xmlFree (str);
if (padkey != NULL)
xmlFree (padkey);
if (bin != NULL)
xmlFree (bin);
}
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;
xsltTransformContextPtr tctxt = NULL;
if (nargs != 2) {
xmlXPathSetArityError (ctxt);
return;
}
tctxt = xsltXPathGetTransformContext(ctxt);
str = xmlXPathPopString (ctxt);
str_len = xmlUTF8Strlen (str);
if (str_len == 0) {
xmlXPathReturnEmptyString (ctxt);
xmlFree (str);
return;
}
key = xmlXPathPopString (ctxt);
key_len = xmlUTF8Strlen (key);
if (key_len == 0) {
xmlXPathReturnEmptyString (ctxt);
xmlFree (key);
xmlFree (str);
return;
}
padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1);
if (padkey == NULL) {
xsltTransformError(tctxt, NULL, tctxt->inst,
"exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n");
tctxt->state = XSLT_STATE_STOPPED;
xmlXPathReturnEmptyString (ctxt);
goto done;
}
memset(padkey, 0, RC4_KEY_LENGTH + 1);
key_size = xmlUTF8Strsize (key, key_len);
if ((key_size > RC4_KEY_LENGTH) || (key_size < 0)) {
xsltTransformError(tctxt, NULL, tctxt->inst,
"exsltCryptoRc4EncryptFunction: key size too long or key broken\n");
tctxt->state = XSLT_STATE_STOPPED;
xmlXPathReturnEmptyString (ctxt);
goto done;
}
memcpy (padkey, key, key_size);
bin_len = str_len;
bin = xmlMallocAtomic (bin_len);
if (bin == NULL) {
xsltTransformError(tctxt, NULL, tctxt->inst,
"exsltCryptoRc4EncryptFunction: Failed to allocate string\n");
tctxt->state = XSLT_STATE_STOPPED;
xmlXPathReturnEmptyString (ctxt);
goto done;
}
ret_len = exsltCryptoHex2Bin (str, str_len, bin, bin_len);
ret = xmlMallocAtomic (ret_len);
if (ret == NULL) {
xsltTransformError(tctxt, NULL, tctxt->inst,
"exsltCryptoRc4EncryptFunction: Failed to allocate result\n");
tctxt->state = XSLT_STATE_STOPPED;
xmlXPathReturnEmptyString (ctxt);
goto done;
}
PLATFORM_RC4_DECRYPT (ctxt, padkey, bin, ret_len, ret, ret_len);
xmlXPathReturnString (ctxt, ret);
done:
if (key != NULL)
xmlFree (key);
if (str != NULL)
xmlFree (str);
if (padkey != NULL)
xmlFree (padkey);
if (bin != NULL)
xmlFree (bin);
}
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
#endif