Coverage Report

Created: 2026-10-28 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxslt/libexslt/crypto.c
Line
Count
Source
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
9.43k
#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
5.14k
        unsigned char *hex, int hexlen) {
50
5.14k
    static const char bin2hex[] = { '0', '1', '2', '3',
51
5.14k
  '4', '5', '6', '7',
52
5.14k
  '8', '9', 'a', 'b',
53
5.14k
  'c', 'd', 'e', 'f'
54
5.14k
    };
55
56
5.14k
    unsigned char lo, hi;
57
5.14k
    int i, pos;
58
11.3M
    for (i = 0, pos = 0; (i < binlen && pos < hexlen); i++) {
59
11.3M
  lo = bin[i] & 0xf;
60
11.3M
  hi = bin[i] >> 4;
61
11.3M
  hex[pos++] = bin2hex[hi];
62
11.3M
  hex[pos++] = bin2hex[lo];
63
11.3M
    }
64
65
5.14k
    hex[pos] = '\0';
66
5.14k
}
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
2.28k
        unsigned char *bin, int binlen) {
80
2.28k
    int i = 0, j = 0;
81
2.28k
    unsigned char lo, hi, result, tmp;
82
83
17.9M
    while (i < hexlen && j < binlen) {
84
17.9M
  hi = lo = 0;
85
86
17.9M
  tmp = hex[i++];
87
17.9M
  if (tmp >= '0' && tmp <= '9')
88
7.03M
      hi = tmp - '0';
89
10.9M
  else if (tmp >= 'a' && tmp <= 'f')
90
4.21M
      hi = 10 + (tmp - 'a');
91
92
17.9M
  tmp = hex[i++];
93
17.9M
  if (tmp >= '0' && tmp <= '9')
94
7.02M
      lo = tmp - '0';
95
10.9M
  else if (tmp >= 'a' && tmp <= 'f')
96
4.21M
      lo = 10 + (tmp - 'a');
97
98
17.9M
  result = hi << 4;
99
17.9M
  result += lo;
100
17.9M
  bin[j++] = result;
101
17.9M
    }
102
103
2.28k
    return j;
104
2.28k
}
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
5.08k
#define PLATFORM_HASH exsltCryptoGcryptHash
310
66
#define PLATFORM_RC4_ENCRYPT exsltCryptoGcryptRc4Encrypt
311
2.28k
#define PLATFORM_RC4_DECRYPT exsltCryptoGcryptRc4Decrypt
312
766
#define PLATFORM_MD4 GCRY_MD_MD4
313
950
#define PLATFORM_MD5 GCRY_MD_MD5
314
3.36k
#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
7.43k
exsltCryptoGcryptInit (void) {
327
7.43k
    static int gcrypt_init;
328
7.43k
    xmlLockLibrary ();
329
330
7.43k
    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
2
  gcry_check_version (GCRYPT_VERSION);
339
2
  gcrypt_init = 1;
340
2
    }
341
342
7.43k
    xmlUnlockLibrary ();
