| OLD | NEW |
| (Empty) |
| 1 #define IN_LIBEXSLT | |
| 2 #include "libexslt/libexslt.h" | |
| 3 | |
| 4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__) | |
| 5 #include <win32config.h> | |
| 6 #else | |
| 7 #include "config.h" | |
| 8 #endif | |
| 9 | |
| 10 #include <libxml/tree.h> | |
| 11 #include <libxml/xpath.h> | |
| 12 #include <libxml/xpathInternals.h> | |
| 13 #include <libxml/parser.h> | |
| 14 #include <libxml/encoding.h> | |
| 15 #include <libxml/uri.h> | |
| 16 | |
| 17 #include <libxslt/xsltconfig.h> | |
| 18 #include <libxslt/xsltutils.h> | |
| 19 #include <libxslt/xsltInternals.h> | |
| 20 #include <libxslt/extensions.h> | |
| 21 | |
| 22 #include "exslt.h" | |
| 23 | |
| 24 #ifdef EXSLT_CRYPTO_ENABLED | |
| 25 | |
| 26 #define HASH_DIGEST_LENGTH 32 | |
| 27 #define MD5_DIGEST_LENGTH 16 | |
| 28 #define SHA1_DIGEST_LENGTH 20 | |
| 29 | |
| 30 /* gcrypt rc4 can do 256 bit keys, but cryptoapi limit | |
| 31 seems to be 128 for the default provider */ | |
| 32 #define RC4_KEY_LENGTH 128 | |
| 33 | |
| 34 /* The following routines have been declared static - this should be | |
| 35 reviewed to consider whether we want to expose them to the API | |
| 36 exsltCryptoBin2Hex | |
| 37 exsltCryptoHex2Bin | |
| 38 exsltCryptoGcryptInit | |
| 39 exsltCryptoGcryptHash | |
| 40 exsltCryptoGcryptRc4Encrypt | |
| 41 exsltCryptoGcryptRC4Decrypt | |
| 42 */ | |
| 43 | |
| 44 /** | |
| 45 * exsltCryptoBin2Hex: | |
| 46 * @bin: binary blob to convert | |
| 47 * @binlen: length of binary blob | |
| 48 * @hex: buffer to store hex version of blob | |
| 49 * @hexlen: length of buffer to store hex version of blob | |
| 50 * | |
| 51 * Helper function which encodes a binary blob as hex. | |
| 52 */ | |
| 53 static void | |
| 54 exsltCryptoBin2Hex (const unsigned char *bin, int binlen, | |
| 55 unsigned char *hex, int hexlen) { | |
| 56 static const char bin2hex[] = { '0', '1', '2', '3', | |
| 57 '4', '5', '6', '7', | |
| 58 '8', '9', 'a', 'b', | |
| 59 'c', 'd', 'e', 'f' | |
| 60 }; | |
| 61 | |
| 62 unsigned char lo, hi; | |
| 63 int i, pos; | |
| 64 for (i = 0, pos = 0; (i < binlen && pos < hexlen); i++) { | |
| 65 lo = bin[i] & 0xf; | |
| 66 hi = bin[i] >> 4; | |
| 67 hex[pos++] = bin2hex[hi]; | |
| 68 hex[pos++] = bin2hex[lo]; | |
| 69 } | |
| 70 | |
| 71 hex[pos] = '\0'; | |
| 72 } | |
| 73 | |
| 74 /** | |
| 75 * exsltCryptoHex2Bin: | |
| 76 * @hex: hex version of blob to convert | |
| 77 * @hexlen: length of hex buffer | |
| 78 * @bin: destination binary buffer | |
| 79 * @binlen: length of binary buffer | |
| 80 * | |
| 81 * Helper function which decodes a hex blob to binary | |
| 82 */ | |
| 83 static int | |
| 84 exsltCryptoHex2Bin (const unsigned char *hex, int hexlen, | |
| 85 unsigned char *bin, int binlen) { | |
| 86 int i = 0, j = 0; | |
| 87 unsigned char lo, hi, result, tmp; | |
| 88 | |
| 89 while (i < hexlen && j < binlen) { | |
| 90 hi = lo = 0; | |
| 91 | |
| 92 tmp = hex[i++]; | |
| 93 if (tmp >= '0' && tmp <= '9') | |
| 94 hi = tmp - '0'; | |
| 95 else if (tmp >= 'a' && tmp <= 'f') | |
| 96 hi = 10 + (tmp - 'a'); | |
| 97 | |
| 98 tmp = hex[i++]; | |
| 99 if (tmp >= '0' && tmp <= '9') | |
| 100 lo = tmp - '0'; | |
| 101 else if (tmp >= 'a' && tmp <= 'f') | |
| 102 lo = 10 + (tmp - 'a'); | |
| 103 | |
| 104 result = hi << 4; | |
| 105 result += lo; | |
| 106 bin[j++] = result; | |
| 107 } | |
| 108 | |
| 109 return j; | |
| 110 } | |
| 111 | |
| 112 #if defined(WIN32) | |
| 113 | |
| 114 #define HAVE_CRYPTO | |
| 115 #define PLATFORM_HASH exsltCryptoCryptoApiHash | |
| 116 #define PLATFORM_RC4_ENCRYPT exsltCryptoCryptoApiRc4Encrypt | |
| 117 #define PLATFORM_RC4_DECRYPT exsltCryptoCryptoApiRc4Decrypt | |
| 118 #define PLATFORM_MD4 CALG_MD4 | |
| 119 #define PLATFORM_MD5 CALG_MD5 | |
| 120 #define PLATFORM_SHA1 CALG_SHA1 | |
| 121 | |
| 122 #include <windows.h> | |
| 123 #include <wincrypt.h> | |
| 124 #pragma comment(lib, "advapi32.lib") | |
| 125 | |
| 126 static void | |
| 127 exsltCryptoCryptoApiReportError (xmlXPathParserContextPtr ctxt, | |
| 128 int line) { | |
| 129 LPVOID lpMsgBuf; | |
| 130 DWORD dw = GetLastError (); | |
| 131 | |
| 132 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
| 133 FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, | |
| 134 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), | |
| 135 (LPTSTR) & lpMsgBuf, 0, NULL); | |
| 136 | |
| 137 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL, | |
| 138 "exslt:crypto error (line %d). %s", line, | |
| 139 lpMsgBuf); | |
| 140 LocalFree (lpMsgBuf); | |
| 141 } | |
| 142 | |
| 143 static HCRYPTHASH | |
| 144 exsltCryptoCryptoApiCreateHash (xmlXPathParserContextPtr ctxt, | |
| 145 HCRYPTPROV hCryptProv, ALG_ID algorithm, | |
| 146 const char *msg, unsigned int msglen, | |
| 147 char *dest, unsigned int destlen) | |
| 148 { | |
| 149 HCRYPTHASH hHash = 0; | |
| 150 DWORD dwHashLen = destlen; | |
| 151 | |
| 152 if (!CryptCreateHash (hCryptProv, algorithm, 0, 0, &hHash)) { | |
| 153 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 154 return 0; | |
| 155 } | |
| 156 | |
| 157 if (!CryptHashData (hHash, (const BYTE *) msg, msglen, 0)) { | |
| 158 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 159 goto fail; | |
| 160 } | |
| 161 | |
| 162 if (!CryptGetHashParam (hHash, HP_HASHVAL, dest, &dwHashLen, 0)) { | |
| 163 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 164 goto fail; | |
| 165 } | |
| 166 | |
| 167 fail: | |
| 168 return hHash; | |
| 169 } | |
| 170 | |
| 171 /** | |
| 172 * exsltCryptoCryptoApiHash: | |
| 173 * @ctxt: an XPath parser context | |
| 174 * @algorithm: hashing algorithm to use | |
| 175 * @msg: text to be hashed | |
| 176 * @msglen: length of text to be hashed | |
| 177 * @dest: buffer to place hash result | |
| 178 * | |
| 179 * Helper function which hashes a message using MD4, MD5, or SHA1. | |
| 180 * Uses Win32 CryptoAPI. | |
| 181 */ | |
| 182 static void | |
| 183 exsltCryptoCryptoApiHash (xmlXPathParserContextPtr ctxt, | |
| 184 ALG_ID algorithm, const char *msg, | |
| 185 unsigned long msglen, | |
| 186 char dest[HASH_DIGEST_LENGTH]) { | |
| 187 HCRYPTPROV hCryptProv; | |
| 188 HCRYPTHASH hHash; | |
| 189 | |
| 190 if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, | |
| 191 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { | |
| 192 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 193 return; | |
| 194 } | |
| 195 | |
| 196 hHash = exsltCryptoCryptoApiCreateHash (ctxt, hCryptProv, | |
| 197 algorithm, msg, msglen, | |
| 198 dest, HASH_DIGEST_LENGTH); | |
| 199 if (0 != hHash) { | |
| 200 CryptDestroyHash (hHash); | |
| 201 } | |
| 202 | |
| 203 CryptReleaseContext (hCryptProv, 0); | |
| 204 } | |
| 205 | |
| 206 static void | |
| 207 exsltCryptoCryptoApiRc4Encrypt (xmlXPathParserContextPtr ctxt, | |
| 208 const unsigned char *key, | |
| 209 const unsigned char *msg, int msglen, | |
| 210 unsigned char *dest, int destlen) { | |
| 211 HCRYPTPROV hCryptProv; | |
| 212 HCRYPTKEY hKey; | |
| 213 HCRYPTHASH hHash; | |
| 214 DWORD dwDataLen; | |
| 215 unsigned char hash[HASH_DIGEST_LENGTH]; | |
| 216 | |
| 217 if (msglen > destlen) { | |
| 218 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, | |
| 219 NULL, | |
| 220 "exslt:crypto : internal error exsltCryptoCryptoApiR
c4Encrypt dest buffer too small.\n"); | |
| 221 return; | |
| 222 } | |
| 223 | |
| 224 if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, | |
| 225 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { | |
| 226 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 227 return; | |
| 228 } | |
| 229 | |
| 230 hHash = exsltCryptoCryptoApiCreateHash (ctxt, hCryptProv, | |
| 231 CALG_SHA1, key, | |
| 232 RC4_KEY_LENGTH, hash, | |
| 233 HASH_DIGEST_LENGTH); | |
| 234 | |
| 235 if (!CryptDeriveKey | |
| 236 (hCryptProv, CALG_RC4, hHash, 0x00800000, &hKey)) { | |
| 237 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 238 goto fail; | |
| 239 } | |
| 240 /* Now encrypt data. */ | |
| 241 dwDataLen = msglen; | |
| 242 memcpy (dest, msg, msglen); | |
| 243 if (!CryptEncrypt (hKey, 0, TRUE, 0, dest, &dwDataLen, msglen)) { | |
| 244 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 245 goto fail; | |
| 246 } | |
| 247 | |
| 248 fail: | |
| 249 if (0 != hHash) { | |
| 250 CryptDestroyHash (hHash); | |
| 251 } | |
| 252 | |
| 253 CryptDestroyKey (hKey); | |
| 254 CryptReleaseContext (hCryptProv, 0); | |
| 255 } | |
| 256 | |
| 257 static void | |
| 258 exsltCryptoCryptoApiRc4Decrypt (xmlXPathParserContextPtr ctxt, | |
| 259 const unsigned char *key, | |
| 260 const unsigned char *msg, int msglen, | |
| 261 unsigned char *dest, int destlen) { | |
| 262 HCRYPTPROV hCryptProv; | |
| 263 HCRYPTKEY hKey; | |
| 264 HCRYPTHASH hHash; | |
| 265 DWORD dwDataLen; | |
| 266 unsigned char hash[HASH_DIGEST_LENGTH]; | |
| 267 | |
| 268 if (msglen > destlen) { | |
| 269 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, | |
| 270 NULL, | |
| 271 "exslt:crypto : internal error exsltCryptoCryptoApiR
c4Encrypt dest buffer too small.\n"); | |
| 272 return; | |
| 273 } | |
| 274 | |
| 275 if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, | |
| 276 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { | |
| 277 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 278 return; | |
| 279 } | |
| 280 | |
| 281 hHash = exsltCryptoCryptoApiCreateHash (ctxt, hCryptProv, | |
| 282 CALG_SHA1, key, | |
| 283 RC4_KEY_LENGTH, hash, | |
| 284 HASH_DIGEST_LENGTH); | |
| 285 | |
| 286 if (!CryptDeriveKey | |
| 287 (hCryptProv, CALG_RC4, hHash, 0x00800000, &hKey)) { | |
| 288 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 289 goto fail; | |
| 290 } | |
| 291 /* Now encrypt data. */ | |
| 292 dwDataLen = msglen; | |
| 293 memcpy (dest, msg, msglen); | |
| 294 if (!CryptDecrypt (hKey, 0, TRUE, 0, dest, &dwDataLen)) { | |
| 295 exsltCryptoCryptoApiReportError (ctxt, __LINE__); | |
| 296 goto fail; | |
| 297 } | |
| 298 | |
| 299 fail: | |
| 300 if (0 != hHash) { | |
| 301 CryptDestroyHash (hHash); | |
| 302 } | |
| 303 | |
| 304 CryptDestroyKey (hKey); | |
| 305 CryptReleaseContext (hCryptProv, 0); | |
| 306 } | |
| 307 | |
| 308 #endif /* defined(WIN32) */ | |
| 309 | |
| 310 #if defined(HAVE_GCRYPT) | |
| 311 | |
| 312 #define HAVE_CRYPTO | |
| 313 #define PLATFORM_HASH exsltCryptoGcryptHash | |
| 314 #define PLATFORM_RC4_ENCRYPT exsltCryptoGcryptRc4Encrypt | |
| 315 #define PLATFORM_RC4_DECRYPT exsltCryptoGcryptRc4Decrypt | |
| 316 #define PLATFORM_MD4 GCRY_MD_MD4 | |
| 317 #define PLATFORM_MD5 GCRY_MD_MD5 | |
| 318 #define PLATFORM_SHA1 GCRY_MD_SHA1 | |
| 319 | |
| 320 #ifdef HAVE_SYS_TYPES_H | |
| 321 # include <sys/types.h> | |
| 322 #endif | |
| 323 #ifdef HAVE_STDINT_H | |
| 324 # include <stdint.h> | |
| 325 #endif | |
| 326 | |
| 327 #ifdef HAVE_SYS_SELECT_H | |
| 328 #include <sys/select.h> /* needed by gcrypt.h 4 Jul 04 */ | |
| 329 #endif | |
| 330 #include <gcrypt.h> | |
| 331 | |
| 332 static void | |
| 333 exsltCryptoGcryptInit (void) { | |
| 334 static int gcrypt_init; | |
| 335 xmlLockLibrary (); | |
| 336 | |
| 337 if (!gcrypt_init) { | |
| 338 /* The function `gcry_check_version' must be called before any other | |
| 339 function in the library, because it initializes the thread support | |
| 340 subsystem in Libgcrypt. To achieve this in all generality, it is | |
| 341 necessary to synchronize the call to this function with all other calls | |
| 342 to functions in the library, using the synchronization mechanisms | |
| 343 available in your thread library. (from gcrypt.info) | |
| 344 */ | |
| 345 gcry_check_version (GCRYPT_VERSION); | |
| 346 gcrypt_init = 1; | |
| 347 } | |
| 348 | |
| 349 xmlUnlockLibrary (); | |
| 350 } | |
| 351 | |
| 352 /** | |
| 353 * exsltCryptoGcryptHash: | |
| 354 * @ctxt: an XPath parser context | |
| 355 * @algorithm: hashing algorithm to use | |
| 356 * @msg: text to be hashed | |
| 357 * @msglen: length of text to be hashed | |
| 358 * @dest: buffer to place hash result | |
| 359 * | |
| 360 * Helper function which hashes a message using MD4, MD5, or SHA1. | |
| 361 * using gcrypt | |
| 362 */ | |
| 363 static void | |
| 364 exsltCryptoGcryptHash (xmlXPathParserContextPtr ctxt ATTRIBUTE_UNUSED, | |
| 365 /* changed the enum to int */ | |
| 366 int algorithm, const char *msg, | |
| 367 unsigned long msglen, | |
| 368 char dest[HASH_DIGEST_LENGTH]) { | |
| 369 exsltCryptoGcryptInit (); | |
| 370 gcry_md_hash_buffer (algorithm, dest, msg, msglen); | |
| 371 } | |
| 372 | |
| 373 static void | |
| 374 exsltCryptoGcryptRc4Encrypt (xmlXPathParserContextPtr ctxt, | |
| 375 const unsigned char *key, | |
| 376 const unsigned char *msg, int msglen, | |
| 377 unsigned char *dest, int destlen) { | |
| 378 gcry_cipher_hd_t cipher; | |
| 379 gcry_error_t rc = 0; | |
| 380 | |
| 381 exsltCryptoGcryptInit (); | |
| 382 | |
| 383 rc = gcry_cipher_open (&cipher, GCRY_CIPHER_ARCFOUR, | |
| 384 GCRY_CIPHER_MODE_STREAM, 0); | |
| 385 if (rc) { | |
| 386 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, | |
| 387 NULL, | |
| 388 "exslt:crypto internal error %s (gcry_cipher_open)\n
", | |
| 389 gcry_strerror (rc)); | |
| 390 } | |
| 391 | |
| 392 rc = gcry_cipher_setkey (cipher, key, RC4_KEY_LENGTH); | |
| 393 if (rc) { | |
| 394 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, | |
| 395 NULL, | |
| 396 "exslt:crypto internal error %s (gcry_cipher_setkey)
\n", | |
| 397 gcry_strerror (rc)); | |
| 398 } | |
| 399 | |
| 400 rc = gcry_cipher_encrypt (cipher, (unsigned char *) dest, destlen, | |
| 401 (const unsigned char *) msg, msglen); | |
| 402 if (rc) { | |
| 403 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, | |
| 404 NULL, | |
| 405 "exslt:crypto internal error %s (gcry_cipher_encrypt
)\n", | |
| 406 gcry_strerror (rc)); | |
| 407 } | |
| 408 | |
| 409 gcry_cipher_close (cipher); | |
| 410 } | |
| 411 | |
| 412 static void | |
| 413 exsltCryptoGcryptRc4Decrypt (xmlXPathParserContextPtr ctxt, | |
| 414 const unsigned char *key, | |
| 415 const unsigned char *msg, int msglen, | |
| 416 unsigned char *dest, int destlen) { | |
| 417 gcry_cipher_hd_t cipher; | |
| 418 gcry_error_t rc = 0; | |
| 419 | |
| 420 exsltCryptoGcryptInit (); | |
| 421 | |
| 422 rc = gcry_cipher_open (&cipher, GCRY_CIPHER_ARCFOUR, | |
| 423 GCRY_CIPHER_MODE_STREAM, 0); | |
| 424 if (rc) { | |
| 425 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, | |
| 426 NULL, | |
| 427 "exslt:crypto internal error %s (gcry_cipher_open)\n
", | |
| 428 gcry_strerror (rc)); | |
| 429 } | |
| 430 | |
| 431 rc = gcry_cipher_setkey (cipher, key, RC4_KEY_LENGTH); | |
| 432 if (rc) { | |
| 433 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, | |
| 434 NULL, | |
| 435 "exslt:crypto internal error %s (gcry_cipher_setkey)
\n", | |
| 436 gcry_strerror (rc)); | |
| 437 } | |
| 438 | |
| 439 rc = gcry_cipher_decrypt (cipher, (unsigned char *) dest, destlen, | |
| 440 (const unsigned char *) msg, msglen); | |
| 441 if (rc) { | |
| 442 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, | |
| 443 NULL, | |
| 444 "exslt:crypto internal error %s (gcry_cipher_decrypt
)\n", | |
| 445 gcry_strerror (rc)); | |
| 446 } | |
| 447 | |
| 448 gcry_cipher_close (cipher); | |
| 449 } | |
| 450 | |
| 451 #endif /* defined(HAVE_GCRYPT) */ | |
| 452 | |
| 453 #if defined(HAVE_CRYPTO) | |
| 454 | |
| 455 /** | |
| 456 * exsltCryptoPopString: | |
| 457 * @ctxt: an XPath parser context | |
| 458 * @nargs: the number of arguments | |
| 459 * | |
| 460 * Helper function which checks for and returns first string argument and its | |
| 461 * length in bytes. | |
| 462 */ | |
| 463 static int | |
| 464 exsltCryptoPopString (xmlXPathParserContextPtr ctxt, int nargs, | |
| 465 xmlChar ** str) { | |
| 466 | |
| 467 int str_len = 0; | |
| 468 | |
| 469 if ((nargs < 1) || (nargs > 2)) { | |
| 470 xmlXPathSetArityError (ctxt); | |
| 471 return 0; | |
| 472 } | |
| 473 | |
| 474 *str = xmlXPathPopString (ctxt); | |
| 475 str_len = xmlStrlen (*str); | |
| 476 | |
| 477 if (str_len == 0) { | |
| 478 xmlXPathReturnEmptyString (ctxt); | |
| 479 xmlFree (*str); | |
| 480 return 0; | |
| 481 } | |
| 482 | |
| 483 return str_len; | |
| 484 } | |
| 485 | |
| 486 /** | |
| 487 * exsltCryptoMd4Function: | |
| 488 * @ctxt: an XPath parser context | |
| 489 * @nargs: the number of arguments | |
| 490 * | |
| 491 * computes the md4 hash of a string and returns as hex | |
| 492 */ | |
| 493 static void | |
| 494 exsltCryptoMd4Function (xmlXPathParserContextPtr ctxt, int nargs) { | |
| 495 | |
| 496 int str_len = 0; | |
| 497 xmlChar *str = NULL, *ret = NULL; | |
| 498 unsigned char hash[HASH_DIGEST_LENGTH]; | |
| 499 unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1]; | |
| 500 | |
| 501 str_len = exsltCryptoPopString (ctxt, nargs, &str); | |
| 502 if (str_len == 0) | |
| 503 return; | |
| 504 | |
| 505 PLATFORM_HASH (ctxt, PLATFORM_MD4, (const char *) str, str_len, | |
| 506 (char *) hash); | |
| 507 exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); | |
| 508 | |
| 509 ret = xmlStrdup ((xmlChar *) hex); | |
| 510 xmlXPathReturnString (ctxt, ret); | |
| 511 | |
| 512 if (str != NULL) | |
| 513 xmlFree (str); | |
| 514 } | |
| 515 | |
| 516 /** | |
| 517 * exsltCryptoMd5Function: | |
| 518 * @ctxt: an XPath parser context | |
| 519 * @nargs: the number of arguments | |
| 520 * | |
| 521 * computes the md5 hash of a string and returns as hex | |
| 522 */ | |
| 523 static void | |
| 524 exsltCryptoMd5Function (xmlXPathParserContextPtr ctxt, int nargs) { | |
| 525 | |
| 526 int str_len = 0; | |
| 527 xmlChar *str = NULL, *ret = NULL; | |
| 528 unsigned char hash[HASH_DIGEST_LENGTH]; | |
| 529 unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1]; | |
| 530 | |
| 531 str_len = exsltCryptoPopString (ctxt, nargs, &str); | |
| 532 if (str_len == 0) | |
| 533 return; | |
| 534 | |
| 535 PLATFORM_HASH (ctxt, PLATFORM_MD5, (const char *) str, str_len, | |
| 536 (char *) hash); | |
| 537 exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); | |
| 538 | |
| 539 ret = xmlStrdup ((xmlChar *) hex); | |
| 540 xmlXPathReturnString (ctxt, ret); | |
| 541 | |
| 542 if (str != NULL) | |
| 543 xmlFree (str); | |
| 544 } | |
| 545 | |
| 546 /** | |
| 547 * exsltCryptoSha1Function: | |
| 548 * @ctxt: an XPath parser context | |
| 549 * @nargs: the number of arguments | |
| 550 * | |
| 551 * computes the sha1 hash of a string and returns as hex | |
| 552 */ | |
| 553 static void | |
| 554 exsltCryptoSha1Function (xmlXPathParserContextPtr ctxt, int nargs) { | |
| 555 | |
| 556 int str_len = 0; | |
| 557 xmlChar *str = NULL, *ret = NULL; | |
| 558 unsigned char hash[HASH_DIGEST_LENGTH]; | |
| 559 unsigned char hex[SHA1_DIGEST_LENGTH * 2 + 1]; | |
| 560 | |
| 561 str_len = exsltCryptoPopString (ctxt, nargs, &str); | |
| 562 if (str_len == 0) | |
| 563 return; | |
| 564 | |
| 565 PLATFORM_HASH (ctxt, PLATFORM_SHA1, (const char *) str, str_len, | |
| 566 (char *) hash); | |
| 567 exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); | |
| 568 | |
| 569 ret = xmlStrdup ((xmlChar *) hex); | |
| 570 xmlXPathReturnString (ctxt, ret); | |
| 571 | |
| 572 if (str != NULL) | |
| 573 xmlFree (str); | |
| 574 } | |
| 575 | |
| 576 /** | |
| 577 * exsltCryptoRc4EncryptFunction: | |
| 578 * @ctxt: an XPath parser context | |
| 579 * @nargs: the number of arguments | |
| 580 * | |
| 581 * computes the sha1 hash of a string and returns as hex | |
| 582 */ | |
| 583 static void | |
| 584 exsltCryptoRc4EncryptFunction (xmlXPathParserContextPtr ctxt, int nargs) { | |
| 585 | |
| 586 int key_len = 0; | |
| 587 int str_len = 0, bin_len = 0, hex_len = 0; | |
| 588 xmlChar *key = NULL, *str = NULL, *padkey = NULL; | |
| 589 xmlChar *bin = NULL, *hex = NULL; | |
| 590 xsltTransformContextPtr tctxt = NULL; | |
| 591 | |
| 592 if (nargs != 2) { | |
| 593 xmlXPathSetArityError (ctxt); | |
| 594 return; | |
| 595 } | |
| 596 tctxt = xsltXPathGetTransformContext(ctxt); | |
| 597 | |
| 598 str = xmlXPathPopString (ctxt); | |
| 599 str_len = xmlStrlen (str); | |
| 600 | |
| 601 if (str_len == 0) { | |
| 602 xmlXPathReturnEmptyString (ctxt); | |
| 603 xmlFree (str); | |
| 604 return; | |
| 605 } | |
| 606 | |
| 607 key = xmlXPathPopString (ctxt); | |
| 608 key_len = xmlStrlen (key); | |
| 609 | |
| 610 if (key_len == 0) { | |
| 611 xmlXPathReturnEmptyString (ctxt); | |
| 612 xmlFree (key); | |
| 613 xmlFree (str); | |
| 614 return; | |
| 615 } | |
| 616 | |
| 617 padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1); | |
| 618 if (padkey == NULL) { | |
| 619 xsltTransformError(tctxt, NULL, tctxt->inst, | |
| 620 "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n"); | |
| 621 tctxt->state = XSLT_STATE_STOPPED; | |
| 622 xmlXPathReturnEmptyString (ctxt); | |
| 623 goto done; | |
| 624 } | |
| 625 memset(padkey, 0, RC4_KEY_LENGTH + 1); | |
| 626 | |
| 627 if ((key_len > RC4_KEY_LENGTH) || (key_len < 0)) { | |
| 628 xsltTransformError(tctxt, NULL, tctxt->inst, | |
| 629 "exsltCryptoRc4EncryptFunction: key size too long or key broken\n"); | |
| 630 tctxt->state = XSLT_STATE_STOPPED; | |
| 631 xmlXPathReturnEmptyString (ctxt); | |
| 632 goto done; | |
| 633 } | |
| 634 memcpy (padkey, key, key_len); | |
| 635 | |
| 636 /* encrypt it */ | |
| 637 bin_len = str_len; | |
| 638 bin = xmlStrdup (str); | |
| 639 if (bin == NULL) { | |
| 640 xsltTransformError(tctxt, NULL, tctxt->inst, | |
| 641 "exsltCryptoRc4EncryptFunction: Failed to allocate string\n"); | |
| 642 tctxt->state = XSLT_STATE_STOPPED; | |
| 643 xmlXPathReturnEmptyString (ctxt); | |
| 644 goto done; | |
| 645 } | |
| 646 PLATFORM_RC4_ENCRYPT (ctxt, padkey, str, str_len, bin, bin_len); | |
| 647 | |
| 648 /* encode it */ | |
| 649 hex_len = str_len * 2 + 1; | |
| 650 hex = xmlMallocAtomic (hex_len); | |
| 651 if (hex == NULL) { | |
| 652 xsltTransformError(tctxt, NULL, tctxt->inst, | |
| 653 "exsltCryptoRc4EncryptFunction: Failed to allocate result\n"); | |
| 654 tctxt->state = XSLT_STATE_STOPPED; | |
| 655 xmlXPathReturnEmptyString (ctxt); | |
| 656 goto done; | |
| 657 } | |
| 658 | |
| 659 exsltCryptoBin2Hex (bin, str_len, hex, hex_len); | |
| 660 xmlXPathReturnString (ctxt, hex); | |
| 661 | |
| 662 done: | |
| 663 if (key != NULL) | |
| 664 xmlFree (key); | |
| 665 if (str != NULL) | |
| 666 xmlFree (str); | |
| 667 if (padkey != NULL) | |
| 668 xmlFree (padkey); | |
| 669 if (bin != NULL) | |
| 670 xmlFree (bin); | |
| 671 } | |
| 672 | |
| 673 /** | |
| 674 * exsltCryptoRc4DecryptFunction: | |
| 675 * @ctxt: an XPath parser context | |
| 676 * @nargs: the number of arguments | |
| 677 * | |
| 678 * computes the sha1 hash of a string and returns as hex | |
| 679 */ | |
| 680 static void | |
| 681 exsltCryptoRc4DecryptFunction (xmlXPathParserContextPtr ctxt, int nargs) { | |
| 682 | |
| 683 int key_len = 0; | |
| 684 int str_len = 0, bin_len = 0, ret_len = 0; | |
| 685 xmlChar *key = NULL, *str = NULL, *padkey = NULL, *bin = | |
| 686 NULL, *ret = NULL; | |
| 687 xsltTransformContextPtr tctxt = NULL; | |
| 688 | |
| 689 if (nargs != 2) { | |
| 690 xmlXPathSetArityError (ctxt); | |
| 691 return; | |
| 692 } | |
| 693 tctxt = xsltXPathGetTransformContext(ctxt); | |
| 694 | |
| 695 str = xmlXPathPopString (ctxt); | |
| 696 str_len = xmlStrlen (str); | |
| 697 | |
| 698 if (str_len == 0) { | |
| 699 xmlXPathReturnEmptyString (ctxt); | |
| 700 xmlFree (str); | |
| 701 return; | |
| 702 } | |
| 703 | |
| 704 key = xmlXPathPopString (ctxt); | |
| 705 key_len = xmlStrlen (key); | |
| 706 | |
| 707 if (key_len == 0) { | |
| 708 xmlXPathReturnEmptyString (ctxt); | |
| 709 xmlFree (key); | |
| 710 xmlFree (str); | |
| 711 return; | |
| 712 } | |
| 713 | |
| 714 padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1); | |
| 715 if (padkey == NULL) { | |
| 716 xsltTransformError(tctxt, NULL, tctxt->inst, | |
| 717 "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n"); | |
| 718 tctxt->state = XSLT_STATE_STOPPED; | |
| 719 xmlXPathReturnEmptyString (ctxt); | |
| 720 goto done; | |
| 721 } | |
| 722 memset(padkey, 0, RC4_KEY_LENGTH + 1); | |
| 723 if ((key_len > RC4_KEY_LENGTH) || (key_len < 0)) { | |
| 724 xsltTransformError(tctxt, NULL, tctxt->inst, | |
| 725 "exsltCryptoRc4EncryptFunction: key size too long or key broken\n"); | |
| 726 tctxt->state = XSLT_STATE_STOPPED; | |
| 727 xmlXPathReturnEmptyString (ctxt); | |
| 728 goto done; | |
| 729 } | |
| 730 memcpy (padkey, key, key_len); | |
| 731 | |
| 732 /* decode hex to binary */ | |
| 733 bin_len = str_len; | |
| 734 bin = xmlMallocAtomic (bin_len); | |
| 735 if (bin == NULL) { | |
| 736 xsltTransformError(tctxt, NULL, tctxt->inst, | |
| 737 "exsltCryptoRc4EncryptFunction: Failed to allocate string\n"); | |
| 738 tctxt->state = XSLT_STATE_STOPPED; | |
| 739 xmlXPathReturnEmptyString (ctxt); | |
| 740 goto done; | |
| 741 } | |
| 742 ret_len = exsltCryptoHex2Bin (str, str_len, bin, bin_len); | |
| 743 | |
| 744 /* decrypt the binary blob */ | |
| 745 ret = xmlMallocAtomic (ret_len + 1); | |
| 746 if (ret == NULL) { | |
| 747 xsltTransformError(tctxt, NULL, tctxt->inst, | |
| 748 "exsltCryptoRc4EncryptFunction: Failed to allocate result\n"); | |
| 749 tctxt->state = XSLT_STATE_STOPPED; | |
| 750 xmlXPathReturnEmptyString (ctxt); | |
| 751 goto done; | |
| 752 } | |
| 753 PLATFORM_RC4_DECRYPT (ctxt, padkey, bin, ret_len, ret, ret_len); | |
| 754 ret[ret_len] = 0; | |
| 755 | |
| 756 xmlXPathReturnString (ctxt, ret); | |
| 757 | |
| 758 done: | |
| 759 if (key != NULL) | |
| 760 xmlFree (key); | |
| 761 if (str != NULL) | |
| 762 xmlFree (str); | |
| 763 if (padkey != NULL) | |
| 764 xmlFree (padkey); | |
| 765 if (bin != NULL) | |
| 766 xmlFree (bin); | |
| 767 } | |
| 768 | |
| 769 /** | |
| 770 * exsltCryptoRegister: | |
| 771 * | |
| 772 * Registers the EXSLT - Crypto module | |
| 773 */ | |
| 774 | |
| 775 void | |
| 776 exsltCryptoRegister (void) { | |
| 777 xsltRegisterExtModuleFunction ((const xmlChar *) "md4", | |
| 778 EXSLT_CRYPTO_NAMESPACE, | |
| 779 exsltCryptoMd4Function); | |
| 780 xsltRegisterExtModuleFunction ((const xmlChar *) "md5", | |
| 781 EXSLT_CRYPTO_NAMESPACE, | |
| 782 exsltCryptoMd5Function); | |
| 783 xsltRegisterExtModuleFunction ((const xmlChar *) "sha1", | |
| 784 EXSLT_CRYPTO_NAMESPACE, | |
| 785 exsltCryptoSha1Function); | |
| 786 xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_encrypt", | |
| 787 EXSLT_CRYPTO_NAMESPACE, | |
| 788 exsltCryptoRc4EncryptFunction); | |
| 789 xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_decrypt", | |
| 790 EXSLT_CRYPTO_NAMESPACE, | |
| 791 exsltCryptoRc4DecryptFunction); | |
| 792 } | |
| 793 | |
| 794 #else | |
| 795 /** | |
| 796 * exsltCryptoRegister: | |
| 797 * | |
| 798 * Registers the EXSLT - Crypto module | |
| 799 */ | |
| 800 void | |
| 801 exsltCryptoRegister (void) { | |
| 802 } | |
| 803 | |
| 804 #endif /* defined(HAVE_CRYPTO) */ | |
| 805 | |
| 806 #endif /* EXSLT_CRYPTO_ENABLED */ | |
| OLD | NEW |