Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/basex.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * convert/decode to/from ascii using various bases
3
 *
4
 * Copyright (C) 2008 iptelorg GmbH
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/*!
20
 * \file
21
 * \brief Kamailio core :: convert/decode to/from ascii using various bases
22
 *
23
 * Copyright (C) 2008 iptelorg GmbH
24
 * \ingroup core
25
 *
26
 * Module: \ref core
27
 *
28
 *
29
 * Functions:
30
 *  - base16_enc(src, src_len, dst, dst_len)    : encode to standard hex
31
 *  - base16_dec(src, src_len, dst, dst_len)    : decode from standard hex
32
 *  - base16_enc_len(len)                       : length needed to encode len bytes (macro)
33
 *  - base16_max_dec_len(len)                   : length needed to decode a string of size len
34
 *
35
 *  - base64_enc(src, src_len, dst, dst_len)    : encode to base64, standard alphabet
36
 *  - base64_dec(src, src_len, dst, dst_len)    : decode from base64, standard  alphabet
37
 *  - base64_enc_len(len)                       : length needed to encode len bytes (macro)
38
 *  - base64_max_dec_len(len)                   : maximum length needed to decode len bytes (macro)
39
 *  - base64_dec_len(str, len)                  : size of the decoded str
40
 *  - q_base64_enc(src, src_len, dst, dst_len)  : encode to special base64 alphabet (non standard)
41
 *  - q_base64_dec(src, src_len, dst, dst_len)  - decode from special non-standard base64 alphabet
42
 *
43
 *  All the above functions return the size used (in dst) on success and
44
 *   0 or a negative number (which is -1*size_needed) on error.
45
 *
46
 * There are close to no checks for validity, an unexpected char will lead
47
 * to a corrupted result, but the functions won't return error.
48
 *
49
 * Notes:
50
 *  on a core2 duo the versions with lookup tables are way faster (see
51
 *  http://www.experts-exchange.com/Programming/Languages/CPP/Q_21988706.html
52
 *  for some interesting tests and ideeas).
53
 *
54
 *  Test results for 40 bytes  (typical ser nounce) in average cpu cycles:
55
\verbatim
56
 *                    lookup   lookup_large lookup8k no-lookup
57
 *  base16_enc           211/231  218/199      -       1331
58
 *  base16_dec           252/251  236          -       1226
59
 *  base64_enc           209      186         156      1005
60
 *  base64_dec           208      207         207      1242
61
 *  q_base64_enc         -                              288
62
 *  q_base64_dec         -                              281
63
 *  (see test/basex.txt for more results)
64
\endverbatim
65
 *
66
 * Defines:
67
 *  - BASE64_LOOKUP_TABLE/NO_BASE64_LOOKUP_TABLE : use (default)/don't use
68
 *     small lookup tables for conversions (faster in general).
69
 *  - BASE64_LOOKUP_LARGE    : use large lookup tables (2560 bytes for
70
 *    encoding and 256 bytes for decoding; without it 64 bytes are used for
71
 *    encoding and 85 bytes for decoding.
72
 *  - BASE64_LOOKUP_8K : use even larger lookup tables (8K for encoding and
73
 *    256 for decoding); also try to write 2 bytes at a time (short) if
74
 *    the destination is 2 byte aligned
75
 *
76
 *  - BASE16_LOOKUP_TABLE/NO_BASE16_LOOKUP_TABLE : use (default)/don't use
77
 *     small lookup tables for conversions (faster in general).
78
 *  - BASE16_LOOKUP_LARGE  : use large lookup tables (512 bytes for
79
 *    encoding and 256 bytes for decoding
80
 *  - BASE16_READ_WHOLE_INTS : read an int at a time
81
 *
82
 * History:
83
 * --------
84
 *  2008-06-11  created by andrei
85
 */
86
87
88
#ifndef _basex_h
89
#define _basex_h
90
91
#include "compiler_opt.h"
92
93
/* defaults */
94
#ifndef NO_BASE16_LOOKUP_TABLE
95
#define BASE16_LOOKUP_TABLE
96
#endif
97
98
#ifndef NO_BASE64_LOOKUP_TABLE
99
#define BASE64_LOOKUP_TABLE
100
#endif
101
102
#ifndef NO_BASE64_LOOKUP_8K
103
#define BASE64_LOOKUP_8K
104
#endif
105
106
#ifndef NO_BASE16_LOOKUP_LARGE
107
#define BASE16_LOOKUP_LARGE
108
#endif
109
110
#if !defined NO_BASE64_LOOKUP_LARGE && !defined BASE64_LOOKUP_8K
111
#define BASE64_LOOKUP_LARGE
112
#endif
113
114
115
#if defined BASE16_READ_WHOLE_INTS || defined BASE64_READ_WHOLE_INTS \
116
    || defined BASE64_LOOKUP_8K