343
7.43k
}
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
5.08k
           char dest[HASH_DIGEST_LENGTH]) {
362
5.08k
    exsltCryptoGcryptInit ();
363
5.08k
    gcry_md_hash_buffer (algorithm, dest, msg, msglen);
364
5.08k
}
365
366
static void
367
exsltCryptoGcryptRc4Encrypt (xmlXPathParserContextPtr ctxt,
368
           const unsigned char *key,
369
           const unsigned char *msg, int msglen,
370
66
           unsigned char *dest, int destlen) {
371
66
    gcry_cipher_hd_t cipher;
372
66
    gcry_error_t rc = 0;
373
374
66
    exsltCryptoGcryptInit ();
375
376
66
    rc = gcry_cipher_open (&cipher, GCRY_CIPHER_ARCFOUR,
377
66
         GCRY_CIPHER_MODE_STREAM, 0);
378
66
    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
66
    rc = gcry_cipher_setkey (cipher, key, RC4_KEY_LENGTH);
386
66
    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
66
    rc = gcry_cipher_encrypt (cipher, (unsigned char *) dest, destlen,
394
66
            (const unsigned char *) msg, msglen);
395
66
    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
66
    gcry_cipher_close (cipher);
403
66
}
404
405
static void
406
exsltCryptoGcryptRc4Decrypt (xmlXPathParserContextPtr ctxt,
407
           const unsigned char *key,
408
           const unsigned char *msg, int msglen,
409
2.28k
           unsigned char *dest, int destlen) {
410
2.28k
    gcry_cipher_hd_t cipher;
411
2.28k
    gcry_error_t rc = 0;
412
413
2.28k
    exsltCryptoGcryptInit ();
414
415
2.28k
    rc = gcry_cipher_open (&cipher, GCRY_CIPHER_ARCFOUR,
416
2.28k
         GCRY_CIPHER_MODE_STREAM, 0);
417
2.28k
    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
2.28k
    rc = gcry_cipher_setkey (cipher, key, RC4_KEY_LENGTH);
425
2.28k
    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
2.28k
    rc = gcry_cipher_decrypt (cipher, (unsigned char *) dest, destlen,
433
2.28k
            (const unsigned char *) msg, msglen);
434
2.28k
    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
2.28k
    gcry_cipher_close (cipher);
442
2.28k
}
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
20.4k
          xmlChar ** str) {
459
460
20.4k
    int str_len = 0;
461
462
20.4k
    if ((nargs < 1) || (nargs > 2)) {
463
3
  xmlXPathSetArityError (ctxt);
464
3
  return 0;
465
3
    }
466
467
20.4k
    *str = xmlXPathPopString (ctxt);
468
20.4k
    str_len = xmlStrlen (*str);
469
470
20.4k
    if (str_len == 0) {
471
15.3k
  xmlXPathReturnEmptyString (ctxt);
472
15.3k
  xmlFree (*str);
473
15.3k
  return 0;
474
15.3k
    }
475
476
5.08k
    return str_len;
477
20.4k
}
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
1.04k
exsltCryptoMd4Function (xmlXPathParserContextPtr ctxt, int nargs) {
488
489
1.04k
    int str_len = 0;
490
1.04k
    xmlChar *str = NULL, *ret = NULL;
491
1.04k
    unsigned char hash[HASH_DIGEST_LENGTH];
492
1.04k
    unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1];
493
494
1.04k
    str_len = exsltCryptoPopString (ctxt, nargs, &str);
495
1.04k
    if (str_len == 0)
496
282
  return;
497
498
766
    PLATFORM_HASH (ctxt, PLATFORM_MD4, (const char *) str, str_len,
499
766
       (char *) hash);
500
766
    exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1);
501
502
766
    ret = xmlStrdup ((xmlChar *) hex);
503
766
    xmlXPathReturnString (ctxt, ret);
504
505
766
    if (str != NULL)
506
766
  xmlFree (str);
507
766
}
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
1.32k
exsltCryptoMd5Function (xmlXPathParserContextPtr ctxt, int nargs) {
518
519
1.32k
    int str_len = 0;
520
1.32k
    xmlChar *str = NULL, *ret = NULL;
521
1.32k
    unsigned char hash[HASH_DIGEST_LENGTH];
522
1.32k
    unsigned char hex[MD5_DIGEST_LENGTH * 2 + 1];
523
524
1.32k
    str_len = exsltCryptoPopString (ctxt, nargs, &str);
525
1.32k
    if (str_len == 0)
526
371
  return;
527
528
950
    PLATFORM_HASH (ctxt, PLATFORM_MD5, (const char *) str, str_len,
529
950
       (char *) hash);
530
950
    exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1);
531
532
950
    ret = xmlStrdup ((xmlChar *) hex);
533
950
    xmlXPathReturnString (ctxt, ret);
534
535
950
    if (str != NULL)
536
950
  xmlFree (str);
