2 #include "libexslt/libexslt.h"
4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5 #include <win32config.h>
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>
17 #include <libxslt/xsltconfig.h>
18 #include <libxslt/xsltutils.h>
19 #include <libxslt/xsltInternals.h>
20 #include <libxslt/extensions.h>
24 #ifdef EXSLT_CRYPTO_ENABLED
26 #define HASH_DIGEST_LENGTH 32
27 #define MD5_DIGEST_LENGTH 16
28 #define SHA1_DIGEST_LENGTH 20
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
34 /* The following routines have been declared static - this should be
35 reviewed to consider whether we want to expose them to the API
40 exsltCryptoGcryptRc4Encrypt
41 exsltCryptoGcryptRC4Decrypt
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
51 * Helper function which encodes a binary blob as hex.
54 exsltCryptoBin2Hex (const unsigned char *bin
, int binlen
,
55 unsigned char *hex
, int hexlen
) {
56 static const char bin2hex
[] = { '0', '1', '2', '3',
64 for (i
= 0, pos
= 0; (i
< binlen
&& pos
< hexlen
); i
++) {
67 hex
[pos
++] = bin2hex
[hi
];
68 hex
[pos
++] = bin2hex
[lo
];
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
81 * Helper function which decodes a hex blob to binary
84 exsltCryptoHex2Bin (const unsigned char *hex
, int hexlen
,
85 unsigned char *bin
, int binlen
) {
87 unsigned char lo
, hi
, result
, tmp
;
89 while (i
< hexlen
&& j
< binlen
) {
93 if (tmp
>= '0' && tmp
<= '9')
95 else if (tmp
>= 'a' && tmp
<= 'f')
96 hi
= 10 + (tmp
- 'a');
99 if (tmp
>= '0' && tmp
<= '9')
101 else if (tmp
>= 'a' && tmp
<= 'f')
102 lo
= 10 + (tmp
- 'a');
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
123 #include <wincrypt.h>
124 #pragma comment(lib, "advapi32.lib")
127 exsltCryptoCryptoApiReportError (xmlXPathParserContextPtr ctxt
,
130 DWORD dw
= GetLastError ();
132 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
|
133 FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, dw
,
134 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
135 (LPTSTR
) & lpMsgBuf
, 0, NULL
);
137 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
, NULL
,
138 "exslt:crypto error (line %d). %s", line
,
140 LocalFree (lpMsgBuf
);
144 exsltCryptoCryptoApiCreateHash (xmlXPathParserContextPtr ctxt
,
145 HCRYPTPROV hCryptProv
, ALG_ID algorithm
,
146 const char *msg
, unsigned int msglen
,
147 char *dest
, unsigned int destlen
)
149 HCRYPTHASH hHash
= 0;
150 DWORD dwHashLen
= destlen
;
152 if (!CryptCreateHash (hCryptProv
, algorithm
, 0, 0, &hHash
)) {
153 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
157 if (!CryptHashData (hHash
, (const BYTE
*) msg
, msglen
, 0)) {
158 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
162 if (!CryptGetHashParam (hHash
, HP_HASHVAL
, dest
, &dwHashLen
, 0)) {
163 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
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
179 * Helper function which hashes a message using MD4, MD5, or SHA1.
180 * Uses Win32 CryptoAPI.
183 exsltCryptoCryptoApiHash (xmlXPathParserContextPtr ctxt
,
184 ALG_ID algorithm
, const char *msg
,
185 unsigned long msglen
,
186 char dest
[HASH_DIGEST_LENGTH
]) {
187 HCRYPTPROV hCryptProv
;
190 if (!CryptAcquireContext (&hCryptProv
, NULL
, NULL
, PROV_RSA_FULL
,
191 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
)) {
192 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
196 hHash
= exsltCryptoCryptoApiCreateHash (ctxt
, hCryptProv
,
197 algorithm
, msg
, msglen
,
198 dest
, HASH_DIGEST_LENGTH
);
200 CryptDestroyHash (hHash
);
203 CryptReleaseContext (hCryptProv
, 0);
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
;
215 unsigned char hash
[HASH_DIGEST_LENGTH
];
217 if (msglen
> destlen
) {
218 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
,
220 "exslt:crypto : internal error exsltCryptoCryptoApiRc4Encrypt dest buffer too small.\n");
224 if (!CryptAcquireContext (&hCryptProv
, NULL
, NULL
, PROV_RSA_FULL
,
225 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
)) {
226 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
230 hHash
= exsltCryptoCryptoApiCreateHash (ctxt
, hCryptProv
,
232 RC4_KEY_LENGTH
, hash
,
236 (hCryptProv
, CALG_RC4
, hHash
, 0x00800000, &hKey
)) {
237 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
240 /* Now encrypt data. */
242 memcpy (dest
, msg
, msglen
);
243 if (!CryptEncrypt (hKey
, 0, TRUE
, 0, dest
, &dwDataLen
, msglen
)) {
244 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
250 CryptDestroyHash (hHash
);
253 CryptDestroyKey (hKey
);
254 CryptReleaseContext (hCryptProv
, 0);
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
;
266 unsigned char hash
[HASH_DIGEST_LENGTH
];
268 if (msglen
> destlen
) {
269 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
,
271 "exslt:crypto : internal error exsltCryptoCryptoApiRc4Encrypt dest buffer too small.\n");
275 if (!CryptAcquireContext (&hCryptProv
, NULL
, NULL
, PROV_RSA_FULL
,
276 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
)) {
277 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
281 hHash
= exsltCryptoCryptoApiCreateHash (ctxt
, hCryptProv
,
283 RC4_KEY_LENGTH
, hash
,
287 (hCryptProv
, CALG_RC4
, hHash
, 0x00800000, &hKey
)) {
288 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
291 /* Now encrypt data. */
293 memcpy (dest
, msg
, msglen
);
294 if (!CryptDecrypt (hKey
, 0, TRUE
, 0, dest
, &dwDataLen
)) {
295 exsltCryptoCryptoApiReportError (ctxt
, __LINE__
);
301 CryptDestroyHash (hHash
);
304 CryptDestroyKey (hKey
);
305 CryptReleaseContext (hCryptProv
, 0);
308 #endif /* defined(WIN32) */
310 #if defined(HAVE_GCRYPT)
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
320 #ifdef HAVE_SYS_TYPES_H
321 # include <sys/types.h>
327 #ifdef HAVE_SYS_SELECT_H
328 #include <sys/select.h> /* needed by gcrypt.h 4 Jul 04 */
333 exsltCryptoGcryptInit (void) {
334 static int 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)
345 gcry_check_version (GCRYPT_VERSION
);
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
360 * Helper function which hashes a message using MD4, MD5, or SHA1.
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
);
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
;
381 exsltCryptoGcryptInit ();
383 rc
= gcry_cipher_open (&cipher
, GCRY_CIPHER_ARCFOUR
,
384 GCRY_CIPHER_MODE_STREAM
, 0);
386 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
,
388 "exslt:crypto internal error %s (gcry_cipher_open)\n",
392 rc
= gcry_cipher_setkey (cipher
, key
, RC4_KEY_LENGTH
);
394 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
,
396 "exslt:crypto internal error %s (gcry_cipher_setkey)\n",
400 rc
= gcry_cipher_encrypt (cipher
, (unsigned char *) dest
, destlen
,
401 (const unsigned char *) msg
, msglen
);
403 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
,
405 "exslt:crypto internal error %s (gcry_cipher_encrypt)\n",
409 gcry_cipher_close (cipher
);
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
;
420 exsltCryptoGcryptInit ();
422 rc
= gcry_cipher_open (&cipher
, GCRY_CIPHER_ARCFOUR
,
423 GCRY_CIPHER_MODE_STREAM
, 0);
425 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
,
427 "exslt:crypto internal error %s (gcry_cipher_open)\n",
431 rc
= gcry_cipher_setkey (cipher
, key
, RC4_KEY_LENGTH
);
433 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
,
435 "exslt:crypto internal error %s (gcry_cipher_setkey)\n",
439 rc
= gcry_cipher_decrypt (cipher
, (unsigned char *) dest
, destlen
,
440 (const unsigned char *) msg
, msglen
);
442 xsltTransformError (xsltXPathGetTransformContext (ctxt
), NULL
,
444 "exslt:crypto internal error %s (gcry_cipher_decrypt)\n",
448 gcry_cipher_close (cipher
);
451 #endif /* defined(HAVE_GCRYPT) */
453 #if defined(HAVE_CRYPTO)
456 * exsltCryptoPopString:
457 * @ctxt: an XPath parser context
458 * @nargs: the number of arguments
460 * Helper function which checks for and returns first string argument and its length
463 exsltCryptoPopString (xmlXPathParserContextPtr ctxt
, int nargs
,
468 if ((nargs
< 1) || (nargs
> 2)) {
469 xmlXPathSetArityError (ctxt
);
473 *str
= xmlXPathPopString (ctxt
);
474 str_len
= xmlUTF8Strlen (*str
);
477 xmlXPathReturnEmptyString (ctxt
);
486 * exsltCryptoMd4Function:
487 * @ctxt: an XPath parser context
488 * @nargs: the number of arguments
490 * computes the md4 hash of a string and returns as hex
493 exsltCryptoMd4Function (xmlXPathParserContextPtr ctxt
, int nargs
) {
496 xmlChar
*str
= NULL
, *ret
= NULL
;
497 unsigned char hash
[HASH_DIGEST_LENGTH
];
498 unsigned char hex
[MD5_DIGEST_LENGTH
* 2 + 1];
500 str_len
= exsltCryptoPopString (ctxt
, nargs
, &str
);
502 xmlXPathReturnEmptyString (ctxt
);
507 PLATFORM_HASH (ctxt
, PLATFORM_MD4
, (const char *) str
, str_len
,
509 exsltCryptoBin2Hex (hash
, sizeof (hash
) - 1, hex
, sizeof (hex
) - 1);
511 ret
= xmlStrdup ((xmlChar
*) hex
);
512 xmlXPathReturnString (ctxt
, ret
);
519 * exsltCryptoMd5Function:
520 * @ctxt: an XPath parser context
521 * @nargs: the number of arguments
523 * computes the md5 hash of a string and returns as hex
526 exsltCryptoMd5Function (xmlXPathParserContextPtr ctxt
, int nargs
) {
529 xmlChar
*str
= NULL
, *ret
= NULL
;
530 unsigned char hash
[HASH_DIGEST_LENGTH
];
531 unsigned char hex
[MD5_DIGEST_LENGTH
* 2 + 1];
533 str_len
= exsltCryptoPopString (ctxt
, nargs
, &str
);
535 xmlXPathReturnEmptyString (ctxt
);
540 PLATFORM_HASH (ctxt
, PLATFORM_MD5
, (const char *) str
, str_len
,
542 exsltCryptoBin2Hex (hash
, sizeof (hash
) - 1, hex
, sizeof (hex
) - 1);
544 ret
= xmlStrdup ((xmlChar
*) hex
);
545 xmlXPathReturnString (ctxt
, ret
);
552 * exsltCryptoSha1Function:
553 * @ctxt: an XPath parser context
554 * @nargs: the number of arguments
556 * computes the sha1 hash of a string and returns as hex
559 exsltCryptoSha1Function (xmlXPathParserContextPtr ctxt
, int nargs
) {
562 xmlChar
*str
= NULL
, *ret
= NULL
;
563 unsigned char hash
[HASH_DIGEST_LENGTH
];
564 unsigned char hex
[SHA1_DIGEST_LENGTH
* 2 + 1];
566 str_len
= exsltCryptoPopString (ctxt
, nargs
, &str
);
568 xmlXPathReturnEmptyString (ctxt
);
573 PLATFORM_HASH (ctxt
, PLATFORM_SHA1
, (const char *) str
, str_len
,
575 exsltCryptoBin2Hex (hash
, sizeof (hash
) - 1, hex
, sizeof (hex
) - 1);
577 ret
= xmlStrdup ((xmlChar
*) hex
);
578 xmlXPathReturnString (ctxt
, ret
);
585 * exsltCryptoRc4EncryptFunction:
586 * @ctxt: an XPath parser context
587 * @nargs: the number of arguments
589 * computes the sha1 hash of a string and returns as hex
592 exsltCryptoRc4EncryptFunction (xmlXPathParserContextPtr ctxt
, int nargs
) {
594 int key_len
= 0, key_size
= 0;
595 int str_len
= 0, bin_len
= 0, hex_len
= 0;
596 xmlChar
*key
= NULL
, *str
= NULL
, *padkey
= NULL
;
597 xmlChar
*bin
= NULL
, *hex
= NULL
;
598 xsltTransformContextPtr tctxt
= NULL
;
601 xmlXPathSetArityError (ctxt
);
604 tctxt
= xsltXPathGetTransformContext(ctxt
);
606 str
= xmlXPathPopString (ctxt
);
607 str_len
= xmlUTF8Strlen (str
);
610 xmlXPathReturnEmptyString (ctxt
);
615 key
= xmlXPathPopString (ctxt
);
616 key_len
= xmlUTF8Strlen (key
);
619 xmlXPathReturnEmptyString (ctxt
);
625 padkey
= xmlMallocAtomic (RC4_KEY_LENGTH
+ 1);
626 if (padkey
== NULL
) {
627 xsltTransformError(tctxt
, NULL
, tctxt
->inst
,
628 "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n");
629 tctxt
->state
= XSLT_STATE_STOPPED
;
630 xmlXPathReturnEmptyString (ctxt
);
633 memset(padkey
, 0, RC4_KEY_LENGTH
+ 1);
635 key_size
= xmlUTF8Strsize (key
, key_len
);
636 if ((key_size
> RC4_KEY_LENGTH
) || (key_size
< 0)) {
637 xsltTransformError(tctxt
, NULL
, tctxt
->inst
,
638 "exsltCryptoRc4EncryptFunction: key size too long or key broken\n");
639 tctxt
->state
= XSLT_STATE_STOPPED
;
640 xmlXPathReturnEmptyString (ctxt
);
643 memcpy (padkey
, key
, key_size
);
647 bin
= xmlStrdup (str
);
649 xsltTransformError(tctxt
, NULL
, tctxt
->inst
,
650 "exsltCryptoRc4EncryptFunction: Failed to allocate string\n");
651 tctxt
->state
= XSLT_STATE_STOPPED
;
652 xmlXPathReturnEmptyString (ctxt
);
655 PLATFORM_RC4_ENCRYPT (ctxt
, padkey
, str
, str_len
, bin
, bin_len
);
658 hex_len
= str_len
* 2 + 1;
659 hex
= xmlMallocAtomic (hex_len
);
661 xsltTransformError(tctxt
, NULL
, tctxt
->inst
,
662 "exsltCryptoRc4EncryptFunction: Failed to allocate result\n");
663 tctxt
->state
= XSLT_STATE_STOPPED
;
664 xmlXPathReturnEmptyString (ctxt
);
668 exsltCryptoBin2Hex (bin
, str_len
, hex
, hex_len
);
669 xmlXPathReturnString (ctxt
, hex
);
683 * exsltCryptoRc4DecryptFunction:
684 * @ctxt: an XPath parser context
685 * @nargs: the number of arguments
687 * computes the sha1 hash of a string and returns as hex
690 exsltCryptoRc4DecryptFunction (xmlXPathParserContextPtr ctxt
, int nargs
) {
692 int key_len
= 0, key_size
= 0;
693 int str_len
= 0, bin_len
= 0, ret_len
= 0;
694 xmlChar
*key
= NULL
, *str
= NULL
, *padkey
= NULL
, *bin
=
696 xsltTransformContextPtr tctxt
= NULL
;
699 xmlXPathSetArityError (ctxt
);
702 tctxt
= xsltXPathGetTransformContext(ctxt
);
704 str
= xmlXPathPopString (ctxt
);
705 str_len
= xmlUTF8Strlen (str
);
708 xmlXPathReturnEmptyString (ctxt
);
713 key
= xmlXPathPopString (ctxt
);
714 key_len
= xmlUTF8Strlen (key
);
717 xmlXPathReturnEmptyString (ctxt
);
723 padkey
= xmlMallocAtomic (RC4_KEY_LENGTH
+ 1);
724 if (padkey
== NULL
) {
725 xsltTransformError(tctxt
, NULL
, tctxt
->inst
,
726 "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n");
727 tctxt
->state
= XSLT_STATE_STOPPED
;
728 xmlXPathReturnEmptyString (ctxt
);
731 memset(padkey
, 0, RC4_KEY_LENGTH
+ 1);
732 key_size
= xmlUTF8Strsize (key
, key_len
);
733 if ((key_size
> RC4_KEY_LENGTH
) || (key_size
< 0)) {
734 xsltTransformError(tctxt
, NULL
, tctxt
->inst
,
735 "exsltCryptoRc4EncryptFunction: key size too long or key broken\n");
736 tctxt
->state
= XSLT_STATE_STOPPED
;
737 xmlXPathReturnEmptyString (ctxt
);
740 memcpy (padkey
, key
, key_size
);
742 /* decode hex to binary */
744 bin
= xmlMallocAtomic (bin_len
);
746 xsltTransformError(tctxt
, NULL
, tctxt
->inst
,
747 "exsltCryptoRc4EncryptFunction: Failed to allocate string\n");
748 tctxt
->state
= XSLT_STATE_STOPPED
;
749 xmlXPathReturnEmptyString (ctxt
);
752 ret_len
= exsltCryptoHex2Bin (str
, str_len
, bin
, bin_len
);
754 /* decrypt the binary blob */
755 ret
= xmlMallocAtomic (ret_len
+ 1);
757 xsltTransformError(tctxt
, NULL
, tctxt
->inst
,
758 "exsltCryptoRc4EncryptFunction: Failed to allocate result\n");
759 tctxt
->state
= XSLT_STATE_STOPPED
;
760 xmlXPathReturnEmptyString (ctxt
);
763 PLATFORM_RC4_DECRYPT (ctxt
, padkey
, bin
, ret_len
, ret
, ret_len
);
766 xmlXPathReturnString (ctxt
, ret
);
780 * exsltCryptoRegister:
782 * Registers the EXSLT - Crypto module
786 exsltCryptoRegister (void) {
787 xsltRegisterExtModuleFunction ((const xmlChar
*) "md4",
788 EXSLT_CRYPTO_NAMESPACE
,
789 exsltCryptoMd4Function
);
790 xsltRegisterExtModuleFunction ((const xmlChar
*) "md5",
791 EXSLT_CRYPTO_NAMESPACE
,
792 exsltCryptoMd5Function
);
793 xsltRegisterExtModuleFunction ((const xmlChar
*) "sha1",
794 EXSLT_CRYPTO_NAMESPACE
,
795 exsltCryptoSha1Function
);
796 xsltRegisterExtModuleFunction ((const xmlChar
*) "rc4_encrypt",
797 EXSLT_CRYPTO_NAMESPACE
,
798 exsltCryptoRc4EncryptFunction
);
799 xsltRegisterExtModuleFunction ((const xmlChar
*) "rc4_decrypt",
800 EXSLT_CRYPTO_NAMESPACE
,
801 exsltCryptoRc4DecryptFunction
);
806 * exsltCryptoRegister:
808 * Registers the EXSLT - Crypto module
811 exsltCryptoRegister (void) {
814 #endif /* defined(HAVE_CRYPTO) */
816 #endif /* EXSLT_CRYPTO_ENABLED */