/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 | 4.07k | #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 | 625 | unsigned char *hex, int hexlen) { |
49 | 625 | static const char bin2hex[] = { '0', '1', '2', '3', |
50 | 625 | '4', '5', '6', '7', |
51 | 625 | '8', '9', 'a', 'b', |
52 | 625 | 'c', 'd', 'e', 'f' |
53 | 625 | }; |
54 | | |
55 | 625 | unsigned char lo, hi; |
56 | 625 | int i, pos; |
57 | 13.5k | for (i = 0, pos = 0; (i < binlen && pos < hexlen); i++) { |
58 | 12.9k | lo = bin[i] & 0xf; |
59 | 12.9k | hi = bin[i] >> 4; |
60 | 12.9k | hex[pos++] = bin2hex[hi]; |
61 | 12.9k | hex[pos++] = bin2hex[lo]; |
62 | 12.9k | } |
63 | | |
64 | 625 | hex[pos] = '\0'; |
65 | 625 | } |
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 | 744 | unsigned char *bin, int binlen) { |
79 | 744 | int i = 0, j = 0; |
80 | 744 | unsigned char lo, hi, result, tmp; |
81 | | |
82 | 33.9k | while (i < hexlen && j < binlen) { |
83 | 33.2k | hi = lo = 0; |
84 | | |
85 | 33.2k | tmp = hex[i++]; |
86 | 33.2k | if (tmp >= '0' && tmp <= '9') |
87 | 3.66k | hi = tmp - '0'; |
88 | 29.5k | else if (tmp >= 'a' && tmp <= 'f') |
89 | 3.36k | hi = 10 + (tmp - 'a'); |
90 | | |
91 | 33.2k | tmp = hex[i++]; |
92 | 33.2k | if (tmp >= '0' && tmp <= '9') |
93 | 3.40k | lo = tmp - '0'; |
94 | 29.8k | else if (tmp >= 'a' && tmp <= 'f') |
95 | 3.32k | lo = 10 + (tmp - 'a'); |
96 | | |
97 | 33.2k | result = hi << 4; |
98 | 33.2k | result += lo; |
99 | 33.2k | bin[j++] = result; |
100 | 33.2k | } |
101 | | |
102 | 744 | return j; |
103 | 744 | } |
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 | 386 | #define PLATFORM_HASH exsltCryptoGcryptHash |
309 | 239 | #define PLATFORM_RC4_ENCRYPT exsltCryptoGcryptRc4Encrypt |
310 | 744 | #define PLATFORM_RC4_DECRYPT exsltCryptoGcryptRc4Decrypt |
311 | 176 | #define PLATFORM_MD4 GCRY_MD_MD4 |
312 | 94 | #define PLATFORM_MD5 GCRY_MD_MD5 |
313 | 116 | #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 | 1.36k | exsltCryptoGcryptInit (void) { |
326 | 1.36k | static int gcrypt_init; |
327 | 1.36k | xmlLockLibrary (); |
328 | | |
329 | 1.36k | 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 | 237 | gcry_check_version (GCRYPT_VERSION); |
338 | 237 | gcrypt_init = 1; |
339 | 237 | } |
340 | | |
341 | 1.36k | xmlUnlockLibrary (); |
342 | 1.36k | } |
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 | 386 | char dest[HASH_DIGEST_LENGTH]) { |
361 | 386 | exsltCryptoGcryptInit (); |
362 | 386 | gcry_md_hash_buffer (algorithm, dest, msg, msglen); |
363 | 386 | } |
364 | | |
365 | | static void |
366 | | exsltCryptoGcryptRc4Encrypt (xmlXPathParserContextPtr ctxt, |
367 | | const unsigned char *key, |
368 | | const unsigned char *msg, int msglen, |
369 | 239 | unsigned char *dest, int destlen) { |
370 | 239 | gcry_cipher_hd_t cipher; |
371 | 239 | gcry_error_t rc = 0; |
372 | | |
373 | 239 | exsltCryptoGcryptInit (); |
374 | | |
375 | 239 | rc = gcry_cipher_open (&cipher, GCRY_CIPHER_ARCFOUR, |
376 | 239 | GCRY_CIPHER_MODE_STREAM, 0); |
377 | 239 | 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 | 239 | rc = gcry_cipher_setkey (cipher, key, RC4_KEY_LENGTH); |
385 | 239 | 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 | 239 | rc = gcry_cipher_encrypt (cipher, (unsigned char *) dest, destlen, |
393 | 239 | (const unsigned char *) msg, msglen); |
394 | 239 | 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 | 239 | gcry_cipher_close (cipher); |
402 | 239 | } |
403 | | |
404 | | static void |
405 | | exsltCryptoGcryptRc4Decrypt (xmlXPathParserContextPtr ctxt, |
406 | | const unsigned char *key, |
407 | | const unsigned char *msg, int msglen, |
408 | 744 | unsigned char *dest, int destlen) { |
409 | 744 | gcry_cipher_hd_t cipher; |
410 | 744 | gcry_error_t rc = 0; |
411 | | |
412 | 744 | exsltCryptoGcryptInit (); |
413 | | |
414 | 744 | rc = gcry_cipher_open (&cipher, GCRY_CIPHER_ARCFOUR, |
415 | 744 | GCRY_CIPHER_MODE_STREAM, 0); |
416 | 744 | 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 | 744 | rc = gcry_cipher_setkey (cipher, key, RC4_KEY_LENGTH); |
424 | 744 | 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 | 744 | rc = gcry_cipher_decrypt (cipher, (unsigned char *) dest, destlen, |
432 | 744 | (const unsigned char *) msg, msglen); |
433 | 744 | 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 | 744 | gcry_cipher_close (cipher); |
441 | 744 | } |
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 | 745 | xmlChar ** str) { |
458 | | |
459 | 745 | int str_len = 0; |
460 | | |
461 | 745 | if ((nargs < 1) || (nargs > 2)) { |
462 | 57 | xmlXPathSetArityError (ctxt); |
463 | 57 | return 0; |
464 | 57 | } |
465 | | |
466 | 688 | *str = xmlXPathPopString (ctxt); |
467 | 688 | str_len = xmlStrlen (*str); |
468 | | |
469 | 688 | if (str_len == 0) { |
470 | 302 | xmlXPathReturnEmptyString (ctxt); |
471 | 302 | xmlFree (*str); |
472 | 302 | return 0; |
473 | 302 | } |
474 | | |
475 | 386 | return str_len; |
476 | 688 | } |
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 | 370 | exsltCryptoMd4Function (xmlXPathParserContextPtr ctxt, int nargs) { |
487 | | |
488 | 370 | int str_len = 0; |
489 | 370 | xmlChar *str = NULL, *ret = NULL; |
490 | 370 | unsigned char hash[HASH_DIGEST_LENGTH]; |
491 | 370 | unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1]; |
492 | | |
493 | 370 | str_len = exsltCryptoPopString (ctxt, nargs, &str); |
494 | 370 | if (str_len == 0) |
495 | 194 | return; |
496 | | |
497 | 176 | PLATFORM_HASH (ctxt, PLATFORM_MD4, (const char *) str, str_len, |
498 | 176 | (char *) hash); |
499 | 176 | exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); |
500 | | |
501 | 176 | ret = xmlStrdup ((xmlChar *) hex); |
502 | 176 | xmlXPathReturnString (ctxt, ret); |
503 | | |
504 | 176 | if (str != NULL) |
505 | 176 | xmlFree (str); |
506 | 176 | } |
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 | 177 | exsltCryptoMd5Function (xmlXPathParserContextPtr ctxt, int nargs) { |
517 | | |
518 | 177 | int str_len = 0; |
519 | 177 | xmlChar *str = NULL, *ret = NULL; |
520 | 177 | unsigned char hash[HASH_DIGEST_LENGTH]; |
521 | 177 | unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1]; |
522 | | |
523 | 177 | str_len = exsltCryptoPopString (ctxt, nargs, &str); |
524 | 177 | if (str_len == 0) |
525 | 83 | return; |
526 | | |
527 | 94 | PLATFORM_HASH (ctxt, PLATFORM_MD5, (const char *) str, str_len, |
528 | 94 | (char *) hash); |
529 | 94 | exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); |
530 | | |
531 | 94 | ret = xmlStrdup ((xmlChar *) hex); |
532 | 94 | xmlXPathReturnString (ctxt, ret); |
533 | | |
534 | 94 | if (str != NULL) |
535 | 94 | xmlFree (str); |
536 | 94 | } |
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 | 198 | exsltCryptoSha1Function (xmlXPathParserContextPtr ctxt, int nargs) { |
547 | | |
548 | 198 | int str_len = 0; |
549 | 198 | xmlChar *str = NULL, *ret = NULL; |
550 | 198 | unsigned char hash[HASH_DIGEST_LENGTH]; |
551 | 198 | unsigned char hex[SHA1_DIGEST_LENGTH * 2 + 1]; |
552 | | |
553 | 198 | str_len = exsltCryptoPopString (ctxt, nargs, &str); |
554 | 198 | if (str_len == 0) |
555 | 82 | return; |
556 | | |
557 | 116 | PLATFORM_HASH (ctxt, PLATFORM_SHA1, (const char *) str, str_len, |
558 | 116 | (char *) hash); |
559 | 116 | exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1); |
560 | | |
561 | 116 | ret = xmlStrdup ((xmlChar *) hex); |
562 | 116 | xmlXPathReturnString (ctxt, ret); |
563 | | |
564 | 116 | if (str != NULL) |
565 | 116 | xmlFree (str); |
566 | 116 | } |
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 | 336 | exsltCryptoRc4EncryptFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
577 | | |
578 | 336 | int key_len = 0; |
579 | 336 | int str_len = 0, bin_len = 0, hex_len = 0; |
580 | 336 | xmlChar *key = NULL, *str = NULL, *padkey = NULL; |
581 | 336 | xmlChar *bin = NULL, *hex = NULL; |
582 | 336 | xsltTransformContextPtr tctxt = NULL; |
583 | | |
584 | 336 | if (nargs != 2) { |
585 | 26 | xmlXPathSetArityError (ctxt); |
586 | 26 | return; |
587 | 26 | } |
588 | 310 | tctxt = xsltXPathGetTransformContext(ctxt); |
589 | | |
590 | 310 | str = xmlXPathPopString (ctxt); |
591 | 310 | str_len = xmlStrlen (str); |
592 | | |
593 | 310 | if (str_len == 0) { |
594 | 20 | xmlXPathReturnEmptyString (ctxt); |
595 | 20 | xmlFree (str); |
596 | 20 | return; |
597 | 20 | } |
598 | | |
599 | 290 | key = xmlXPathPopString (ctxt); |
600 | 290 | key_len = xmlStrlen (key); |
601 | | |
602 | 290 | if (key_len == 0) { |
603 | 33 | xmlXPathReturnEmptyString (ctxt); |
604 | 33 | xmlFree (key); |
605 | 33 | xmlFree (str); |
606 | 33 | return; |
607 | 33 | } |
608 | | |
609 | 257 | padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1); |
610 | 257 | 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 | 257 | memset(padkey, 0, RC4_KEY_LENGTH + 1); |
618 | | |
619 | 257 | if ((key_len > RC4_KEY_LENGTH) || (key_len < 0)) { |
620 | 18 | xsltTransformError(tctxt, NULL, tctxt->inst, |
621 | 18 | "exsltCryptoRc4EncryptFunction: key size too long or key broken\n"); |
622 | 18 | tctxt->state = XSLT_STATE_STOPPED; |
623 | 18 | xmlXPathReturnEmptyString (ctxt); |
624 | 18 | goto done; |
625 | 18 | } |
626 | 239 | memcpy (padkey, key, key_len); |
627 | | |
628 | | /* encrypt it */ |
629 | 239 | bin_len = str_len; |
630 | 239 | bin = xmlStrdup (str); |
631 | 239 | 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 | 239 | PLATFORM_RC4_ENCRYPT (ctxt, padkey, str, str_len, bin, bin_len); |
639 | | |
640 | | /* encode it */ |
641 | 239 | hex_len = str_len * 2 + 1; |
642 | 239 | hex = xmlMallocAtomic (hex_len); |
643 | 239 | 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 | 239 | exsltCryptoBin2Hex (bin, str_len, hex, hex_len); |
652 | 239 | xmlXPathReturnString (ctxt, hex); |
653 | | |
654 | 257 | done: |
655 | 257 | if (key != NULL) |
656 | 257 | xmlFree (key); |
657 | 257 | if (str != NULL) |
658 | 257 | xmlFree (str); |
659 | 257 | if (padkey != NULL) |
660 | 257 | xmlFree (padkey); |
661 | 257 | if (bin != NULL) |
662 | 239 | xmlFree (bin); |
663 | 257 | } |
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 | 1.01k | exsltCryptoRc4DecryptFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
674 | | |
675 | 1.01k | int key_len = 0; |
676 | 1.01k | int str_len = 0, bin_len = 0, ret_len = 0; |
677 | 1.01k | xmlChar *key = NULL, *str = NULL, *padkey = NULL, *bin = |
678 | 1.01k | NULL, *ret = NULL; |
679 | 1.01k | xsltTransformContextPtr tctxt = NULL; |
680 | | |
681 | 1.01k | if (nargs != 2) { |
682 | 95 | xmlXPathSetArityError (ctxt); |
683 | 95 | return; |
684 | 95 | } |
685 | 922 | tctxt = xsltXPathGetTransformContext(ctxt); |
686 | | |
687 | 922 | str = xmlXPathPopString (ctxt); |
688 | 922 | str_len = xmlStrlen (str); |
689 | | |
690 | 922 | if (str_len == 0) { |
691 | 20 | xmlXPathReturnEmptyString (ctxt); |
692 | 20 | xmlFree (str); |
693 | 20 | return; |
694 | 20 | } |
695 | | |
696 | 902 | key = xmlXPathPopString (ctxt); |
697 | 902 | key_len = xmlStrlen (key); |
698 | | |
699 | 902 | if (key_len == 0) { |
700 | 130 | xmlXPathReturnEmptyString (ctxt); |
701 | 130 | xmlFree (key); |
702 | 130 | xmlFree (str); |
703 | 130 | return; |
704 | 130 | } |
705 | | |
706 | 772 | padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1); |
707 | 772 | 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 | 772 | memset(padkey, 0, RC4_KEY_LENGTH + 1); |
715 | 772 | if ((key_len > RC4_KEY_LENGTH) || (key_len < 0)) { |
716 | 28 | xsltTransformError(tctxt, NULL, tctxt->inst, |
717 | 28 | "exsltCryptoRc4EncryptFunction: key size too long or key broken\n"); |
718 | 28 | tctxt->state = XSLT_STATE_STOPPED; |
719 | 28 | xmlXPathReturnEmptyString (ctxt); |
720 | 28 | goto done; |
721 | 28 | } |
722 | 744 | memcpy (padkey, key, key_len); |
723 | | |
724 | | /* decode hex to binary */ |
725 | 744 | bin_len = str_len; |
726 | 744 | bin = xmlMallocAtomic (bin_len); |
727 | 744 | 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 | 744 | ret_len = exsltCryptoHex2Bin (str, str_len, bin, bin_len); |
735 | | |
736 | | /* decrypt the binary blob */ |
737 | 744 | ret = xmlMallocAtomic (ret_len + 1); |
738 | 744 | 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 | 744 | PLATFORM_RC4_DECRYPT (ctxt, padkey, bin, ret_len, ret, ret_len); |
746 | 744 | ret[ret_len] = 0; |
747 | | |
748 | 744 | if (xmlCheckUTF8(ret) == 0) { |
749 | 611 | xsltTransformError(tctxt, NULL, tctxt->inst, |
750 | 611 | "exsltCryptoRc4DecryptFunction: Invalid UTF-8\n"); |
751 | 611 | xmlFree(ret); |
752 | 611 | xmlXPathReturnEmptyString(ctxt); |
753 | 611 | } else { |
754 | 133 | xmlXPathReturnString(ctxt, ret); |
755 | 133 | } |
756 | | |
757 | 772 | done: |
758 | 772 | if (key != NULL) |
759 | 772 | xmlFree (key); |
760 | 772 | if (str != NULL) |
761 | 772 | xmlFree (str); |
762 | 772 | if (padkey != NULL) |
763 | 772 | xmlFree (padkey); |
764 | 772 | if (bin != NULL) |
765 | 744 | xmlFree (bin); |
766 | 772 | } |
767 | | |
768 | | /** |
769 | | * exsltCryptoRegister: |
770 | | * |
771 | | * Registers the EXSLT - Crypto module |
772 | | */ |
773 | | |
774 | | void |
775 | 3.51k | exsltCryptoRegister (void) { |
776 | 3.51k | xsltRegisterExtModuleFunction ((const xmlChar *) "md4", |
777 | 3.51k | EXSLT_CRYPTO_NAMESPACE, |
778 | 3.51k | exsltCryptoMd4Function); |
779 | 3.51k | xsltRegisterExtModuleFunction ((const xmlChar *) "md5", |
780 | 3.51k | EXSLT_CRYPTO_NAMESPACE, |
781 | 3.51k | exsltCryptoMd5Function); |
782 | 3.51k | xsltRegisterExtModuleFunction ((const xmlChar *) "sha1", |
783 | 3.51k | EXSLT_CRYPTO_NAMESPACE, |
784 | 3.51k | exsltCryptoSha1Function); |
785 | 3.51k | xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_encrypt", |
786 | 3.51k | EXSLT_CRYPTO_NAMESPACE, |
787 | 3.51k | exsltCryptoRc4EncryptFunction); |
788 | 3.51k | xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_decrypt", |
789 | 3.51k | EXSLT_CRYPTO_NAMESPACE, |
790 | 3.51k | exsltCryptoRc4DecryptFunction); |
791 | 3.51k | } |
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 */ |