537
950
}
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
18.0k
exsltCryptoSha1Function (xmlXPathParserContextPtr ctxt, int nargs) {
548
549
18.0k
    int str_len = 0;
550
18.0k
    xmlChar *str = NULL, *ret = NULL;
551
18.0k
    unsigned char hash[HASH_DIGEST_LENGTH];
552
18.0k
    unsigned char hex[SHA1_DIGEST_LENGTH * 2 + 1];
553
554
18.0k
    str_len = exsltCryptoPopString (ctxt, nargs, &str);
555
18.0k
    if (str_len == 0)
556
14.6k
  return;
557
558
3.36k
    PLATFORM_HASH (ctxt, PLATFORM_SHA1, (const char *) str, str_len,
559
3.36k
       (char *) hash);
560
3.36k
    exsltCryptoBin2Hex (hash, sizeof (hash) - 1, hex, sizeof (hex) - 1);
561
562
3.36k
    ret = xmlStrdup ((xmlChar *) hex);
563
3.36k
    xmlXPathReturnString (ctxt, ret);
564
565
3.36k
    if (str != NULL)
566
3.36k
  xmlFree (str);
567
3.36k
}
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
234
exsltCryptoRc4EncryptFunction (xmlXPathParserContextPtr ctxt, int nargs) {
578
579
234
    int key_len = 0;
580
234
    int str_len = 0, bin_len = 0, hex_len = 0;
581
234
    xmlChar *key = NULL, *str = NULL, *padkey = NULL;
582
234
    xmlChar *bin = NULL, *hex = NULL;
583
234
    xsltTransformContextPtr tctxt = NULL;
584
585
234
    if (nargs != 2) {
586
1
  xmlXPathSetArityError (ctxt);
587
1
  return;
588
1
    }
589
233
    tctxt = xsltXPathGetTransformContext(ctxt);
590
591
233
    str = xmlXPathPopString (ctxt);
592
233
    str_len = xmlStrlen (str);
593
594
233
    if (str_len == 0) {
595
1
  xmlXPathReturnEmptyString (ctxt);
596
1
  xmlFree (str);
597
1
  return;
598
1
    }
599
600
232
    key = xmlXPathPopString (ctxt);
601
232
    key_len = xmlStrlen (key);
602
603
232
    if (key_len == 0) {
604
163
  xmlXPathReturnEmptyString (ctxt);
605
163
  xmlFree (key);
606
163
  xmlFree (str);
607
163
  return;
608
163
    }
609
610
69
    padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1);
611
69
    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
68
    memset(padkey, 0, RC4_KEY_LENGTH + 1);
619
620
68
    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
67
    memcpy (padkey, key, key_len);
628
629
/* encrypt it */
630
67
    bin_len = str_len;
631
67
    bin = xmlStrdup (str);
632
67
    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
66
    PLATFORM_RC4_ENCRYPT (ctxt, padkey, str, str_len, bin, bin_len);
640
641
/* encode it */
642
66
    hex_len = str_len * 2 + 1;
643
66
    hex = xmlMallocAtomic (hex_len);
644
66
    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
64
    exsltCryptoBin2Hex (bin, str_len, hex, hex_len);
653
64
    xmlXPathReturnString (ctxt, hex);
654
655
69
done:
656
69
    if (key != NULL)
657
69
  xmlFree (key);
658
69
    if (str != NULL)
659
69
  xmlFree (str);
660
69
    if (padkey != NULL)
661
68
  xmlFree (padkey);
662
69
    if (bin != NULL)
663
66
  xmlFree (bin);
