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
exsltCryptoBin2Hex(const unsigned char * bin,int binlen,unsigned char * hex,int hexlen)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
exsltCryptoHex2Bin(const unsigned char * hex,int hexlen,unsigned char * bin,int binlen)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) && !defined(__CYGWIN__)
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 #ifdef _MSC_VER
125 #pragma comment(lib, "advapi32.lib")
126 #endif
127
128 static void
exsltCryptoCryptoApiReportError(xmlXPathParserContextPtr ctxt,int line)129 exsltCryptoCryptoApiReportError (xmlXPathParserContextPtr ctxt,
130 int line) {
131 char *lpMsgBuf;
132 DWORD dw = GetLastError ();
133
134 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
135 FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw,
136 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
137 (LPTSTR) & lpMsgBuf, 0, NULL);
138
139 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL, NULL,
140 "exslt:crypto error (line %d). %s", line,
141 lpMsgBuf);
142 LocalFree (lpMsgBuf);
143 }
144
145 static HCRYPTHASH
exsltCryptoCryptoApiCreateHash(xmlXPathParserContextPtr ctxt,HCRYPTPROV hCryptProv,ALG_ID algorithm,const unsigned char * msg,unsigned int msglen,char * dest,unsigned int destlen)146 exsltCryptoCryptoApiCreateHash (xmlXPathParserContextPtr ctxt,
147 HCRYPTPROV hCryptProv, ALG_ID algorithm,
148 const unsigned char *msg, unsigned int msglen,
149 char *dest, unsigned int destlen)
150 {
151 HCRYPTHASH hHash = 0;
152 DWORD dwHashLen = destlen;
153
154 if (!CryptCreateHash (hCryptProv, algorithm, 0, 0, &hHash)) {
155 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
156 return 0;
157 }
158
159 if (!CryptHashData (hHash, msg, msglen, 0)) {
160 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
161 goto fail;
162 }
163
164 if (!CryptGetHashParam (hHash, HP_HASHVAL, (BYTE *) dest, &dwHashLen, 0)) {
165 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
166 goto fail;
167 }
168
169 fail:
170 return hHash;
171 }
172
173 /**
174 * exsltCryptoCryptoApiHash:
175 * @ctxt: an XPath parser context
176 * @algorithm: hashing algorithm to use
177 * @msg: text to be hashed
178 * @msglen: length of text to be hashed
179 * @dest: buffer to place hash result
180 *
181 * Helper function which hashes a message using MD4, MD5, or SHA1.
182 * Uses Win32 CryptoAPI.
183 */
184 static void
exsltCryptoCryptoApiHash(xmlXPathParserContextPtr ctxt,ALG_ID algorithm,const char * msg,unsigned long msglen,char dest[HASH_DIGEST_LENGTH])185 exsltCryptoCryptoApiHash (xmlXPathParserContextPtr ctxt,
186 ALG_ID algorithm, const char *msg,
187 unsigned long msglen,
188 char dest[HASH_DIGEST_LENGTH]) {
189 HCRYPTPROV hCryptProv;
190 HCRYPTHASH hHash;
191
192 if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL,
193 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
194 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
195 return;
196 }
197
198 hHash = exsltCryptoCryptoApiCreateHash (ctxt, hCryptProv,
199 algorithm, (unsigned char *) msg,
200 msglen, dest, HASH_DIGEST_LENGTH);
201 if (0 != hHash) {
202 CryptDestroyHash (hHash);
203 }
204
205 CryptReleaseContext (hCryptProv, 0);
206 }
207
208 static void
exsltCryptoCryptoApiRc4Encrypt(xmlXPathParserContextPtr ctxt,const unsigned char * key,const unsigned char * msg,int msglen,unsigned char * dest,int destlen)209 exsltCryptoCryptoApiRc4Encrypt (xmlXPathParserContextPtr ctxt,
210 const unsigned char *key,
211 const unsigned char *msg, int msglen,
212 unsigned char *dest, int destlen) {
213 HCRYPTPROV hCryptProv;
214 HCRYPTKEY hKey;
215 HCRYPTHASH hHash;
216 DWORD dwDataLen;
217 char hash[HASH_DIGEST_LENGTH];
218
219 if (msglen > destlen) {
220 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL,
221 NULL,
222 "exslt:crypto : internal error exsltCryptoCryptoApiRc4Encrypt dest buffer too small.\n");
223 return;
224 }
225
226 if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL,
227 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
228 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
229 return;
230 }
231
232 hHash = exsltCryptoCryptoApiCreateHash (ctxt, hCryptProv,
233 CALG_SHA1, key,
234 RC4_KEY_LENGTH, hash,
235 HASH_DIGEST_LENGTH);
236
237 if (!CryptDeriveKey
238 (hCryptProv, CALG_RC4, hHash, 0x00800000, &hKey)) {
239 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
240 goto fail;
241 }
242 /* Now encrypt data. */
243 dwDataLen = msglen;
244 memcpy (dest, msg, msglen);
245 if (!CryptEncrypt (hKey, 0, TRUE, 0, dest, &dwDataLen, msglen)) {
246 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
247 goto fail;
248 }
249
250 fail:
251 if (0 != hHash) {
252 CryptDestroyHash (hHash);
253 }
254
255 CryptDestroyKey (hKey);
256 CryptReleaseContext (hCryptProv, 0);
257 }
258
259 static void
exsltCryptoCryptoApiRc4Decrypt(xmlXPathParserContextPtr ctxt,const unsigned char * key,const unsigned char * msg,int msglen,unsigned char * dest,int destlen)260 exsltCryptoCryptoApiRc4Decrypt (xmlXPathParserContextPtr ctxt,
261 const unsigned char *key,
262 const unsigned char *msg, int msglen,
263 unsigned char *dest, int destlen) {
264 HCRYPTPROV hCryptProv;
265 HCRYPTKEY hKey;
266 HCRYPTHASH hHash;
267 DWORD dwDataLen;
268 char hash[HASH_DIGEST_LENGTH];
269
270 if (msglen > destlen) {
271 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL,
272 NULL,
273 "exslt:crypto : internal error exsltCryptoCryptoApiRc4Encrypt dest buffer too small.\n");
274 return;
275 }
276
277 if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL,
278 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
279 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
280 return;
281 }
282
283 hHash = exsltCryptoCryptoApiCreateHash (ctxt, hCryptProv,
284 CALG_SHA1, key,
285 RC4_KEY_LENGTH, hash,
286 HASH_DIGEST_LENGTH);
287
288 if (!CryptDeriveKey
289 (hCryptProv, CALG_RC4, hHash, 0x00800000, &hKey)) {
290 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
291 goto fail;
292 }
293 /* Now encrypt data. */
294 dwDataLen = msglen;
295 memcpy (dest, msg, msglen);
296 if (!CryptDecrypt (hKey, 0, TRUE, 0, dest, &dwDataLen)) {
297 exsltCryptoCryptoApiReportError (ctxt, __LINE__);
298 goto fail;
299 }
300
301 fail:
302 if (0 != hHash) {
303 CryptDestroyHash (hHash);
304 }
305
306 CryptDestroyKey (hKey);
307 CryptReleaseContext (hCryptProv, 0);
308 }
309
310 #endif /* defined(_WIN32) */
311
312 #if defined(HAVE_GCRYPT)
313
314 #define HAVE_CRYPTO
315 #define PLATFORM_HASH exsltCryptoGcryptHash
316 #define PLATFORM_RC4_ENCRYPT exsltCryptoGcryptRc4Encrypt
317 #define PLATFORM_RC4_DECRYPT exsltCryptoGcryptRc4Decrypt
318 #define PLATFORM_MD4 GCRY_MD_MD4
319 #define PLATFORM_MD5 GCRY_MD_MD5
320 #define PLATFORM_SHA1 GCRY_MD_SHA1
321
322 #ifdef HAVE_SYS_TYPES_H
323 # include <sys/types.h>
324 #endif
325 #ifdef HAVE_STDINT_H
326 # include <stdint.h>
327 #endif
328
329 #ifdef HAVE_SYS_SELECT_H
330 #include <sys/select.h> /* needed by gcrypt.h 4 Jul 04 */
331 #endif
332 #include <gcrypt.h>
333
334 static void
exsltCryptoGcryptInit(void)335 exsltCryptoGcryptInit (void) {
336 static int gcrypt_init;
337 xmlLockLibrary ();
338
339 if (!gcrypt_init) {
340 /* The function `gcry_check_version' must be called before any other
341 function in the library, because it initializes the thread support
342 subsystem in Libgcrypt. To achieve this in all generality, it is
343 necessary to synchronize the call to this function with all other calls
344 to functions in the library, using the synchronization mechanisms
345 available in your thread library. (from gcrypt.info)
346 */
347 gcry_check_version (GCRYPT_VERSION);
348 gcrypt_init = 1;
349 }
350
351 xmlUnlockLibrary ();
352 }
353
354 /**
355 * exsltCryptoGcryptHash:
356 * @ctxt: an XPath parser context
357 * @algorithm: hashing algorithm to use
358 * @msg: text to be hashed
359 * @msglen: length of text to be hashed
360 * @dest: buffer to place hash result
361 *
362 * Helper function which hashes a message using MD4, MD5, or SHA1.
363 * using gcrypt
364 */
365 static void
exsltCryptoGcryptHash(xmlXPathParserContextPtr ctxt ATTRIBUTE_UNUSED,int algorithm,const char * msg,unsigned long msglen,char dest[HASH_DIGEST_LENGTH])366 exsltCryptoGcryptHash (xmlXPathParserContextPtr ctxt ATTRIBUTE_UNUSED,
367 /* changed the enum to int */
368 int algorithm, const char *msg,
369 unsigned long msglen,
370 char dest[HASH_DIGEST_LENGTH]) {
371 exsltCryptoGcryptInit ();
372 gcry_md_hash_buffer (algorithm, dest, msg, msglen);
373 }
374
375 static void
exsltCryptoGcryptRc4Encrypt(xmlXPathParserContextPtr ctxt,const unsigned char * key,const unsigned char * msg,int msglen,unsigned char * dest,int destlen)376 exsltCryptoGcryptRc4Encrypt (xmlXPathParserContextPtr ctxt,
377 const unsigned char *key,
378 const unsigned char *msg, int msglen,
379 unsigned char *dest, int destlen) {
380 gcry_cipher_hd_t cipher;
381 gcry_error_t rc = 0;
382
383 exsltCryptoGcryptInit ();
384
385 rc = gcry_cipher_open (&cipher, GCRY_CIPHER_ARCFOUR,
386 GCRY_CIPHER_MODE_STREAM, 0);
387 if (rc) {
388 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL,
389 NULL,
390 "exslt:crypto internal error %s (gcry_cipher_open)\n",
391 gcry_strerror (rc));
392 }
393
394 rc = gcry_cipher_setkey (cipher, key, RC4_KEY_LENGTH);
395 if (rc) {
396 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL,
397 NULL,
398 "exslt:crypto internal error %s (gcry_cipher_setkey)\n",
399 gcry_strerror (rc));
400 }
401
402 rc = gcry_cipher_encrypt (cipher, (unsigned char *) dest, destlen,
403 (const unsigned char *) msg, msglen);
404 if (rc) {
405 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL,
406 NULL,
407 "exslt:crypto internal error %s (gcry_cipher_encrypt)\n",
408 gcry_strerror (rc));
409 }
410
411 gcry_cipher_close (cipher);
412 }
413
414 static void
exsltCryptoGcryptRc4Decrypt(xmlXPathParserContextPtr ctxt,const unsigned char * key,const unsigned char * msg,int msglen,unsigned char * dest,int destlen)415 exsltCryptoGcryptRc4Decrypt (xmlXPathParserContextPtr ctxt,
416 const unsigned char *key,
417 const unsigned char *msg, int msglen,
418 unsigned char *dest, int destlen) {
419 gcry_cipher_hd_t cipher;
420 gcry_error_t rc = 0;
421
422 exsltCryptoGcryptInit ();
423
424 rc = gcry_cipher_open (&cipher, GCRY_CIPHER_ARCFOUR,
425 GCRY_CIPHER_MODE_STREAM, 0);
426 if (rc) {
427 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL,
428 NULL,
429 "exslt:crypto internal error %s (gcry_cipher_open)\n",
430 gcry_strerror (rc));
431 }
432
433 rc = gcry_cipher_setkey (cipher, key, RC4_KEY_LENGTH);
434 if (rc) {
435 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL,
436 NULL,
437 "exslt:crypto internal error %s (gcry_cipher_setkey)\n",
438 gcry_strerror (rc));
439 }
440
441 rc = gcry_cipher_decrypt (cipher, (unsigned char *) dest, destlen,
442 (const unsigned char *) msg, msglen);
443 if (rc) {
444 xsltTransformError (xsltXPathGetTransformContext (ctxt), NULL,
445 NULL,
446 "exslt:crypto internal error %s (gcry_cipher_decrypt)\n",
447 gcry_strerror (rc));
448 }
449
450 gcry_cipher_close (cipher);
451 }
452
453 #endif /* defined(HAVE_GCRYPT) */
454
455 #if defined(HAVE_CRYPTO)
456
457 /**
458 * exsltCryptoPopString:
459 * @ctxt: an XPath parser context
460 * @nargs: the number of arguments
461 *
462 * Helper function which checks for and returns first string argument and its
463 * length in bytes.
464 */
465 static int
exsltCryptoPopString(xmlXPathParserContextPtr ctxt,int nargs,xmlChar ** str)466 exsltCryptoPopString (xmlXPathParserContextPtr ctxt, int nargs,
467 xmlChar ** str) {
468
469 int str_len = 0;
470
471 if ((nargs < 1) || (nargs > 2)) {
472 xmlXPathSetArityError (ctxt);
473 return 0;
474 }
475
476 *str = xmlXPathPopString (ctxt);
477 str_len = xmlStrlen (*str);
478
479 if (str_len == 0) {
480 xmlXPathReturnEmptyString (ctxt);
481 xmlFree (*str);
482 return 0;
483 }
484
485 return str_len;
486 }
487
488 /**
489 * exsltCryptoMd4Function:
490 * @ctxt: an XPath parser context
491 * @nargs: the number of arguments
492 *
493 * computes the md4 hash of a string and returns as hex
494 */
495 static void
exsltCryptoMd4Function(xmlXPathParserContextPtr ctxt,int nargs)496 exsltCryptoMd4Function (xmlXPathParserContextPtr ctxt, int nargs) {
497
498 int str_len = 0;
499 xmlChar *str = NULL, *ret = NULL;
500 unsigned char hash[HASH_DIGEST_LENGTH];
501 unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1];
502
503 str_len = exsltCryptoPopString (ctxt, nargs, &str);
504 if (str_len == 0)
505 return;
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
exsltCryptoMd5Function(xmlXPathParserContextPtr ctxt,int nargs)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 return;
536
537 PLATFORM_HASH (ctxt, PLATFORM_MD5, (const char *) str, str_len,
538 (char *) hash);
539 exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1);
540
541 ret = xmlStrdup ((xmlChar *) hex);
542 xmlXPathReturnString (ctxt, ret);
543
544 if (str != NULL)
545 xmlFree (str);
546 }
547
548 /**
549 * exsltCryptoSha1Function:
550 * @ctxt: an XPath parser context
551 * @nargs: the number of arguments
552 *
553 * computes the sha1 hash of a string and returns as hex
554 */
555 static void
exsltCryptoSha1Function(xmlXPathParserContextPtr ctxt,int nargs)556 exsltCryptoSha1Function (xmlXPathParserContextPtr ctxt, int nargs) {
557
558 int str_len = 0;
559 xmlChar *str = NULL, *ret = NULL;
560 unsigned char hash[HASH_DIGEST_LENGTH];
561 unsigned char hex[SHA1_DIGEST_LENGTH * 2 + 1];
562
563 str_len = exsltCryptoPopString (ctxt, nargs, &str);
564 if (str_len == 0)
565 return;
566
567 PLATFORM_HASH (ctxt, PLATFORM_SHA1, (const char *) str, str_len,
568 (char *) hash);
569 exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1);
570
571 ret = xmlStrdup ((xmlChar *) hex);
572 xmlXPathReturnString (ctxt, ret);
573
574 if (str != NULL)
575 xmlFree (str);
576 }
577
578 /**
579 * exsltCryptoRc4EncryptFunction:
580 * @ctxt: an XPath parser context
581 * @nargs: the number of arguments
582 *
583 * computes the sha1 hash of a string and returns as hex
584 */
585 static void
exsltCryptoRc4EncryptFunction(xmlXPathParserContextPtr ctxt,int nargs)586 exsltCryptoRc4EncryptFunction (xmlXPathParserContextPtr ctxt, int nargs) {
587
588 int key_len = 0;
589 int str_len = 0, bin_len = 0, hex_len = 0;
590 xmlChar *key = NULL, *str = NULL, *padkey = NULL;
591 xmlChar *bin = NULL, *hex = NULL;
592 xsltTransformContextPtr tctxt = NULL;
593
594 if (nargs != 2) {
595 xmlXPathSetArityError (ctxt);
596 return;
597 }
598 tctxt = xsltXPathGetTransformContext(ctxt);
599
600 str = xmlXPathPopString (ctxt);
601 str_len = xmlStrlen (str);
602
603 if (str_len == 0) {
604 xmlXPathReturnEmptyString (ctxt);
605 xmlFree (str);
606 return;
607 }
608
609 key = xmlXPathPopString (ctxt);
610 key_len = xmlStrlen (key);
611
612 if (key_len == 0) {
613 xmlXPathReturnEmptyString (ctxt);
614 xmlFree (key);
615 xmlFree (str);
616 return;
617 }
618
619 padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1);
620 if (padkey == NULL) {
621 xsltTransformError(tctxt, NULL, tctxt->inst,
622 "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n");
623 tctxt->state = XSLT_STATE_STOPPED;
624 xmlXPathReturnEmptyString (ctxt);
625 goto done;
626 }
627 memset(padkey, 0, RC4_KEY_LENGTH + 1);
628
629 if ((key_len > RC4_KEY_LENGTH) || (key_len < 0)) {
630 xsltTransformError(tctxt, NULL, tctxt->inst,
631 "exsltCryptoRc4EncryptFunction: key size too long or key broken\n");
632 tctxt->state = XSLT_STATE_STOPPED;
633 xmlXPathReturnEmptyString (ctxt);
634 goto done;
635 }
636 memcpy (padkey, key, key_len);
637
638 /* encrypt it */
639 bin_len = str_len;
640 bin = xmlStrdup (str);
641 if (bin == NULL) {
642 xsltTransformError(tctxt, NULL, tctxt->inst,
643 "exsltCryptoRc4EncryptFunction: Failed to allocate string\n");
644 tctxt->state = XSLT_STATE_STOPPED;
645 xmlXPathReturnEmptyString (ctxt);
646 goto done;
647 }
648 PLATFORM_RC4_ENCRYPT (ctxt, padkey, str, str_len, bin, bin_len);
649
650 /* encode it */
651 hex_len = str_len * 2 + 1;
652 hex = xmlMallocAtomic (hex_len);
653 if (hex == NULL) {
654 xsltTransformError(tctxt, NULL, tctxt->inst,
655 "exsltCryptoRc4EncryptFunction: Failed to allocate result\n");
656 tctxt->state = XSLT_STATE_STOPPED;
657 xmlXPathReturnEmptyString (ctxt);
658 goto done;
659 }
660
661 exsltCryptoBin2Hex (bin, str_len, hex, hex_len);
662 xmlXPathReturnString (ctxt, hex);
663
664 done:
665 if (key != NULL)
666 xmlFree (key);
667 if (str != NULL)
668 xmlFree (str);
669 if (padkey != NULL)
670 xmlFree (padkey);
671 if (bin != NULL)
672 xmlFree (bin);
673 }
674
675 /**
676 * exsltCryptoRc4DecryptFunction:
677 * @ctxt: an XPath parser context
678 * @nargs: the number of arguments
679 *
680 * computes the sha1 hash of a string and returns as hex
681 */
682 static void
exsltCryptoRc4DecryptFunction(xmlXPathParserContextPtr ctxt,int nargs)683 exsltCryptoRc4DecryptFunction (xmlXPathParserContextPtr ctxt, int nargs) {
684
685 int key_len = 0;
686 int str_len = 0, bin_len = 0, ret_len = 0;
687 xmlChar *key = NULL, *str = NULL, *padkey = NULL, *bin =
688 NULL, *ret = NULL;
689 xsltTransformContextPtr tctxt = NULL;
690
691 if (nargs != 2) {
692 xmlXPathSetArityError (ctxt);
693 return;
694 }
695 tctxt = xsltXPathGetTransformContext(ctxt);
696
697 str = xmlXPathPopString (ctxt);
698 str_len = xmlStrlen (str);
699
700 if (str_len == 0) {
701 xmlXPathReturnEmptyString (ctxt);
702 xmlFree (str);
703 return;
704 }
705
706 key = xmlXPathPopString (ctxt);
707 key_len = xmlStrlen (key);
708
709 if (key_len == 0) {
710 xmlXPathReturnEmptyString (ctxt);
711 xmlFree (key);
712 xmlFree (str);
713 return;
714 }
715
716 padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1);
717 if (padkey == NULL) {
718 xsltTransformError(tctxt, NULL, tctxt->inst,
719 "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n");
720 tctxt->state = XSLT_STATE_STOPPED;
721 xmlXPathReturnEmptyString (ctxt);
722 goto done;
723 }
724 memset(padkey, 0, RC4_KEY_LENGTH + 1);
725 if ((key_len > RC4_KEY_LENGTH) || (key_len < 0)) {
726 xsltTransformError(tctxt, NULL, tctxt->inst,
727 "exsltCryptoRc4EncryptFunction: key size too long or key broken\n");
728 tctxt->state = XSLT_STATE_STOPPED;
729 xmlXPathReturnEmptyString (ctxt);
730 goto done;
731 }
732 memcpy (padkey, key, key_len);
733
734 /* decode hex to binary */
735 bin_len = str_len;
736 bin = xmlMallocAtomic (bin_len);
737 if (bin == NULL) {
738 xsltTransformError(tctxt, NULL, tctxt->inst,
739 "exsltCryptoRc4EncryptFunction: Failed to allocate string\n");
740 tctxt->state = XSLT_STATE_STOPPED;
741 xmlXPathReturnEmptyString (ctxt);
742 goto done;
743 }
744 ret_len = exsltCryptoHex2Bin (str, str_len, bin, bin_len);
745
746 /* decrypt the binary blob */
747 ret = xmlMallocAtomic (ret_len + 1);
748 if (ret == NULL) {
749 xsltTransformError(tctxt, NULL, tctxt->inst,
750 "exsltCryptoRc4EncryptFunction: Failed to allocate result\n");
751 tctxt->state = XSLT_STATE_STOPPED;
752 xmlXPathReturnEmptyString (ctxt);
753 goto done;
754 }
755 PLATFORM_RC4_DECRYPT (ctxt, padkey, bin, ret_len, ret, ret_len);
756 ret[ret_len] = 0;
757
758 if (xmlCheckUTF8(ret) == 0) {
759 xsltTransformError(tctxt, NULL, tctxt->inst,
760 "exsltCryptoRc4DecryptFunction: Invalid UTF-8\n");
761 xmlFree(ret);
762 xmlXPathReturnEmptyString(ctxt);
763 } else {
764 xmlXPathReturnString(ctxt, ret);
765 }
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
exsltCryptoRegister(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
exsltCryptoRegister(void)810 exsltCryptoRegister (void) {
811 }
812
813 #endif /* defined(HAVE_CRYPTO) */
814
815 #endif /* EXSLT_CRYPTO_ENABLED */
816