File: base64.c

package info (click to toggle)
optee-os 4.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 31,560 kB
  • sloc: ansic: 441,914; asm: 12,903; python: 3,719; makefile: 1,676; sh: 238
file content (128 lines) | stat: -rw-r--r-- 2,351 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2020, Linaro Limited
 * Copyright (c) 2014, STMicroelectronics International N.V.
 */
#include "base64.h"

static const char base64_table[] =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

size_t base64_enc_len(size_t size)
{
	return 4 * ((size + 2) / 3) + 1;
}

bool base64_enc(const void *data, size_t dlen, char *buf, size_t *blen)
{
	size_t n = 0;
	size_t boffs = 0;
	const unsigned char *d = data;

	n = base64_enc_len(dlen);
	if (*blen < n) {
		*blen = n;
		return false;
	}

	for (n = 0; n < dlen; n += 3) {
		uint32_t igrp;

		igrp = d[n];
		igrp <<= 8;

		if ((n + 1) < dlen)
			igrp |= d[n + 1];
		igrp <<= 8;

		if ((n + 2) < dlen)
			igrp |= d[n + 2];

		buf[boffs] = base64_table[(igrp >> 18) & 0x3f];
		buf[boffs + 1] = base64_table[(igrp >> 12) & 0x3f];
		if ((n + 1) < dlen)
			buf[boffs + 2] = base64_table[(igrp >> 6) & 0x3f];
		else
			buf[boffs + 2] = '=';
		if ((n + 2) < dlen)
			buf[boffs + 3] = base64_table[igrp & 0x3f];
		else
			buf[boffs + 3] = '=';

		boffs += 4;
	}
	buf[boffs++] = '\0';

	*blen = boffs;
	return true;
}

static bool get_idx(char ch, uint8_t *idx)
{
	size_t n = 0;

	for (n = 0; base64_table[n] != '\0'; n++) {
		if (ch == base64_table[n]) {
			*idx = n;
			return true;
		}
	}
	return false;
}

bool base64_dec(const char *data, size_t size, void *buf, size_t *blen)
{
	bool ret = false;
	size_t n = 0;
	uint8_t idx = 0;
	uint8_t *b = buf;
	size_t m = 0;
	size_t s = 0;
	uint8_t byte = 0;

	for (n = 0; n < size && data[n] != '\0'; n++) {
		if (data[n] == '=')
			break;	/* Reached pad characters, we're done */

		if (!get_idx(data[n], &idx))
			continue;

		switch (s) {
		case 0:
			byte = idx << 2;
			s++;
			break;
		case 1:
			if (b && m < *blen)
				b[m] = byte | (idx >> 4);
			m++;
			byte = (idx & 0xf) << 4;
			s++;
			break;
		case 2:
			if (b && m < *blen)
				b[m] = byte | (idx >> 2);
			m++;
			byte = (idx & 0x3) << 6;
			s++;
			break;
		case 3:
			if (b && m < *blen)
				b[m] = byte | idx;
			m++;
			s = 0;
			break;
		default:
			return false;	/* "Can't happen" */
		}
	}

	/*
	 * We don't detect if input was bad, but that's OK with the spec.
	 * We expect that each fully extracted byte is stored in output buffer.
	 */
	ret = (!m && !*blen) || (b && (m <= *blen));
	*blen = m;

	return ret;
}