117
#include "endianness.h"
118
119
/*! \brief aligns p to a type* pointer, type must have a 2^k size */
120
#define ALIGN_POINTER(p, type)                       \
121
  ((type *)((long)((char *)(p) + sizeof(type) - 1) \
122
        & ~(long)(sizeof(type) - 1)))
123
124
#define ALIGN_UINT_POINTER(p) ALIGN_POINTER(p, unsigned int)
125
126
#endif
127
128
129
#ifdef BASE16_LOOKUP_TABLE
130
131
#ifdef BASE16_LOOKUP_LARGE
132
/*! \brief use large tables: 512 for lookup and 256 for decode */
133
134
extern unsigned char _bx_hexdig_hi[256];
135
extern unsigned char _bx_hexdig_low[256];
136
137
/*! \brief returns the first 4 bits of c converted to a hex digit */
138
#define HEX_HI(h) _bx_hexdig_hi[(unsigned char)(h)]
139
/*! \brief returns the low 4 bits of converted to a hex digit */
140
#define HEX_LOW(h) _bx_hexdig_low[(unsigned char)(h)]
141
142
extern unsigned char _bx_unhexdig256[256];
143
144
/*! \brief  converts hex_digit to a number (0..15); it might
145
 *      \return 0xff for invalid digit (but with some compile
146
 *      option it won't check)
147
 */
148
#define UNHEX(h) _bx_unhexdig256[(h)]
149
150
#else /* BASE16_LOOKUP_LARGE */
151
/*! \brief use small tabes: 16 bytes for lookup and 32 for decode */
152
153
extern unsigned char _bx_hexdig[16 + 1];
154
155
#define HEX_4BITS(h) _bx_hexdig[(h)]
156
#define HEX_HI(h) HEX_4BITS(((unsigned char)(h)) >> 4)
157
#define HEX_LOW(h) HEX_4BITS((h)&0xf)
158
159
extern unsigned char _bx_unhexdig32[32];
160
#define UNHEX(h) _bx_unhexdig32[(((h)) - '0') & 0x1f]
161
162
#endif /* BASE16_LOOKUP_LARGE */
163
164
#else /* BASE16_LOOKUP_TABLE */
165
/* no lookup tables */
166
#if 0
167
#define HEX_4BITS(h) \
168
  (unsigned char)((unlikely((h) >= 10)) ? ((h)-10 + 'A') : (h) + '0')
169
#define UNHEX(c) \
170
  (unsigned char)((unlikely((c) >= 'A')) ? (c) - 'A' + 10 : (c) - '0')
171
#else
172
#define HEX_4BITS(hc)                                   \
173
  (unsigned char)(((((hc) >= 10) - 1) & ((hc) + '0')) \
174
          | ((((hc) < 10) - 1) & ((hc) + 'A')))
175
#define UNHEX(c)                                      \
176
  (unsigned char)(((((c) > '9') - 1) & ((c) - '0')) \
177
          | ((((c) <= '9') - 1) & ((c) - 'A')))
