Coverage Report

Created: 2023-06-07 06:06

/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
0
UA_base64(const unsigned char *src, size_t len, size_t *out_len) {
18
0
    if(len == 0) {
19
0
        *out_len = 0;
20
0
        return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
21
0
    }
22
23
0
  size_t olen = 4*((len + 2) / 3); /* 3-byte blocks to 4-byte */
24
0
  if(olen < len)
25
0
    return NULL; /* integer overflow */
26
27
0
  unsigned char *out = (unsigned char*)UA_malloc(olen);
28
0
  if(!out)
29
0
    return NULL;
30
31
0
    *out_len = UA_base64_buf(src, len, out);
32
0
    return out;
33
0
}
34
35
size_t
36
0
UA_base64_buf(const unsigned char *src, size_t len, unsigned char *out) {
37
0
  const unsigned char *end = src + len;
38
0
  const unsigned char *in = src;
39
0
  unsigned char *pos = out;
40
0
  while(end - in >= 3) {
41
0
    *pos++ = base64_table[in[0] >> 2];
42
0
    *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
43
0
    *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
44
0
    *pos++ = base64_table[in[2] & 0x3f];
45
0
    in += 3;
46
0
  }
47
48
0
  if(end - in) {
49
0
    *pos++ = base64_table[in[0] >> 2];
50
0
    if(end - in == 1) {
51
0
      *pos++ = base64_table[(in[0] & 0x03) << 4];
52
0
      *pos++ = '=';
53
0
    } else {
54
0
      *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
55
0
      *pos++ = base64_table[(in[1] & 0x0f) << 2];
56
0
    }
57
0
    *pos++ = '=';
58
0
  }
59
60
0
    return (size_t)(pos - out);
61
0
}
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
0
UA_unbase64(const unsigned char *src, size_t len, size_t *out_len) {
75
    // we need a minimum length
76
0
    if(len <= 2) {
77
0
        *out_len = 0;
78
0
        return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
79
0
    }
80
81
0
    const unsigned char *p = src;
82
0
    size_t pad1 = len % 4 || p[len - 1] == '=';
83
0
    size_t pad2 = pad1 && (len % 4 > 2 || p[len - 2] != '=');
84
0
    const size_t last = (len - pad1) / 4 << 2;
85
86
0
    unsigned char *str = (unsigned char*)UA_malloc(last / 4 * 3 + pad1 + pad2);
87
0
    if(!str)
88
0
        return NULL;
89
90
0
    unsigned char *pos = str;
91
0
    for(size_t i = 0; i < last; i += 4) {
92
0
        uint32_t n = from_b64[p[i]] << 18 | from_b64[p[i + 1]] << 12 |
93
0
                     from_b64[p[i + 2]] << 6 | from_b64[p[i + 3]];
94
0
        *pos++ = (unsigned char)(n >> 16);
95
0
        *pos++ = (unsigned char)(n >> 8 & 0xFF);
96
0
        *pos++ = (unsigned char)(n & 0xFF);
97
0
    }
98
99
0
    if(pad1) {
100
0
        if (last + 1 >= len) {
101
0
            UA_free(str);
102
0
            *out_len = 0;
103
0
            return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
104
0
        }
105
0
        uint32_t n = from_b64[p[last]] << 18 | from_b64[p[last + 1]] << 12;
106
0
        *pos++ = (unsigned char)(n >> 16);
107
0
        if(pad2) {
108
0
            if (last + 2 >= len) {
109
0
                UA_free(str);
110
0
                *out_len = 0;
111
0
                return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
112
0
            }
113
0
            n |= from_b64[p[last + 2]] << 6;
114
0
            *pos++ = (unsigned char)(n >> 8 & 0xFF);
115
0
        }
116
0
    }
117
118
0
    *out_len = (uintptr_t)(pos - str);
119
0
    return str;
120
0
}