blob: 41706106424697d5b41ce96f3848a7f4f1aa42f5 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jens Wiklander817466c2018-05-22 13:49:31 +020018 */
19
Jerome Forissier79013242021-07-28 10:24:04 +020020#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020021
22#if defined(MBEDTLS_BASE64_C)
23
24#include "mbedtls/base64.h"
Jerome Forissier039e02d2022-08-09 17:10:15 +020025#include "constant_time_internal.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020026
27#include <stdint.h>
28
29#if defined(MBEDTLS_SELF_TEST)
30#include <string.h>
Jens Wiklander817466c2018-05-22 13:49:31 +020031#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020032#endif /* MBEDTLS_SELF_TEST */
33
Jens Wiklander32b31802023-10-06 16:59:46 +020034#define BASE64_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */
Jens Wiklander817466c2018-05-22 13:49:31 +020035
36/*
37 * Encode a buffer into base64 format
38 */
Jens Wiklander32b31802023-10-06 16:59:46 +020039int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
40 const unsigned char *src, size_t slen)
Jens Wiklander817466c2018-05-22 13:49:31 +020041{
42 size_t i, n;
43 int C1, C2, C3;
44 unsigned char *p;
45
Jens Wiklander32b31802023-10-06 16:59:46 +020046 if (slen == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +020047 *olen = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +020048 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +020049 }
50
Jens Wiklander32b31802023-10-06 16:59:46 +020051 n = slen / 3 + (slen % 3 != 0);
Jens Wiklander817466c2018-05-22 13:49:31 +020052
Jens Wiklander32b31802023-10-06 16:59:46 +020053 if (n > (BASE64_SIZE_T_MAX - 1) / 4) {
Jens Wiklander817466c2018-05-22 13:49:31 +020054 *olen = BASE64_SIZE_T_MAX;
Jens Wiklander32b31802023-10-06 16:59:46 +020055 return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
Jens Wiklander817466c2018-05-22 13:49:31 +020056 }
57
58 n *= 4;
59
Jens Wiklander32b31802023-10-06 16:59:46 +020060 if ((dlen < n + 1) || (NULL == dst)) {
Jens Wiklander817466c2018-05-22 13:49:31 +020061 *olen = n + 1;
Jens Wiklander32b31802023-10-06 16:59:46 +020062 return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
Jens Wiklander817466c2018-05-22 13:49:31 +020063 }
64
Jens Wiklander32b31802023-10-06 16:59:46 +020065 n = (slen / 3) * 3;
Jens Wiklander817466c2018-05-22 13:49:31 +020066
Jens Wiklander32b31802023-10-06 16:59:46 +020067 for (i = 0, p = dst; i < n; i += 3) {
Jens Wiklander817466c2018-05-22 13:49:31 +020068 C1 = *src++;
69 C2 = *src++;
70 C3 = *src++;
71
Jens Wiklander32b31802023-10-06 16:59:46 +020072 *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);
73 *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4))
74 & 0x3F);
75 *p++ = mbedtls_ct_base64_enc_char((((C2 & 15) << 2) + (C3 >> 6))
76 & 0x3F);
77 *p++ = mbedtls_ct_base64_enc_char(C3 & 0x3F);
Jens Wiklander817466c2018-05-22 13:49:31 +020078 }
79
Jens Wiklander32b31802023-10-06 16:59:46 +020080 if (i < slen) {
Jens Wiklander817466c2018-05-22 13:49:31 +020081 C1 = *src++;
Jens Wiklander32b31802023-10-06 16:59:46 +020082 C2 = ((i + 1) < slen) ? *src++ : 0;
Jens Wiklander817466c2018-05-22 13:49:31 +020083
Jens Wiklander32b31802023-10-06 16:59:46 +020084 *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);
85 *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4))
86 & 0x3F);
Jens Wiklander817466c2018-05-22 13:49:31 +020087
Jens Wiklander32b31802023-10-06 16:59:46 +020088 if ((i + 1) < slen) {
89 *p++ = mbedtls_ct_base64_enc_char(((C2 & 15) << 2) & 0x3F);
90 } else {
91 *p++ = '=';
92 }
Jens Wiklander817466c2018-05-22 13:49:31 +020093
94 *p++ = '=';
95 }
96
97 *olen = p - dst;
98 *p = 0;
99
Jens Wiklander32b31802023-10-06 16:59:46 +0200100 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200101}
102
103/*
104 * Decode a base64-formatted buffer
105 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200106int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen,
107 const unsigned char *src, size_t slen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200108{
Jerome Forissier039e02d2022-08-09 17:10:15 +0200109 size_t i; /* index in source */
110 size_t n; /* number of digits or trailing = in source */
111 uint32_t x; /* value accumulator */
112 unsigned accumulated_digits = 0;
113 unsigned equals = 0;
114 int spaces_present = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200115 unsigned char *p;
116
117 /* First pass: check for validity and get output length */
Jens Wiklander32b31802023-10-06 16:59:46 +0200118 for (i = n = 0; i < slen; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200119 /* Skip spaces before checking for EOL */
Jerome Forissier039e02d2022-08-09 17:10:15 +0200120 spaces_present = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200121 while (i < slen && src[i] == ' ') {
Jens Wiklander817466c2018-05-22 13:49:31 +0200122 ++i;
Jerome Forissier039e02d2022-08-09 17:10:15 +0200123 spaces_present = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200124 }
125
126 /* Spaces at end of buffer are OK */
Jens Wiklander32b31802023-10-06 16:59:46 +0200127 if (i == slen) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200128 break;
Jens Wiklander32b31802023-10-06 16:59:46 +0200129 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200130
Jens Wiklander32b31802023-10-06 16:59:46 +0200131 if ((slen - i) >= 2 &&
132 src[i] == '\r' && src[i + 1] == '\n') {
Jens Wiklander817466c2018-05-22 13:49:31 +0200133 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +0200134 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200135
Jens Wiklander32b31802023-10-06 16:59:46 +0200136 if (src[i] == '\n') {
Jens Wiklander817466c2018-05-22 13:49:31 +0200137 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +0200138 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200139
140 /* Space inside a line is an error */
Jens Wiklander32b31802023-10-06 16:59:46 +0200141 if (spaces_present) {
142 return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
Jerome Forissier039e02d2022-08-09 17:10:15 +0200143 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200144
145 if (src[i] > 127) {
146 return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
147 }
148
149 if (src[i] == '=') {
150 if (++equals > 2) {
151 return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
152 }
153 } else {
154 if (equals != 0) {
155 return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
156 }
157 if (mbedtls_ct_base64_dec_value(src[i]) < 0) {
158 return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
159 }
Jerome Forissier039e02d2022-08-09 17:10:15 +0200160 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200161 n++;
162 }
163
Jens Wiklander32b31802023-10-06 16:59:46 +0200164 if (n == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200165 *olen = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200166 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200167 }
168
169 /* The following expression is to calculate the following formula without
170 * risk of integer overflow in n:
171 * n = ( ( n * 6 ) + 7 ) >> 3;
172 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200173 n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3);
Jerome Forissier039e02d2022-08-09 17:10:15 +0200174 n -= equals;
Jens Wiklander817466c2018-05-22 13:49:31 +0200175
Jens Wiklander32b31802023-10-06 16:59:46 +0200176 if (dst == NULL || dlen < n) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200177 *olen = n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200178 return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200179 }
180
Jerome Forissier039e02d2022-08-09 17:10:15 +0200181 equals = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200182 for (x = 0, p = dst; i > 0; i--, src++) {
183 if (*src == '\r' || *src == '\n' || *src == ' ') {
Jens Wiklander817466c2018-05-22 13:49:31 +0200184 continue;
Jens Wiklander32b31802023-10-06 16:59:46 +0200185 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200186
Jerome Forissier039e02d2022-08-09 17:10:15 +0200187 x = x << 6;
Jens Wiklander32b31802023-10-06 16:59:46 +0200188 if (*src == '=') {
Jerome Forissier039e02d2022-08-09 17:10:15 +0200189 ++equals;
Jens Wiklander32b31802023-10-06 16:59:46 +0200190 } else {
191 x |= mbedtls_ct_base64_dec_value(*src);
192 }
Jerome Forissier79013242021-07-28 10:24:04 +0200193
Jens Wiklander32b31802023-10-06 16:59:46 +0200194 if (++accumulated_digits == 4) {
Jerome Forissier039e02d2022-08-09 17:10:15 +0200195 accumulated_digits = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200196 *p++ = MBEDTLS_BYTE_2(x);
197 if (equals <= 1) {
198 *p++ = MBEDTLS_BYTE_1(x);
199 }
200 if (equals <= 0) {
201 *p++ = MBEDTLS_BYTE_0(x);
202 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200203 }
204 }
205
206 *olen = p - dst;
207
Jens Wiklander32b31802023-10-06 16:59:46 +0200208 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200209}
210
211#if defined(MBEDTLS_SELF_TEST)
212
213static const unsigned char base64_test_dec[64] =
214{
215 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
216 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
217 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
218 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
219 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
220 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
221 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
222 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
223};
224
225static const unsigned char base64_test_enc[] =
226 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
227 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
228
229/*
230 * Checkup routine
231 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200232int mbedtls_base64_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200233{
234 size_t len;
235 const unsigned char *src;
236 unsigned char buffer[128];
237
Jens Wiklander32b31802023-10-06 16:59:46 +0200238 if (verbose != 0) {
239 mbedtls_printf(" Base64 encoding test: ");
240 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200241
242 src = base64_test_dec;
243
Jens Wiklander32b31802023-10-06 16:59:46 +0200244 if (mbedtls_base64_encode(buffer, sizeof(buffer), &len, src, 64) != 0 ||
245 memcmp(base64_test_enc, buffer, 88) != 0) {
246 if (verbose != 0) {
247 mbedtls_printf("failed\n");
248 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200249
Jens Wiklander32b31802023-10-06 16:59:46 +0200250 return 1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200251 }
252
Jens Wiklander32b31802023-10-06 16:59:46 +0200253 if (verbose != 0) {
254 mbedtls_printf("passed\n Base64 decoding test: ");
255 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200256
257 src = base64_test_enc;
258
Jens Wiklander32b31802023-10-06 16:59:46 +0200259 if (mbedtls_base64_decode(buffer, sizeof(buffer), &len, src, 88) != 0 ||
260 memcmp(base64_test_dec, buffer, 64) != 0) {
261 if (verbose != 0) {
262 mbedtls_printf("failed\n");
263 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200264
Jens Wiklander32b31802023-10-06 16:59:46 +0200265 return 1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200266 }
267
Jens Wiklander32b31802023-10-06 16:59:46 +0200268 if (verbose != 0) {
269 mbedtls_printf("passed\n\n");
270 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200271
Jens Wiklander32b31802023-10-06 16:59:46 +0200272 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200273}
274
275#endif /* MBEDTLS_SELF_TEST */
276
277#endif /* MBEDTLS_BASE64_C */