178
#endif
179
180
#define HEX_HI(h) HEX_4BITS(((unsigned char)(h)) >> 4)
181
#define HEX_LOW(h) HEX_4BITS((h)&0xf)
182
183
#endif /* BASE16_LOOKUP_TABLE */
184
185
186
#ifdef BASE64_LOOKUP_TABLE
187
#ifdef BASE64_LOOKUP_LARGE
188
/* large lookup tables, 2.5 k */
189
190
extern unsigned char _bx_b64_first[256];
191
extern unsigned char _bx_b64_second[4][256];
192
extern unsigned char _bx_b64_third[4][256];
193
extern unsigned char _bx_b64_fourth[256];
194
195
#define BASE64_1(a) _bx_b64_first[(a)]
196
#define BASE64_2(a, b) _bx_b64_second[(a)&0x3][(b)]
197
#define BASE64_3(b, c) _bx_b64_third[(c) >> 6][(b)]
198
#define BASE64_4(c) _bx_b64_fourth[(c)]
199
200
extern unsigned char _bx_ub64[256];
201
#define UNBASE64(v) _bx_ub64[(v)]
202
203
#elif defined BASE64_LOOKUP_8K
204
/* even larger encode tables: 8k */
205
extern unsigned short _bx_b64_12[4096];
206
207
/* return a word (16 bits) */
208
#define BASE64_12(a, b) _bx_b64_12[((a) << 4) | ((b) >> 4)]
209
#define BASE64_34(b, c) _bx_b64_12[(((b)&0xf) << 8) | (c)]
210
#ifdef __IS_LITTLE_ENDIAN
211
#define FIRST_8B(s) ((unsigned char)(s))
212
#define LAST_8B(s) ((s) >> 8)
213
#elif defined __IS_BIG_ENDIAN
214
#define FIRST_8B(s) ((s) >> 8)
215
#define LAST_8B(s) ((unsigned char)(s))
216
#else
217
#error neither __IS_LITTLE_ENDIAN nor __IS_BIG_ENDIAN are defined
218
#endif
219
220
221
extern unsigned char _bx_ub64[256];
222
#define UNBASE64(v) _bx_ub64[(v)]
223
224
#else /* BASE64_LOOKUP_LARGE */
225
/* small lookup tables */
226
extern unsigned char _bx_b64[64 + 1];
227
228
#define BASE64_DIG(v) _bx_b64[(v)]
229
230
#define BASE64_1(a) BASE64_DIG((a) >> 2)
231
#define BASE64_2(a, b) BASE64_DIG((((a) << 4) & 0x3f) | ((b) >> 4))
232
#define BASE64_3(b, c) BASE64_DIG((((b) << 2) & 0x3f) | ((c) >> 6))
233
#define BASE64_4(c) BASE64_DIG((c)&0x3f)
234
235
extern unsigned char _bx_ub64[0x54 + 1];
236
#define UNBASE64(v) _bx_ub64[(((v)&0x7f) - 0x2b)]
237
238
#endif /* BASE64_LOOKUP_LARGE */
239
240
241
#else /* BASE64_LOOKUP_TABLE */
242
243
#define BASE64_DIG(v) base64_enc_char(v)
244
#define BASE64_1(a) BASE64_DIG((a) >> 2)
245
#define BASE64_2(a, b) BASE64_DIG((((a) << 4) & 0x3f) | ((b) >> 4))
246
#define BASE64_3(b, c) BASE64_DIG((((b) << 2) & 0x3f) | ((c) >> 6))
247
#define BASE64_4(c) BASE64_DIG((c)&0x3f)
248
249
#define UNBASE64(v) base64_dec_char(v)
250
251
#endif /* BASE64_LOOKUP_TABLE */
252
253
254
/*! \brief length needed for encoding l bytes */
255
#define base16_enc_len(l) (l * 2)
256
/*! \brief maximum length needed for decoding l bytes */
257
#define base16_max_dec_len(l) (l / 2)
258
/*! \brief actual space needed for decoding a string b of size l */
259
#define base16_dec_len(b, l) base16_max_dec_len(l)
260
/*! \brief minimum valid source len for decoding */
261
#define base16_dec_min_len() 2
262
/*! \brief minimum valid source len for encoding */
263
#define base16_enc_min_len() 0
264
265
/*! \brief space needed for encoding l bytes */
266
#define base64_enc_len(l) (((l) + 2) / 3 * 4)
267
/*! \brief maximum space needed for encoding l bytes */
268
#define base64_max_dec_len(l) ((l) / 4 * 3)
269
/*! \brief actual space needed for decoding a string b of size l, l>=4 */
270
#define base64_dec_len(b, l) \
271
  (base64_max_dec_len(l) - ((b)[(l)-2] == '=') - ((b)[(l)-1] == '='))
272
/*! \brief minimum valid source len for decoding */
273
#define base64_dec_min_len() 4
274
/*! \brief minimum valid source len for encoding */
275
#define base64_enc_min_len() 0
276
277
278
#ifdef BASE16_READ_WHOLE_INTS
279
280
/*!
281
 * \params:
282
 * \return: size used from the output buffer (dst) on success,
283
 *          -size_needed on error
284
 *
285
 * WARNING: the output string is not 0-term
286
 */
287
inline static int base16_enc(
288
    unsigned char *src, int slen, unsigned char *dst, int dlen)