664
69
}
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
2.82k
exsltCryptoRc4DecryptFunction (xmlXPathParserContextPtr ctxt, int nargs) {
675
676
2.82k
    int key_len = 0;
677
2.82k
    int str_len = 0, bin_len = 0, ret_len = 0;
678
2.82k
    xmlChar *key = NULL, *str = NULL, *padkey = NULL, *bin =
679
2.82k
  NULL, *ret = NULL;
680
2.82k
    xsltTransformContextPtr tctxt = NULL;
681
682
2.82k
    if (nargs != 2) {
683
84
  xmlXPathSetArityError (ctxt);
684
84
  return;
685
84
    }
686
2.74k
    tctxt = xsltXPathGetTransformContext(ctxt);
687
688
2.74k
    str = xmlXPathPopString (ctxt);
689
2.74k
    str_len = xmlStrlen (str);
690
691
2.74k
    if (str_len == 0) {
692
140
  xmlXPathReturnEmptyString (ctxt);
693
140
  xmlFree (str);
694
140
  return;
695
140
    }
696
697
2.60k
    key = xmlXPathPopString (ctxt);
698
2.60k
    key_len = xmlStrlen (key);
699
700
2.60k
    if (key_len == 0) {
701
306
  xmlXPathReturnEmptyString (ctxt);
702
306
  xmlFree (key);
703
306
  xmlFree (str);
704
306
  return;
705
306
    }
706
707
2.29k
    padkey = xmlMallocAtomic (RC4_KEY_LENGTH + 1);
708
2.29k
    if (padkey == NULL) {
709
3
  xsltTransformError(tctxt, NULL, tctxt->inst,
710
3
      "exsltCryptoRc4EncryptFunction: Failed to allocate padkey\n");
711
3
  tctxt->state = XSLT_STATE_STOPPED;
712
3
  xmlXPathReturnEmptyString (ctxt);
713
3
  goto done;
714
3
    }
715
2.29k
    memset(padkey, 0, RC4_KEY_LENGTH + 1);
716
2.29k
    if ((key_len > RC4_KEY_LENGTH) || (key_len < 0)) {
717
2
  xsltTransformError(tctxt, NULL, tctxt->inst,
718
2
      "exsltCryptoRc4EncryptFunction: key size too long or key broken\n");
719
2
  tctxt->state = XSLT_STATE_STOPPED;
720
2
  xmlXPathReturnEmptyString (ctxt);
721
2
  goto done;
722
2
    }
723
2.29k
    memcpy (padkey, key, key_len);
724
725
/* decode hex to binary */
726
2.29k
    bin_len = str_len;
727
2.29k
    bin = xmlMallocAtomic (bin_len);
728
2.29k
    if (bin == NULL) {
729
4
  xsltTransformError(tctxt, NULL, tctxt->inst,
730
4
      "exsltCryptoRc4EncryptFunction: Failed to allocate string\n");
731
4
  tctxt->state = XSLT_STATE_STOPPED;
732
4
  xmlXPathReturnEmptyString (ctxt);
733
4
  goto done;
734
4
    }
735
2.28k
    ret_len = exsltCryptoHex2Bin (str, str_len, bin, bin_len);
736
737
/* decrypt the binary blob */
738
2.28k
    ret = xmlMallocAtomic (ret_len + 1);
739
2.28k
    if (ret == NULL) {
740
3
  xsltTransformError(tctxt, NULL, tctxt->inst,
741
3
      "exsltCryptoRc4EncryptFunction: Failed to allocate result\n");
742
3
  tctxt->state = XSLT_STATE_STOPPED;
743
3
  xmlXPathReturnEmptyString (ctxt);
744
3
  goto done;
745
3
    }
746
2.28k
    PLATFORM_RC4_DECRYPT (ctxt, padkey, bin, ret_len, ret, ret_len);
747
2.28k
    ret[ret_len] = 0;
748
749
2.28k
    if (xmlCheckUTF8(ret) == 0) {
750
1.98k
  xsltTransformError(tctxt, NULL, tctxt->inst,
751
1.98k
      "exsltCryptoRc4DecryptFunction: Invalid UTF-8\n");
752
1.98k
        xmlFree(ret);
753
1.98k
  xmlXPathReturnEmptyString(ctxt);
754
1.98k
    } else {
755
298
        xmlXPathReturnString(ctxt, ret);
756
298
    }
757
758
2.29k
done:
759
2.29k
    if (key != NULL)
760
2.29k
  xmlFree (key);
761
2.29k
    if (str != NULL)
762
2.29k
  xmlFree (str);
763
2.29k
    if (padkey != NULL)
764
2.29k
  xmlFree (padkey);
765
2.29k
    if (bin != NULL)
766
2.28k
  xmlFree (bin);
767
2.29k
}
768
769
/**
770
 * exsltCryptoRegister:
771
 *
772
 * Registers the EXSLT - Crypto module
773
 */
774
775
void
776
4
exsltCryptoRegister (void) {
777
4
    xsltRegisterExtModuleFunction ((const xmlChar *) "md4",
778
4
           EXSLT_CRYPTO_NAMESPACE,
779
4
           exsltCryptoMd4Function);
780
4
    xsltRegisterExtModuleFunction ((const xmlChar *) "md5",
781
4
           EXSLT_CRYPTO_NAMESPACE,
782
4
           exsltCryptoMd5Function);
783
4
    xsltRegisterExtModuleFunction ((const xmlChar *) "sha1",
784
4
           EXSLT_CRYPTO_NAMESPACE,
785
4
           exsltCryptoSha1Function);
786
4
    xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_encrypt",
787
4
           EXSLT_CRYPTO_NAMESPACE,
788
4
           exsltCryptoRc4EncryptFunction);
789
4
    xsltRegisterExtModuleFunction ((const xmlChar *) "rc4_decrypt",
790
4
           EXSLT_CRYPTO_NAMESPACE,
791
4
           exsltCryptoRc4DecryptFunction);
792
4
}
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 */