Coverage Report

Created: 2026-06-10 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/base64.c
Line
Count
Source
1
/*
2
 * base64.c: Base64 converting functions
3
 *
4
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
25
#include <stdlib.h>
26
#include <string.h>
27
#include <stdio.h>
28
#include <assert.h>
29
30
#include "internal.h"
31
32
static const u8 base64_table[66] =
33
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
34
  "0123456789+/=";
35
36
static const u8 bin_table[128] = {
37
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
38
        0xFF,0xE0,0xD0,0xFF,0xFF,0xD0,0xFF,0xFF,
39
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
40
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
41
        0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
42
        0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F,
43
        0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,
44
        0x3C,0x3D,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,
45
        0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
46
        0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
47
        0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
48
        0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,
49
        0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
50
        0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
51
        0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,
52
        0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,
53
};
54
55
static void to_base64(unsigned int i, u8 *out, size_t fillers)
56
0
{
57
0
  unsigned int s, c;
58
59
0
  for (c = 0, s = 18; c < 4; c++, s -= 6) {
60
0
    if (fillers >= 4 - c)
61
0
      *out = base64_table[64];
62
0
    else
63
0
      *out = base64_table[(i >> s) & 0x3f];
64
0
    out++;
65
0
  }
66
0
}
67
68
static int from_base64(const char *in, unsigned int *out, size_t *skip)
69
0
{
70
0
  unsigned int res = 0, c, s = 18;
71
0
  const char *in0 = in;
72
73
0
  for (c = 0; c < 4; c++, in++) {
74
0
    u8 b;
75
0
    int k = *in;
76
77
0
    if (k < 0 || k >= (int)sizeof(bin_table))
78
0
      return -1;
79
0
    if (k == 0 && c == 0)
80
0
      return 0;
81
0
    b = bin_table[k];
82
0
    if (b == 0xC0) /* '=' */
83
0
      break;
84
0
    switch (b) {
85
0
    case 0xD0: /* '\n' or '\r' */
86
0
      c--;
87
0
      continue;
88
0
    }
89
0
    if (b > 0x3f)
90
0
      return -1;
91
92
0
    res |= b << s;
93
0
    s -= 6;
94
0
  }
95
0
  *skip = in - in0;
96
0
  *out = res;
97
0
  return c * 6 / 8;
98
0
}
99
100
int sc_base64_encode(const u8 *in, size_t len, u8 *out, size_t outlen, size_t linelength)
101
0
{
102
0
  unsigned int chars = 0;
103
0
  unsigned int i, c;
104
105
0
  linelength -= linelength & 0x03;
106
0
  while (len >= 3) {
107
0
    i = in[2] + (in[1] << 8) + (in[0] << 16);
108
0
    in += 3;
109
0
    len -= 3;
110
0
    if (outlen < 4)
111
0
      return SC_ERROR_BUFFER_TOO_SMALL;
112
0
    to_base64(i, out, 0);
113
0
    out += 4;
114
0
    outlen -= 4;
115
0
    chars += 4;
116
0
    if (chars >= linelength && linelength > 0) {
117
0
      if (outlen < 1)
118
0
        return SC_ERROR_BUFFER_TOO_SMALL;
119
0
      *out = '\n';
120
0
      out++;
121
0
      outlen--;
122
0
      chars = 0;
123
0
    }
124
0
  }
125
0
  i = c = 0;
126
0
  while (c < len)
127
0
    i |= ((unsigned int) *in++) << ((2 - c++) << 3);
128
0
  if (len) {
129
0
    if (outlen < 4)
130
0
      return SC_ERROR_BUFFER_TOO_SMALL;
131
0
    to_base64(i, out, 3 - len);
132
0
    out += 4;
133
0
    outlen -= 4;
134
0
    chars += 4;
135
0
  }
136
0
  if (chars && linelength > 0) {
137
0
    if (outlen < 1)
138
0
      return SC_ERROR_BUFFER_TOO_SMALL;
139
0
    *out = '\n';
140
0
    out++;
141
0
    outlen--;
142
0
  }
143
0
  if (outlen < 1)
144
0
    return SC_ERROR_BUFFER_TOO_SMALL;
145
0
  *out = 0;
146
147
0
  return 0;
148
0
}
149
150
int sc_base64_decode(const char *in, u8 *out, size_t outlen)
151
0
{
152
0
  int len = 0, r = 0;
153
0
  size_t skip = 0;
154
0
  unsigned int i = 0;
155
156
0
  while ((r = from_base64(in, &i, &skip)) > 0) {
157
0
    int finished = 0, s = 16;
158
159
0
    if (r < 3)
160
0
      finished = 1;
161
0
    while (r--) {
162
0
      if (outlen <= 0)
163
0
        return SC_ERROR_BUFFER_TOO_SMALL;
164
0
      *out++ = i >> s;
165
0
      s -= 8;
166
0
      outlen--;
167
0
      len++;
168
0
    }
169
0
    in += skip;
170
0
    if (finished || *in == 0)
171
0
      return len;
172
0
  }
173
0
  if (r == 0)
174
0
    return len;
175
0
  return SC_ERROR_INVALID_ARGUMENTS;
176
0
}