289
{
290
  unsigned int *p;
291
  unsigned char *end;
292
  int osize;
293
  unsigned short us;
294
295
  osize = 2 * slen;
296
  if(unlikely(dlen < osize))
297
    return -osize;
298
  end = src + slen;
299
  p = ALIGN_UINT_POINTER(src);
300
  if(likely((unsigned char *)p < end)) {
301
    switch((unsigned char)((unsigned char *)p - src)) {
302
      case 3:
303
        *dst = HEX_HI(*src);
304
        *(dst + 1) = HEX_LOW(*src);
305
        dst += 2;
306
        src++;
307
        /* no break */
308
      case 2:
309
        us = *(unsigned short *)(src);
310
#if defined __IS_LITTLE_ENDIAN
311
        *(dst + 0) = HEX_HI(us);
312
        *(dst + 1) = HEX_LOW(us);
313
        *(dst + 2) = HEX_HI(us >> 8);
314
        *(dst + 3) = HEX_LOW(us >> 8);
315
#elif defined __IS_BIG_ENDIAN
316
        *(dst + 2) = HEX_HI(us);
317
        *(dst + 3) = HEX_LOW(us);
318
        *(dst + 0) = HEX_HI(us >> 8);
319
        *(dst + 1) = HEX_LOW(us >> 8);
320
#endif
321
        dst += 4;
322
        /* no need to inc src */
323
        break;
324
      case 1:
325
        *dst = HEX_HI(*src);
326
        *(dst + 1) = HEX_LOW(*src);
327
        dst += 2;
328
        /* no need to inc src */
329
      case 0:
330
        break;
331
    }
332
    for(; (unsigned char *)p <= (end - 4); p++, dst += 8) {
333
#if defined __IS_LITTLE_ENDIAN
334
      *(dst + 0) = HEX_HI(*p);
335
      *(dst + 1) = HEX_LOW(*p);
336
      *(dst + 2) = HEX_HI(((*p) >> 8));
337
      *(dst + 3) = HEX_LOW(((*p) >> 8));
338
      *(dst + 4) = HEX_HI(((*p) >> 16));
339
      *(dst + 5) = HEX_LOW(((*p) >> 16));
340
      *(dst + 6) = HEX_HI(((*p) >> 24));
341
      *(dst + 7) = HEX_LOW(((*p) >> 24));
342
#elif defined __IS_BIG_ENDIAN
343
      *(dst + 6) = HEX_HI(*p);
344
      *(dst + 7) = HEX_LOW(*p);
345
      *(dst + 4) = HEX_HI(((*p) >> 8));
346
      *(dst + 5) = HEX_LOW(((*p) >> 8));
347
      *(dst + 2) = HEX_HI(((*p) >> 16));
348
      *(dst + 3) = HEX_LOW(((*p) >> 16));
349
      *(dst + 0) = HEX_HI(((*p) >> 24));
350
      *(dst + 1) = HEX_LOW(((*p) >> 24));
351
#else
352
#error neither BIG ro LITTLE endian defined
353
#endif /* __IS_*_ENDIAN */
354
    }
355
    src = (unsigned char *)p;
356
    /* src is 2-bytes aligned (short) */
357
    switch((unsigned char)((unsigned char *)end - src)) {
358
      case 3:
359
      case 2:
360
        us = *(unsigned short *)(src);
361
#if defined __IS_LITTLE_ENDIAN
362
        *(dst + 0) = HEX_HI(us);
363
        *(dst + 1) = HEX_LOW(us);
364
        *(dst + 2) = HEX_HI(us >> 8);
365
        *(dst + 3) = HEX_LOW(us >> 8);
366
#elif defined __IS_BIG_ENDIAN
367
        *(dst + 2) = HEX_HI(us);
368
        *(dst + 3) = HEX_LOW(us);
369
        *(dst + 0) = HEX_HI(us >> 8);
370
        *(dst + 1) = HEX_LOW(us >> 8);
371
#endif
372
        if((end - src) == 3) {
373
          *(dst + 4) = HEX_HI(*(src + 2));
374
          *(dst + 5) = HEX_LOW(*(src + 2));
375
        }
376
        /* no need to inc anything */
377
        break;
378
      case 1:
379
        *dst = HEX_HI(*src);
380
        *(dst + 1) = HEX_LOW(*src);
381
        /* no need to inc anything */
382
      case 0:
383
        break;
384
    }
385
  } else if(unlikely((long)src & 1)) {
386
    /* src is not 2-bytes (short) aligned */
387
    switch((unsigned char)((unsigned char *)end - src)) {
388
      case 3:
389
        *dst = HEX_HI(*src);
390
        *(dst + 1) = HEX_LOW(*src);
391
        dst += 2;
392
        src++;
393
        /* no break */
394
      case 2:
395
        us = *(unsigned short *)(src);
396
#if defined __IS_LITTLE_ENDIAN
397
        *(dst + 0) = HEX_HI(us);
398
        *(dst + 1) = HEX_LOW(us);
399
        *(dst + 2) = HEX_HI(us >> 8);
400
        *(dst + 3) = HEX_LOW(us >> 8);
401
#elif defined __IS_BIG_ENDIAN
402
        *(dst + 2) = HEX_HI(us);
403
        *(dst + 3) = HEX_LOW(us);
404
        *(dst + 0) = HEX_HI(us >> 8);
405
        *(dst + 1) = HEX_LOW(us >> 8);
406
#endif
407
        /* no need to inc anything */
408
        break;
409
      case 1:
410
        *dst = HEX_HI(*src);
411
        *(dst + 1) = HEX_LOW(*src);
412
        /* no need to inc anything */
413
      case 0:
414
        break;
415
    }
416
  } else {
417
    /* src is 2-bytes aligned (short) */
418
    switch((unsigned char)((unsigned char *)end - src)) {
419
      case 3:
420
      case 2:
421
        us = *(unsigned short *)(src);
422
#if defined __IS_LITTLE_ENDIAN
423
        *(dst + 0) = HEX_HI(us);
424
        *(dst + 1) = HEX_LOW(us);
425
        *(dst + 2) = HEX_HI(us >> 8);
426
        *(dst + 3) = HEX_LOW(us >> 8);
427
#elif defined __IS_BIG_ENDIAN
428
        *(dst + 2) = HEX_HI(us);
429
        *(dst + 3) = HEX_LOW(us);
430
        *(dst + 0) = HEX_HI(us >> 8);
431
        *(dst + 1) = HEX_LOW(us >> 8);
432
#endif
433
        if((end - src) == 3) {
434
          *(dst + 4) = HEX_HI(*(src + 2));
435
          *(dst + 5) = HEX_LOW(*(src + 2));
436
        }
437
        /* no need to inc anything */
438
        break;
439
      case 1:
440
        *dst = HEX_HI(*src);
441
        *(dst + 1) = HEX_LOW(*src);
442
        /* no need to inc anything */
443
      case 0:
444
        break;
445
    }
446
  }
447
448
  return osize;
449
}
450
451
452
#else /* BASE16_READ_WHOLE_INTS */
453
454
455
/*!
456
 * \return : size used from the output buffer (dst) on success,
457
 *          -size_needed on error
458
 *
459
 * \note WARNING: the output string is not 0-term
460
 */
