]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/util/base64.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / spdk / lib / util / base64.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright(c) Intel Corporation. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "spdk/stdinc.h"
35 #include "spdk/endian.h"
36 #include "spdk/base64.h"
37
38 #define BASE64_ENC_BITMASK 0x3FUL
39 #define BASE64_PADDING_CHAR '='
40
41 static const char base64_enc_table[] =
42 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
43 "abcdefghijklmnopqrstuvwxyz"
44 "0123456789+/";
45
46 static const char base64_urfsafe_enc_table[] =
47 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
48 "abcdefghijklmnopqrstuvwxyz"
49 "0123456789-_";
50
51 static const uint8_t
52 base64_dec_table[] = {
53 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
54 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
55 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
56 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
57 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
58 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
59 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
60 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
61 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
62 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
63 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
64 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
65 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
66 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
67 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69 };
70
71 static const uint8_t
72 base64_urlsafe_dec_table[] = {
73 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
75 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255,
76 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
77 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
78 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63,
79 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
80 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
81 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
82 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
83 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
84 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
85 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
86 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
87 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
88 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
89 };
90
91 static int
92 _spdk_base64_encode(char *dst, const char *enc_table, const void *src, size_t src_len)
93 {
94 uint32_t raw_u32;
95
96 if (!dst || !src || src_len <= 0) {
97 return -EINVAL;
98 }
99
100 while (src_len >= 4) {
101 raw_u32 = from_be32(src);
102
103 *dst++ = enc_table[(raw_u32 >> 26) & BASE64_ENC_BITMASK];
104 *dst++ = enc_table[(raw_u32 >> 20) & BASE64_ENC_BITMASK];
105 *dst++ = enc_table[(raw_u32 >> 14) & BASE64_ENC_BITMASK];
106 *dst++ = enc_table[(raw_u32 >> 8) & BASE64_ENC_BITMASK];
107
108 src_len -= 3;
109 src += 3;
110 }
111
112 if (src_len == 0) {
113 goto out;
114 }
115
116 raw_u32 = 0;
117 memcpy(&raw_u32, src, src_len);
118 raw_u32 = from_be32(&raw_u32);
119
120 *dst++ = enc_table[(raw_u32 >> 26) & BASE64_ENC_BITMASK];
121 *dst++ = enc_table[(raw_u32 >> 20) & BASE64_ENC_BITMASK];
122 *dst++ = (src_len >= 2) ? enc_table[(raw_u32 >> 14) & BASE64_ENC_BITMASK] : BASE64_PADDING_CHAR;
123 *dst++ = (src_len == 3) ? enc_table[(raw_u32 >> 8) & BASE64_ENC_BITMASK] : BASE64_PADDING_CHAR;
124
125 out:
126 *dst = '\0';
127
128 return 0;
129 }
130
131 int
132 spdk_base64_encode(char *dst, const void *src, size_t src_len)
133 {
134 return _spdk_base64_encode(dst, base64_enc_table, src, src_len);
135 }
136
137 int
138 spdk_base64_urlsafe_encode(char *dst, const void *src, size_t src_len)
139 {
140 return _spdk_base64_encode(dst, base64_urfsafe_enc_table, src, src_len);
141 }
142
143 static int
144 _spdk_base64_decode(void *dst, size_t *_dst_len, const uint8_t *dec_table, const char *src)
145 {
146 size_t src_strlen, dst_len;
147 size_t tail_len = 0;
148 const uint8_t *src_in;
149 uint32_t tmp[4];
150 int i;
151
152 if (!dst || !src) {
153 return -EINVAL;
154 }
155
156 src_strlen = strlen(src);
157
158 /* strlen of src should be 4n */
159 if (src_strlen == 0 || src_strlen % 4 != 0) {
160 return -EINVAL;
161 }
162
163 /* Consider Base64 padding, it at most has 2 padding characters. */
164 for (i = 0; i < 2; i++) {
165 if (src[src_strlen - 1] != BASE64_PADDING_CHAR) {
166 break;
167 }
168 src_strlen--;
169 }
170
171 /* strlen of src without padding shouldn't be 4n+1 */
172 if (src_strlen == 0 || src_strlen % 4 == 1) {
173 return -EINVAL;
174 }
175
176 dst_len = spdk_base64_get_decoded_len(src_strlen);
177 src_in = (const uint8_t *) src;
178
179 /* space of dst can be used by to_be32 */
180 while (src_strlen > 4) {
181 tmp[0] = dec_table[*src_in++];
182 tmp[1] = dec_table[*src_in++];
183 tmp[2] = dec_table[*src_in++];
184 tmp[3] = dec_table[*src_in++];
185
186 if (tmp[0] == 255 || tmp[1] == 255 || tmp[2] == 255 || tmp[3] == 255) {
187 return -EINVAL;
188 }
189
190 to_be32(dst, tmp[3] << 8 | tmp[2] << 14 | tmp[1] << 20 | tmp[0] << 26);
191
192 dst += 3;
193 src_strlen -= 4;
194 }
195
196 /* space of dst is not enough to be used by to_be32 */
197 tmp[0] = dec_table[src_in[0]];
198 tmp[1] = dec_table[src_in[1]];
199 tmp[2] = (src_strlen >= 3) ? dec_table[src_in[2]] : 0;
200 tmp[3] = (src_strlen == 4) ? dec_table[src_in[3]] : 0;
201 tail_len = src_strlen - 1;
202
203 if (tmp[0] == 255 || tmp[1] == 255 || tmp[2] == 255 || tmp[3] == 255) {
204 return -EINVAL;
205 }
206
207 to_be32(&tmp[3], tmp[3] << 8 | tmp[2] << 14 | tmp[1] << 20 | tmp[0] << 26);
208 memcpy(dst, (uint8_t *)&tmp[3], tail_len);
209
210 /* Assign pointers */
211 if (_dst_len) {
212 *_dst_len = dst_len;
213 }
214
215 return 0;
216 }
217
218 int
219 spdk_base64_decode(void *dst, size_t *dst_len, const char *src)
220 {
221 return _spdk_base64_decode(dst, dst_len, base64_dec_table, src);
222 }
223
224 int
225 spdk_base64_urlsafe_decode(void *dst, size_t *dst_len, const char *src)
226 {
227 return _spdk_base64_decode(dst, dst_len, base64_urlsafe_dec_table, src);
228 }