embox

Форк
0
198 строк · 4.6 Кб
1
/**
2
 * @file
3
 * @brief
4
 *
5
 * @date 22.03.13
6
 * @author Ilia Vaprol
7
 */
8

9
#include <errno.h>
10
#include <stddef.h>
11

12
#include <lib/crypt/b64.h>
13

14

15
struct b64_char {
16
	unsigned char c1,
17
		c2,
18
		c3;
19
};
20

21
struct b64_b {
22
	unsigned char b1:6,
23
		b2:6,
24
		b3:6,
25
		b4:6;
26
};
27

28
static const char b2char[64] = {
29
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
30
	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
31
	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
32
	'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
33
	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
34
	'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
35
	'w', 'x', 'y', 'z', '0', '1', '2', '3',
36
	'4', '5', '6', '7', '8', '9', '+', '/'
37
};
38

39
static const char char2b[256] = {
40
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
41
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
42
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, -1, 63,
43
	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
44
	-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
45
	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
46
	-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
47
	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
48
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
49
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
50
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
51
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
52
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
53
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
55
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
56
};
57

58
#define B_TO_CHAR(b, out) \
59
	out = b2char[(b)]
60

61
#define CHAR_TO_B(ch, out) \
62
	do { \
63
		char b = char2b[(unsigned char)(ch)]; \
64
		if (b == -1) { \
65
			return -EINVAL; \
66
		} \
67
		out = (unsigned char)b; \
68
	} while (0)
69

70
#define MAKE_B1(b64c) \
71
	(b64c.c1 >> 2)
72
#define MAKE_B2(b64c) \
73
	(((b64c.c1 & 0x03) << 4) | (b64c.c2 >> 4))
74
#define MAKE_B3(b64c) \
75
	(((b64c.c2 & 0x0F) << 2) | (b64c.c3 >> 6))
76
#define MAKE_B4(b64c) \
77
	(b64c.c3 & 0x3F)
78

79
#define MAKE_CHAR1(b64b) \
80
	((b64b.b1 << 2) | (b64b.b2 >> 4))
81
#define MAKE_CHAR2(b64b) \
82
	(((b64b.b2 & 0x0F) << 4) | (b64b.b3 >> 2))
83
#define MAKE_CHAR3(b64b) \
84
	(((b64b.b3 & 0x03) << 6) | b64b.b4)
85

86
size_t b64_coded_len(const char *plain, size_t plain_sz) {
87
	return ((plain_sz + 2) / 3) * 4;
88
}
89

90
size_t b64_plain_len(const char *coded, size_t coded_sz) {
91
	size_t size = (coded_sz / 4) * 3;
92
	if (*(coded + coded_sz - 1) == '=') size -= 1;
93
	if (*(coded + coded_sz - 2) == '=') size -= 1;
94
	return size;
95
}
96

97
int b64_encode(const char *plain, size_t plain_sz,
98
		char *buff, size_t buff_sz, size_t *out_coded_sz) {
99
	size_t i;
100
	char *out;
101
	struct b64_char b64c;
102

103
	if ((plain == NULL) || (buff == NULL)
104
			|| (out_coded_sz == NULL)) {
105
		return -EINVAL;
106
	}
107

108
	if (b64_coded_len(plain, plain_sz) > buff_sz) {
109
		return -ENOMEM;
110
	}
111

112
	out = buff;
113

114
	for (i = 2; i < plain_sz; i += 3) {
115
		b64c.c1 = (unsigned char)*plain++;
116
		b64c.c2 = (unsigned char)*plain++;
117
		b64c.c3 = (unsigned char)*plain++;
118

119
		B_TO_CHAR(MAKE_B1(b64c), *out++);
120
		B_TO_CHAR(MAKE_B2(b64c), *out++);
121
		B_TO_CHAR(MAKE_B3(b64c), *out++);
122
		B_TO_CHAR(MAKE_B4(b64c), *out++);
123
	}
124

125
	if (i == plain_sz) {
126
		b64c.c1 = (unsigned char)*plain++;
127
		b64c.c2 = (unsigned char)*plain++;
128
		b64c.c3 = 0;
129

130
		B_TO_CHAR(MAKE_B1(b64c), *out++);
131
		B_TO_CHAR(MAKE_B2(b64c), *out++);
132
		B_TO_CHAR(MAKE_B3(b64c), *out++);
133
		*out++ = '=';
134
	}
135
	else if (i - 1 == plain_sz) {
136
		b64c.c1 = (unsigned char)*plain++;
137
		b64c.c2 = 0;
138

139
		B_TO_CHAR(MAKE_B1(b64c), *out++);
140
		B_TO_CHAR(MAKE_B2(b64c), *out++);
141
		*out++ = '=';
142
		*out++ = '=';
143
	}
144

145
	*out_coded_sz = out - buff;
146

147
	return 0;
148
}
149

150
int b64_decode(const char *coded, size_t coded_sz,
151
		char *buff, size_t buff_sz, size_t *out_plain_sz) {
152
	size_t i;
153
	char *out;
154
	struct b64_b b64b;
155

156
	if ((coded == NULL) || (buff == NULL) || (coded_sz % 4 != 0)
157
			|| (out_plain_sz == NULL)) {
158
		return -EINVAL;
159
	}
160

161
	if (coded_sz == 0) {
162
		*out_plain_sz = 0;
163
		return 0;
164
	}
165

166
	if (b64_plain_len(coded, coded_sz) > buff_sz) {
167
		return -ENOMEM;
168
	}
169

170
	out = buff;
171

172
	for (i = 7; i < coded_sz; i += 4) {
173
		CHAR_TO_B(*coded++, b64b.b1);
174
		CHAR_TO_B(*coded++, b64b.b2);
175
		CHAR_TO_B(*coded++, b64b.b3);
176
		CHAR_TO_B(*coded++, b64b.b4);
177

178
		*out++ = MAKE_CHAR1(b64b);
179
		*out++ = MAKE_CHAR2(b64b);
180
		*out++ = MAKE_CHAR3(b64b);
181
	}
182

183
	CHAR_TO_B(*coded++, b64b.b1);
184
	CHAR_TO_B(*coded++, b64b.b2);
185
	*out++ = MAKE_CHAR1(b64b);
186
	if (*coded != '=') {
187
		CHAR_TO_B(*coded++, b64b.b3);
188
		*out++ = MAKE_CHAR2(b64b);
189
		if (*coded != '=') {
190
			CHAR_TO_B(*coded++, b64b.b4);
191
			*out++ = MAKE_CHAR3(b64b);
192
		}
193
	}
194

195
	*out_plain_sz = out - buff;
196

197
	return 0;
198
}
199

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.