461
inline static int base16_enc(
462
    unsigned char *src, int slen, unsigned char *dst, int dlen)
463
0
{
464
0
  unsigned char *end;
465
0
  int osize;
466
0
467
0
  osize = 2 * slen;
468
0
  if(unlikely(dlen < osize))
469
0
    return -osize;
470
0
  end = src + slen;
471
0
  for(; src < end; src++, dst += 2) {
472
0
    *dst = HEX_HI(*src);
473
0
    *(dst + 1) = HEX_LOW(*src);
474
0
  }
475
0
  return osize;
476
0
}
Unexecuted instantiation: main.c:base16_enc
Unexecuted instantiation: basex.c:base16_enc
477
478
479
#endif /* BASE16_READ_WHOLE_INTS */
480
481
inline static int base16_dec(
482
    unsigned char *src, int slen, unsigned char *dst, int dlen)
483
0
{
484
0
  unsigned char *end;
485
0
  int osize;
486
0
487
0
  osize = slen / 2;
488
0
  if(unlikely(dlen < osize))
489
0
    return -osize;
490
0
  end = src + 2 * osize;
491
0
  for(; src < end; src += 2, dst++)
492
0
    *dst = (UNHEX(*src) << 4) | UNHEX(*(src + 1));
493
0
  return osize;
494
0
}
Unexecuted instantiation: main.c:base16_dec
Unexecuted instantiation: basex.c:base16_dec
495
496
497
/*! \brief helper internal function: encodes v (6 bits value)
498
 * \return char ascii encoding on success and 0xff on error
499
 * (value out of range) */
500
inline static unsigned char base64_enc_char(unsigned char v)
501
0
{
502
0
  switch(v) {
503
0
    case 0x3f:
504
0
      return '/';
505
0
    case 0x3e:
506
0
      return '+';
507
0
    default:
508
0
      if(v <= 25)
509
0
        return v + 'A';
510
0
      else if(v <= 51)
511
0
        return v - 26 + 'a';
512
0
      else if(v <= 61)
513
0
        return v - 52 + '0';
514
0
  }
515
0
  return 0xff;
516
0
}
Unexecuted instantiation: main.c:base64_enc_char
Unexecuted instantiation: basex.c:base64_enc_char
517
518
/*! \brief helper internal function: decodes a base64 "digit",
519
 * \return value on success (0-63) and 0xff on error (invalid)*/
520
inline static unsigned base64_dec_char(unsigned char v)
521
0
{
522
0
  switch(v) {
523
0
    case '/':
524
0
      return 0x3f;
525
0
    case '+':
526
0
      return 0x3e;
527
0
    case ':':
528
0
    case ';':
529
0
    case '<':
530
0
    case '=':
531
0
    case '>':
532
0
    case '?':
533
0
    case '@':
534
0
    case '[':
535
0
    case '\\':
536
0
    case ']':
537
0
    case '^':
538
0
    case '_':
539
0
    case '`':
540
0
      return 0xff;
541
0
    default:
542
0
      if((v) < '0')
543
0
        return 0xff;
544
0
      if((v) <= '9')
545
0
        return (v) - '0' + 0x34;
546
0
      else if((v) <= 'Z')
547
0
        return (v) - 'A';
548
0
      else if((v) <= 'z')
549
0
        return (v) - 'a' + 0x1a;
550
0
  }
551
0
  return 0xff;
552
0
}
Unexecuted instantiation: main.c:base64_dec_char
Unexecuted instantiation: basex.c:base64_dec_char
553
554
555
#ifdef BASE64_LOOKUP_8K
556
/*!
557
 * \return : size used from the output buffer (dst) on success ((slen+2)/3*4)
558
 *          -size_needed on error
559
 *
560
 * \note WARNING: the output string is not 0-term
561
 */
562
inline static int base64_enc(
563
    unsigned char *src, int slen, unsigned char *dst, int dlen)
