Coverage Report

Created: 2024-02-16 06:13

/src/open62541/deps/base64.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Base64 encoding: Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
3
 * This software may be distributed under the terms of the BSD license.
4
 *
5
 * Base64 decoding: Copyright (c) 2016, polfosol
6
 * Posted at https://stackoverflow.com/a/37109258 under the CC-BY-SA Creative
7
 * Commons license.
8
 */
9
10
#include "base64.h"
11
#include <open62541/types.h>
12
13
static const unsigned char base64_table[65] =
14
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
15
16
unsigned char *
17
109k
UA_base64(const unsigned char *src, size_t len, size_t *out_len) {
18
109k
    if(len == 0) {
19
0
        *out_len = 0;
20
0
        return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
21
0
    }
22
23
109k
  size_t olen = 4*((len + 2) / 3); /* 3-byte blocks to 4-byte */
24
109k
  if(olen < len)
25
0
    return NULL; /* integer overflow */
26
27
109k
  unsigned char *out = (unsigned char*)UA_malloc(olen);
28
109k
  if(!out)
29
0
    return NULL;
30
31
109k
    *out_len = UA_base64_buf(src, len, out);
32
109k
    return out;
33
109k
}
34
35
size_t
36
109k
UA_base64_buf(const unsigned char *src, size_t len, unsigned char *out) {
37
109k
  const unsigned char *end = src + len;
38
109k
  const unsigned char *in = src;
39
109k
  unsigned char *pos = out;
40
10.8M
  while(end - in >= 3) {
41
10.7M
    *pos++ = base64_table[in[0] >> 2];
42
10.7M
    *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
43
10.7M
    *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
44
10.7M
    *pos++ = base64_table[in[2] & 0x3f];
45
10.7M
    in += 3;
46
10.7M
  }
47
48
109k
  if(end - in) {
49
69.7k
    *pos++ = base64_table[in[0] >> 2];
50
69.7k
    if(end - in == 1) {
51
766
      *pos++ = base64_table[(in[0] & 0x03) << 4];
52
766
      *pos++ = '=';
53
68.9k
    } else {
54
68.9k
      *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
55
68.9k
      *pos++ = base64_table[(in[1] & 0x0f) << 2];
56
68.9k
    }
57
69.7k
    *pos++ = '=';
58
69.7k
  }
59
60
109k
    return (size_t)(pos - out);
61
109k
}
62
63
static const uint32_t from_b64[256] = {
64
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
65
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
66
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  62, 63, 62, 62, 63,
67
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,  0,  0,  0,  0,  0,
68
    0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
69
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,  0,  0,  0,  63,
70
    0,  26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
71
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
72
73
unsigned char *
74
1.15M
UA_unbase64(const unsigned char *src, size_t len, size_t *out_len) {
75
    // we need a minimum length
76
1.15M
    if(len <= 2) {
77
906k
        *out_len = 0;
78
906k
        return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
79
906k
    }
80
81
243k
    const unsigned char *p = src;
82
243k
    size_t pad1 = len % 4 || p[len - 1] == '=';
83
243k
    size_t pad2 = pad1 && (len % 4 > 2 || p[len - 2] != '=');
84
243k
    const size_t last = (len - pad1) / 4 << 2;
85
86
243k
    unsigned char *str = (unsigned char*)UA_malloc(last / 4 * 3 + pad1 + pad2);
87
243k
    if(!str)
88
0
        return NULL;
89
90
243k
    unsigned char *pos = str;
91
7.01M
    for(size_t i = 0; i < last; i += 4) {
92
6.76M
        uint32_t n = from_b64[p[i]] << 18 | from_b64[p[i + 1]] << 12 |
93
6.76M
                     from_b64[p[i + 2]] << 6 | from_b64[p[i + 3]];
94
6.76M
        *pos++ = (unsigned char)(n >> 16);
95
6.76M
        *pos++ = (unsigned char)(n >> 8 & 0xFF);
96
6.76M
        *pos++ = (unsigned char)(n & 0xFF);
97
6.76M
    }
98
99
243k
    if(pad1) {
100
210k
        if (last + 1 >= len) {
101
6.53k
            UA_free(str);
102
6.53k
            *out_len = 0;
103
6.53k
            return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
104
6.53k
        }
105
203k
        uint32_t n = from_b64[p[last]] << 18 | from_b64[p[last + 1]] << 12;
106
203k
        *pos++ = (unsigned char)(n >> 16);
107
203k
        if(pad2) {
108
202k
            if (last + 2 >= len) {
109
5.61k
                UA_free(str);
110
5.61k
                *out_len = 0;
111
5.61k
                return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
112
5.61k
            }
113
197k
            n |= from_b64[p[last + 2]] << 6;
114
197k
            *pos++ = (unsigned char)(n >> 8 & 0xFF);
115
197k
        }
116
203k
    }
117
118
231k
    *out_len = (uintptr_t)(pos - str);
119
231k
    return str;
120
243k
}