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 exsltCryptoCryptoApiRc4Encrypt 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 exsltCryptoCryptoApiRc4Encrypt 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 length 461 */ 462 static int 463 exsltCryptoPopString (xmlXPathParserContextPtr ctxt, int nargs, 464 xmlChar ** str) { 465 466 int str_len = 0; 467 468 if ((nargs < 1) || (nargs > 2)) { 469 xmlXPathSetArityError (ctxt); 470 return 0; 471 } 472 473 *str = xmlXPathPopString (ctxt); 474 str_len = xmlUTF8Strlen (*str); 475 476 if (str_len == 0) { 477 xmlXPathReturnEmptyString (ctxt); 478 xmlFree (*str); 479 return 0; 480 } 481 482 return str_len; 483 } 484 485 /** 486 * exsltCryptoMd4Function: 487 * @ctxt: an XPath parser context 488 * @nargs: the number of arguments 489 * 490 * computes the md4 hash of a string and returns as hex 491 */ 492 static void 493 exsltCryptoMd4Function (xmlXPathParserContextPtr ctxt, int nargs) { 494 495 int str_len = 0; 496 xmlChar *str = NULL, *ret = NULL; 497 unsigned char hash[HASH_DIGEST_LENGTH]; 498 unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1]; 499 500 str_len = exsltCryptoPopString (ctxt, nargs, &str); 501 if (str_len == 0) { 502 xmlXPathReturnEmptyString (ctxt); 503 xmlFree (str); 504 return; 505 } 506 507 PLATFORM_HASH (ctxt, PLATFORM_MD4, (const char *) str, str_len, 508 (char *) hash); 509 exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); 510 511 ret = xmlStrdup ((xmlChar *) hex); 512 xmlXPathReturnString (ctxt, ret); 513 514 if (str != NULL) 515 xmlFree (str); 516 } 517 518 /** 519 * exsltCryptoMd5Function: 520 * @ctxt: an XPath parser context 521 * @nargs: the number of arguments 522 * 523 * computes the md5 hash of a string and returns as hex 524 */ 525 static void 526 exsltCryptoMd5Function (xmlXPathParserContextPtr ctxt, int nargs) { 527 528 int str_len = 0; 529 xmlChar *str = NULL, *ret = NULL; 530 unsigned char hash[HASH_DIGEST_LENGTH]; 531 unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1]; 532 533 str_len = exsltCryptoPopString (ctxt, nargs, &str); 534 if (str_len == 0) { 535 xmlXPathReturnEmptyString (ctxt); 536 xmlFree (str); 537 return; 538 } 539 540 PLATFORM_HASH (ctxt, PLATFORM_MD5, (const char *) str, str_len, 541 (char *) hash); 542 exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); 543 544 ret = xmlStrdup ((xmlChar *) hex); 545 xmlXPathReturnString (ctxt, ret); 546 547 if (str != NULL) 548 xmlFree (str); 549 } 550 551 /** 552 * exsltCryptoSha1Function: 553 * @ctxt: an XPath parser context 554 * @nargs: the number of arguments 555 * 556 * computes the sha1 hash of a string and returns as hex 557 */ 558 static void 559 exsltCryptoSha1Function (xmlXPathParserContextPtr ctxt, int nargs) { 560 561 int str_len = 0; 562 xmlChar *str = NULL, *ret = NULL; 563 unsigned char hash[HASH_DIGEST_LENGTH]; 564 unsigned char hex[SHA1_DIGEST_LENGTH * 2 + 1]; 565 566 str_len = exsltCryptoPopString (ctxt, nargs, &str); 567 if (str_len == 0) { 568 xmlXPathReturnEmptyString (ctxt); 569 xmlFree (str); 570 return; 571 } 572 573 PLATFORM_HASH (ctxt, PLATFORM_SHA1, (const char *) str, str_len, 574 (char *) hash); 575 exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); 576 577 ret = xmlStrdup ((xmlChar *) hex); 578 xmlXPathReturnString (ctxt, ret); 579 580 if (str != NULL) 581 xmlFree (str); 582 } 583 584 /** 585 * exsltCryptoRc4EncryptFunction: 586 * @ctxt: an XPath parser context 587 * @nargs: the number of arguments 588 * 589 * computes the sha1 hash of a string and returns as hex 590 */ 591 static void 592 exsltCryptoRc4EncryptFunction (xmlXPathParserContextPtr ctxt, int nargs) { 593 594 int key_len = 0, key_size = 0; 595 int str_len = 0, bin_len = 0, hex_len = 0; 596 xmlChar *key = NULL, *str = NULL, *padkey = NULL; 597 xmlChar *bin = NULL, *hex = NULL; 598 xsltTransformContextPtr tctxt = NULL; 599 600 if (nargs != 2) { 601 xmlXPathSetArityError (ctxt); 602 return; 603 } 604 tctxt = xsltXPathGetTransformContext(ctxt); 605 606 str = xmlXPathPopString (ctxt); 607 str_len = xmlUTF8Strlen (str); 608 609 if (str_len == 0) { 610 xmlXPathReturnEmptyString (ctxt); 611 xmlFree (str); 612 return; 613 } 614 615 key = xmlXPathPopString (ctxt); 616 key_len = xmlUTF8Strlen (key); 617 618 if (key_len == 0) { 619 xmlXPathReturnEmptyString (ctxt); 620 xmlFree (key); 621 xmlFree (str); 622 return; 623 } 624 625 padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1); 626 if (padkey == NULL) { 627 xsltTransformError(tctxt, NULL, tctxt->inst, 628 "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n"); 629 tctxt->state = XSLT_STATE_STOPPED; 630 xmlXPathReturnEmptyString (ctxt); 631 goto done; 632 } 633 memset(padkey, 0, RC4_KEY_LENGTH + 1); 634 635 key_size = xmlUTF8Strsize (key, key_len); 636 if ((key_size > RC4_KEY_LENGTH) || (key_size < 0)) { 637 xsltTransformError(tctxt, NULL, tctxt->inst, 638 "exsltCryptoRc4EncryptFunction: key size too long or key broken\n"); 639 tctxt->state = XSLT_STATE_STOPPED; 640 xmlXPathReturnEmptyString (ctxt); 641 goto done; 642 } 643 memcpy (padkey, key, key_size); 644 645 /* encrypt it */ 646 bin_len = str_len; 647 bin = xmlStrdup (str); 648 if (bin == NULL) { 649 xsltTransformError(tctxt, NULL, tctxt->inst, 650 "exsltCryptoRc4EncryptFunction: Failed to allocate string\n"); 651 tctxt->state = XSLT_STATE_STOPPED; 652 xmlXPathReturnEmptyString (ctxt); 653 goto done; 654 } 655 PLATFORM_RC4_ENCRYPT (ctxt, padkey, str, str_len, bin, bin_len); 656 657 /* encode it */ 658 hex_len = str_len * 2 + 1; 659 hex = xmlMallocAtomic (hex_len); 660 if (hex == NULL) { 661 xsltTransformError(tctxt, NULL, tctxt->inst, 662 "exsltCryptoRc4EncryptFunction: Failed to allocate result\n"); 663 tctxt->state = XSLT_STATE_STOPPED; 664 xmlXPathReturnEmptyString (ctxt); 665 goto done; 666 } 667 668 exsltCryptoBin2Hex (bin, str_len, hex, hex_len); 669 xmlXPathReturnString (ctxt, hex); 670 671 done: 672 if (key != NULL) 673 xmlFree (key); 674 if (str != NULL) 675 xmlFree (str); 676 if (padkey != NULL) 677 xmlFree (padkey); 678 if (bin != NULL) 679 xmlFree (bin); 680 } 681 682 /** 683 * exsltCryptoRc4DecryptFunction: 684 * @ctxt: an XPath parser context 685 * @nargs: the number of arguments 686 * 687 * computes the sha1 hash of a string and returns as hex 688 */ 689 static void 690 exsltCryptoRc4DecryptFunction (xmlXPathParserContextPtr ctxt, int nargs) { 691 692 int key_len = 0, key_size = 0; 693 int str_len = 0, bin_len = 0, ret_len = 0; 694 xmlChar *key = NULL, *str = NULL, *padkey = NULL, *bin = 695 NULL, *ret = NULL; 696 xsltTransformContextPtr tctxt = NULL; 697 698 if (nargs != 2) { 699 xmlXPathSetArityError (ctxt); 700 return; 701 } 702 tctxt = xsltXPathGetTransformContext(ctxt); 703 704 str = xmlXPathPopString (ctxt); 705 str_len = xmlUTF8Strlen (str); 706 707 if (str_len == 0) { 708 xmlXPathReturnEmptyString (ctxt); 709 xmlFree (str); 710 return; 711 } 712 713 key = xmlXPathPopString (ctxt); 714 key_len = xmlUTF8Strlen (key); 715 716 if (key_len == 0) { 717 xmlXPathReturnEmptyString (ctxt); 718 xmlFree (key); 719 xmlFree (str); 720 return; 721 } 722 723 padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1); 724 if (padkey == NULL) { 725 xsltTransformError(tctxt, NULL, tctxt->inst, 726 "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n"); 727 tctxt->state = XSLT_STATE_STOPPED; 728 xmlXPathReturnEmptyString (ctxt); 729 goto done; 730 } 731 memset(padkey, 0, RC4_KEY_LENGTH + 1); 732 key_size = xmlUTF8Strsize (key, key_len); 733 if ((key_size > RC4_KEY_LENGTH) || (key_size < 0)) { 734 xsltTransformError(tctxt, NULL, tctxt->inst, 735 "exsltCryptoRc4EncryptFunction: key size too long or key broken\n"); 736 tctxt->state = XSLT_STATE_STOPPED; 737 xmlXPathReturnEmptyString (ctxt); 738 goto done; 739 } 740 memcpy (padkey, key, key_size); 741 742 /* decode hex to binary */ 743 bin_len = str_len; 744 bin = xmlMallocAtomic (bin_len); 745 if (bin == NULL) { 746 xsltTransformError(tctxt, NULL, tctxt->inst, 747 "exsltCryptoRc4EncryptFunction: Failed to allocate string\n"); 748 tctxt->state = XSLT_STATE_STOPPED; 749 xmlXPathReturnEmptyString (ctxt); 750 goto done; 751 } 752 ret_len = exsltCryptoHex2Bin (str, str_len, bin, bin_len); 753 754 /* decrypt the binary blob */ 755 ret = xmlMallocAtomic (ret_len); 756 if (ret == NULL) { 757 xsltTransformError(tctxt, NULL, tctxt->inst, 758 "exsltCryptoRc4EncryptFunction: Failed to allocate result\n"); 759 tctxt->state = XSLT_STATE_STOPPED; 760 xmlXPathReturnEmptyString (ctxt); 761 goto done; 762 } 763 PLATFORM_RC4_DECRYPT (ctxt, padkey, bin, ret_len, ret, ret_len); 764 765 xmlXPathReturnString (ctxt, ret); 766 767 done: 768 if (key != NULL) 769 xmlFree (key); 770 if (str != NULL) 771 xmlFree (str); 772 if (padkey != NULL) 773 xmlFree (padkey); 774 if (bin != NULL) 775 xmlFree (bin); 776 } 777 778 /** 779 * exsltCryptoRegister: 780 * 781 * Registers the EXSLT - Crypto module 782 */ 783 784 void 785 exsltCryptoRegister (void) { 786 xsltRegisterExtModuleFunction ((const xmlChar *) "md4", 787 EXSLT_CRYPTO_NAMESPACE, 788 exsltCryptoMd4Function); 789 xsltRegisterExtModuleFunction ((const xmlChar *) "md5", 790 EXSLT_CRYPTO_NAMESPACE, 791 exsltCryptoMd5Function); 792 xsltRegisterExtModuleFunction ((const xmlChar *) "sha1", 793 EXSLT_CRYPTO_NAMESPACE, 794 exsltCryptoSha1Function); 795 xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_encrypt", 796 EXSLT_CRYPTO_NAMESPACE, 797 exsltCryptoRc4EncryptFunction); 798 xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_decrypt", 799 EXSLT_CRYPTO_NAMESPACE, 800 exsltCryptoRc4DecryptFunction); 801 } 802 803 #else 804 /** 805 * exsltCryptoRegister: 806 * 807 * Registers the EXSLT - Crypto module 808 */ 809 void 810 exsltCryptoRegister (void) { 811 } 812 813 #endif /* defined(HAVE_CRYPTO) */ 814 815 #endif /* EXSLT_CRYPTO_ENABLED */ 816