564
0
{
565
0
  unsigned char *end;
566
0
  int osize;
567
0
568
0
  osize = (slen + 2) / 3 * 4;
569
0
  if(unlikely(dlen < osize))
570
0
    return -osize;
571
0
  end = src + slen / 3 * 3;
572
0
  if(unlikely((long)dst % 2)) {
573
0
    for(; src < end; src += 3, dst += 4) {
574
0
      dst[0] = FIRST_8B(BASE64_12(src[0], src[1]));
575
0
      dst[1] = LAST_8B(BASE64_12(src[0], src[1]));
576
0
      dst[2] = FIRST_8B(BASE64_34(src[1], src[2]));
577
0
      dst[3] = LAST_8B(BASE64_34(src[1], src[2]));
578
0
    }
579
0
    switch(slen % 3) {
580
0
      case 2:
581
0
        dst[0] = FIRST_8B(BASE64_12(src[0], src[1]));
582
0
        dst[1] = LAST_8B(BASE64_12(src[0], src[1]));
583
0
        dst[2] = FIRST_8B(BASE64_34(src[1], 0));
584
0
        dst[3] = '=';
585
0
        break;
586
0
      case 1:
587
0
        dst[0] = FIRST_8B(BASE64_12(src[0], 0));
588
0
        dst[1] = LAST_8B(BASE64_12(src[0], 0));
589
0
        dst[2] = '=';
590
0
        dst[3] = '=';
591
0
        break;
592
0
    }
593
0
  } else {
594
0
    for(; src < end; src += 3, dst += 4) {
595
0
      *(unsigned short *)(dst + 0) =
596
0
          _bx_b64_12[(src[0] << 4) | (src[1] >> 4)];
597
0
      *(unsigned short *)(dst + 2) =
598
0
          _bx_b64_12[((src[1] & 0xf) << 8) | src[2]];
599
0
    }
600
0
    switch(slen % 3) {
601
0
      case 2:
602
0
        *(unsigned short *)(dst + 0) =
603
0
            _bx_b64_12[(src[0] << 4) | (src[1] >> 4)];
604
0
        *(unsigned short *)(dst + 2) =
605
0
            _bx_b64_12[((src[1] & 0xf) << 8) | 0];
606
0
        dst[3] = '=';
607
0
        break;
608
0
      case 1:
609
0
        *(unsigned short *)(dst + 0) = _bx_b64_12[(src[0] << 4) | 0];
610
0
        dst[2] = '=';
611
0
        dst[3] = '=';
612
0
        break;
613
0
    }
614
0
  }
615
0
  return osize;
616
0
}
Unexecuted instantiation: main.c:base64_enc
Unexecuted instantiation: basex.c:base64_enc
617
#else  /*BASE64_LOOKUP_8K*/
618
/*! \brief Convert to base64
619
 * \return size used from the output buffer (dst) on success ((slen+2)/3*4)
620
 *          -size_needed on error
621
 * \note WARNING: the output string is not 0-term
622
 */
623
inline static int base64_enc(
624
    unsigned char *src, int slen, unsigned char *dst, int dlen)
625
{
626
  unsigned char *end;
627
  int osize;
628
629
  osize = (slen + 2) / 3 * 4;
630
  if(unlikely(dlen < osize))
631
    return -osize;
632
  end = src + slen / 3 * 3;
633
  for(; src < end; src += 3, dst += 4) {
634
    dst[0] = BASE64_1(src[0]);
635
    dst[1] = BASE64_2(src[0], src[1]);
636
    dst[2] = BASE64_3(src[1], src[2]);
637
    dst[3] = BASE64_4(src[2]);
638
  }
639
  switch(slen % 3) {
640
    case 2:
641
      dst[0] = BASE64_1(src[0]);
642
      dst[1] = BASE64_2(src[0], src[1]);
643
      dst[2] = BASE64_3(src[1], 0);
644
      dst[3] = '=';
645
      break;
646
    case 1:
647
      dst[0] = BASE64_1(src[0]);
648
      dst[1] = BASE64_2(src[0], 0);
649
      dst[2] = '=';
650
      dst[3] = '=';
651
      break;
652
  }
653
  return osize;
654
}
655
#endif /*BASE64_LOOKUP_8K*/
656
657
658
/*! \brief
659
 * \return size used from the output buffer (dst) on success (max: slen/4*3)
660
 *          -size_needed on error or 0 on bad base64 encoded string
661
 * \note WARNING: the output string is not 0-term
662
 */
663
inline static int base64_dec(
664
    unsigned char *src, int slen, unsigned char *dst, int dlen)
