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