Coverage Report

Created: 2024-08-20 14:13

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