665
0
{
666
0
667
0
  unsigned char *end;
668
0
  int osize;
669
0
  register unsigned a, b, c, d; /* more registers used, but allows for
670
0
                   parallel execution */
671
0
672
0
  if(unlikely((slen < 4) || (slen % 4)
673
0
        || (src[slen - 2] == '=' && src[slen - 1] != '=')))
674
0
    return 0; /* invalid base64 enc. */
675
0
  osize = (slen / 4 * 3) - (src[slen - 2] == '=') - (src[slen - 1] == '=');
676
0
  if(unlikely(dlen < osize))
677
0
    return -osize;
678
0
  end = src + slen - 4;
679
0
  for(; src < end; src += 4, dst += 3) {
680
0
#if 0
681
0
    u=  (UNBASE64(src[0])<<18) | (UNBASE64(src[1])<<12) |
682
0
      (UNBASE64(src[2])<<6)  |  UNBASE64(src[3]);
683
0
    dst[0]=u>>16;
684
0
    dst[1]=u>>8;
685
0
    dst[3]=u;
686
0
#endif
687
0
    a = UNBASE64(src[0]);
688
0
    b = UNBASE64(src[1]);
689
0
    c = UNBASE64(src[2]);
690
0
    d = UNBASE64(src[3]);
691
0
    dst[0] = (a << 2) | (b >> 4);
692
0
    dst[1] = (b << 4) | (c >> 2);
693
0
    dst[2] = (c << 6) | d;
694
0
  }
695
0
  switch(osize % 3) {
696
0
    case 0: /* no '=' => 3 output bytes at the end */
697
0
      a = UNBASE64(src[0]);
698
0
      b = UNBASE64(src[1]);
699
0
      c = UNBASE64(src[2]);
700
0
      d = UNBASE64(src[3]);
701
0
      dst[0] = (a << 2) | (b >> 4);
702
0
      dst[1] = (b << 4) | (c >> 2);
703
0
      dst[2] = (c << 6) | d;
704
0
      break;
705
0
    case 2: /* 1  '=' => 2 output bytes at the end */
706
0
      a = UNBASE64(src[0]);
707
0
      b = UNBASE64(src[1]);
708
0
      c = UNBASE64(src[2]);
709
0
      dst[0] = (a << 2) | (b >> 4);
710
0
      dst[1] = (b << 4) | (c >> 2);
711
0
      break;
712
0
    case 1: /* 2  '=' => 1 output byte at the end */
713
0
      a = UNBASE64(src[0]);
714
0
      b = UNBASE64(src[1]);
715
0
      dst[0] = (a << 2) | (b >> 4);
716
0
      break;
717
0
  }
718
0
  return osize;
719
0
}
Unexecuted instantiation: main.c:base64_dec
Unexecuted instantiation: basex.c:base64_dec
720
721
722
/*! \brief
723
 * same as \ref base64_enc() but with a different alphabet, that allows simpler and
724
 *  faster enc/dec
725
 * \return size used from the output buffer (dst) on success ((slen+2)/3*4)
726
 *          -size_needed on error
727
 * \note WARNING: the alphabet includes ":;<>?@[]\`", so it might not be suited
728
 *  in all cases (e.g. encoding something in a sip uri).
729
 */
730
inline static int q_base64_enc(
731
    unsigned char *src, int slen, unsigned char *dst, int dlen)
732
0
{
733
0
#define q_b64_base '0'
734
0
#define q_b64_pad 'z'
735
0
#define Q_BASE64(v) (unsigned char)((v) + q_b64_base)
736
0
  unsigned char *end;
737
0
  int osize;
738
0
739
0
  osize = (slen + 2) / 3 * 4;
740
0
  if(unlikely(dlen < osize))
741
0
    return -osize;
742
0
  end = src + slen / 3 * 3;
743
0
  for(; src < end; src += 3, dst += 4) {
744
0
    dst[0] = Q_BASE64(src[0] >> 2);
745
0
    dst[1] = (Q_BASE64((src[0] << 4) & 0x3f) | (src[1] >> 4));
746
0
    dst[2] = (Q_BASE64((src[1] << 2) & 0x3f) | (src[2] >> 6));
747
0
    dst[3] = Q_BASE64(src[2] & 0x3f);
748
0
  }
749
0
  switch(slen % 3) {
750
0
    case 2:
751
0
      dst[0] = Q_BASE64(src[0] >> 2);
752
0
      dst[1] = (Q_BASE64((src[0] << 4) & 0x3f) | (src[1] >> 4));
753
0
      dst[2] = Q_BASE64((src[1] << 2) & 0x3f);
754
0
      dst[3] = q_b64_pad;
755
0
      break;
756
0
    case 1:
757
0
      dst[0] = Q_BASE64(src[0] >> 2);
758
0
      dst[1] = Q_BASE64((src[0] << 4) & 0x3f);
759
0
      dst[2] = q_b64_pad;
760
0
      dst[3] = q_b64_pad;
761
0
      break;
762
0
  }
763
0
  return osize;
764
0
#undef Q_BASE64
765
0
}
Unexecuted instantiation: main.c:q_base64_enc
Unexecuted instantiation: basex.c:q_base64_enc
766
767
768
/*! \brief
769
 * same as \ref base64_enc() but with a different alphabet, that allows simpler and
770
 *  faster enc/dec
771
 *
772
 * \return size used from the output buffer (dst) on success (max: slen/4*3)
773
 *          -size_needed on error or 0 on bad base64 encoded string
774
 * \note WARNING: the output string is not 0-term
775
 */
