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