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 |