776
inline static int q_base64_dec(
777
    unsigned char *src, int slen, unsigned char *dst, int dlen)
778
0
{
779
0
#define Q_UNBASE64(v) (unsigned char)((v)-q_b64_base)
780
0
781
0
  unsigned char *end;
782
0
  int osize;
783
0
#ifdef SINGLE_REG
784
0
  register unsigned u;
785
0
#else
786
0
  register unsigned a, b, c, d; /* more registers used, but allows for
787
0
                   parallel execution */
788
0
#endif
789
0
790
0
  if(unlikely((slen < 4) || (slen % 4)
791
0
        || (src[slen - 2] == q_b64_pad && src[slen - 1] != q_b64_pad)))
792
0
    return 0; /* invalid base64 enc. */
793
0
  osize = (slen / 4 * 3) - (src[slen - 2] == q_b64_pad)
794
0
      - (src[slen - 1] == q_b64_pad);
795
0
  if(unlikely(dlen < osize))
796
0
    return -osize;
797
0
  end = src + slen - 4;
798
0
  for(; src < end; src += 4, dst += 3) {
799
0
#ifdef SINGLE_REG
800
0
    u = (Q_UNBASE64(src[0]) << 18) | (Q_UNBASE64(src[1]) << 12)
801
0
      | (Q_UNBASE64(src[2]) << 6) | Q_UNBASE64(src[3]);
802
0
    dst[0] = u >> 16;
803
0
    dst[1] = u >> 8;
804
0
    dst[2] = u;
805
0
#else
806
0
    a = Q_UNBASE64(src[0]);
807
0
    b = Q_UNBASE64(src[1]);
808
0
    c = Q_UNBASE64(src[2]);
809
0
    d = Q_UNBASE64(src[3]);
810
0
    dst[0] = (a << 2) | (b >> 4);
811
0
    dst[1] = (b << 4) | (c >> 2);
812
0
    dst[2] = (c << 6) | d;
813
0
#endif
814
0
  }
815
0
  switch(osize % 3) {
816
0
    case 0: /* no '=' => 3 output bytes at the end */
817
0
#ifdef SINGLE_REG
818
0
      u = (Q_UNBASE64(src[0]) << 18) | (Q_UNBASE64(src[1]) << 12)
819
0
        | (Q_UNBASE64(src[2]) << 6) | Q_UNBASE64(src[3]);
820
0
      dst[0] = u >> 16;
821
0
      dst[1] = u >> 8;
822
0
      dst[2] = u;
823
0
#else
824
0
      a = Q_UNBASE64(src[0]);
825
0
      b = Q_UNBASE64(src[1]);
826
0
      c = Q_UNBASE64(src[2]);
827
0
      d = Q_UNBASE64(src[3]);
828
0
      dst[0] = (a << 2) | (b >> 4);
829
0
      dst[1] = (b << 4) | (c >> 2);
830
0
      dst[2] = (c << 6) | d;
831
0
#endif
832
0
      break;
833
0
    case 2: /* 1  '=' => 2 output bytes at the end */
834
0
#ifdef SINGLE_REG
835
0
      u = (Q_UNBASE64(src[0]) << 12) | (Q_UNBASE64(src[1]) << 6)
836
0
        | (Q_UNBASE64(src[2]));
837
0
      dst[0] = u >> 10;
838
0
      dst[1] = u >> 2;
839
0
#else
840
0
      a = Q_UNBASE64(src[0]);
841
0
      b = Q_UNBASE64(src[1]);
842
0
      c = Q_UNBASE64(src[2]);
843
0
      dst[0] = (a << 2) | (b >> 4);
844
0
      dst[1] = (b << 4) | (c >> 2);
845
0
#endif
846
0
      break;
847
0
    case 1: /* 2  '=' => 1 output byte at the end */
848
0
#ifdef SINGLE_REG
849
0
      dst[0] = (Q_UNBASE64(src[0]) << 2) | (Q_UNBASE64(src[1]) >> 4);
850
0
#else
851
0
      a = Q_UNBASE64(src[0]);
852
0
      b = Q_UNBASE64(src[1]);
853
0
      dst[0] = (a << 2) | (b >> 4);
854
0
#endif
855
0
      break;
856
0
  }
857
0
  return osize;
858
0
#undef q_b64_base
859
0
#undef q_b64_pad
860
0
}
Unexecuted instantiation: main.c:q_base64_dec
Unexecuted instantiation: basex.c:q_base64_dec
861
862
/*! \brief inits internal lookup tables */
863
int init_basex(void);
864
865
char *b58_encode(char *b58, int *b58sz, char *data, int binsz);
866
char *b58_decode(char *outb, int *outbszp, char *b58, int b58sz);
867
868
int base64url_enc(char *in, int ilen, char *out, int osize);
869
int base64url_dec(char *in, int ilen, char *out, int osize);
870
871
#endif /* _basex_h */