blob: 17a283406868b6207c8fad7583d5c184803650d7 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
46
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000048#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020049#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020051#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000052
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#if defined(MBEDTLS_BASE64_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000054
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000055#include "mbedtls/base64.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000056
Manuel Pégourié-Gonnard93866642015-06-22 19:21:23 +020057#include <stdint.h>
Paul Bakker5c2364c2012-10-01 14:41:15 +000058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#if defined(MBEDTLS_SELF_TEST)
Rich Evans00ab4702015-02-06 13:43:58 +000060#include <string.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020061#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000062#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010063#else
Rich Evans00ab4702015-02-06 13:43:58 +000064#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#define mbedtls_printf printf
66#endif /* MBEDTLS_PLATFORM_C */
67#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010068
Paul Bakker5121ce52009-01-03 21:22:43 +000069static const unsigned char base64_enc_map[64] =
70{
71 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
72 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
73 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
74 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
75 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
76 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
77 '8', '9', '+', '/'
78};
79
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +010080#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
81
Paul Elliottf13a47b2021-02-25 12:28:49 +000082/*
Paul Elliotte8ee0f12021-03-01 19:15:43 +000083 * Constant flow conditional assignment to unsigned char
Paul Elliottcd65b622021-03-04 14:34:50 +000084 */
85static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
86 unsigned char condition )
Paul Elliott738d2312021-02-05 17:49:23 +000087{
Paul Elliott6f69d4c2021-03-03 15:31:17 +000088 /* MSVC has a warning about unary minus on unsigned integer types,
89 * but this is well-defined and precisely what we want to do here. */
90#if defined(_MSC_VER)
91#pragma warning( push )
92#pragma warning( disable : 4146 )
93#endif
Paul Elliott738d2312021-02-05 17:49:23 +000094
Paul Elliott48236242021-03-03 17:21:17 +000095 /* Generate bitmask from condition, mask will either be 0xFF or 0 */
Paul Elliott490c5d42021-03-03 17:11:32 +000096 unsigned char mask = ( condition | -condition );
97 mask >>= 7;
98 mask = -mask;
Paul Elliott6f69d4c2021-03-03 15:31:17 +000099
100#if defined(_MSC_VER)
101#pragma warning( pop )
102#endif
103
104 *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
Paul Elliott738d2312021-02-05 17:49:23 +0000105}
106
107/*
Paul Elliottf13a47b2021-02-25 12:28:49 +0000108 * Constant flow check for equality
Paul Elliottcd65b622021-03-04 14:34:50 +0000109 */
110static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
Paul Elliott738d2312021-02-05 17:49:23 +0000111{
Paul Elliott86cb9282021-03-01 17:49:42 +0000112 size_t difference = in_a ^ in_b;
Paul Elliott738d2312021-02-05 17:49:23 +0000113
Paul Elliottf13a47b2021-02-25 12:28:49 +0000114 /* MSVC has a warning about unary minus on unsigned integer types,
115 * but this is well-defined and precisely what we want to do here. */
116#if defined(_MSC_VER)
117#pragma warning( push )
118#pragma warning( disable : 4146 )
119#endif
120
Paul Elliott738d2312021-02-05 17:49:23 +0000121 difference |= -difference;
Paul Elliottf13a47b2021-02-25 12:28:49 +0000122
123#if defined(_MSC_VER)
124#pragma warning( pop )
125#endif
126
Paul Elliott86cb9282021-03-01 17:49:42 +0000127 /* cope with the varying size of size_t per platform */
128 difference >>= ( sizeof( difference ) * 8 - 1 );
129
Paul Elliott738d2312021-02-05 17:49:23 +0000130 return (unsigned char) ( 1 ^ difference );
131}
132
133/*
Paul Elliottf13a47b2021-02-25 12:28:49 +0000134 * Constant flow lookup into table.
Paul Elliottcd65b622021-03-04 14:34:50 +0000135 */
136static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
137 const size_t table_size, const size_t table_index )
Paul Elliott738d2312021-02-05 17:49:23 +0000138{
139 size_t i;
140 unsigned char result = 0;
141
142 for( i = 0; i < table_size; ++i )
143 {
Paul Elliottcd65b622021-03-04 14:34:50 +0000144 mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
Paul Elliott738d2312021-02-05 17:49:23 +0000145 }
146
147 return result;
148}
149
Gilles Peskinef4a0a272021-07-28 13:54:02 +0200150/* Return 0xff if low <= c <= high, 0 otherwise.
151 *
152 * Constant flow with respect to c.
153 */
154static unsigned char mask_of_range( unsigned char low, unsigned char high,
155 unsigned char c )
156{
157 unsigned low_mask = ( c - low ) >> 8;
158 unsigned high_mask = ( c - high - 1 ) >> 8;
159 return( ~low_mask & high_mask & 0xff );
160}
161
Paul Bakker5121ce52009-01-03 21:22:43 +0000162/*
163 * Encode a buffer into base64 format
164 */
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100165int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
Paul Bakker23986e52011-04-24 08:57:21 +0000166 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000167{
Paul Bakker23986e52011-04-24 08:57:21 +0000168 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000169 int C1, C2, C3;
170 unsigned char *p;
171
172 if( slen == 0 )
Manuel Pégourié-Gonnard65fc6a82015-01-28 16:49:26 +0000173 {
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100174 *olen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000175 return( 0 );
Manuel Pégourié-Gonnard65fc6a82015-01-28 16:49:26 +0000176 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000177
Manuel Pégourié-Gonnard0aa45c22015-09-30 16:30:28 +0200178 n = slen / 3 + ( slen % 3 != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000179
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100180 if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181 {
Manuel Pégourié-Gonnard2d708342015-10-05 15:23:11 +0100182 *olen = BASE64_SIZE_T_MAX;
Manuel Pégourié-Gonnard0aa45c22015-09-30 16:30:28 +0200183 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000184 }
185
Manuel Pégourié-Gonnard0aa45c22015-09-30 16:30:28 +0200186 n *= 4;
187
Janos Follath98e28a72016-05-31 14:03:54 +0100188 if( ( dlen < n + 1 ) || ( NULL == dst ) )
Paul Bakker5121ce52009-01-03 21:22:43 +0000189 {
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100190 *olen = n + 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000192 }
193
Paul Bakker66d5d072014-06-17 16:39:18 +0200194 n = ( slen / 3 ) * 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000195
196 for( i = 0, p = dst; i < n; i += 3 )
197 {
198 C1 = *src++;
199 C2 = *src++;
200 C3 = *src++;
201
Paul Elliott738d2312021-02-05 17:49:23 +0000202 *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
203 ( ( C1 >> 2 ) & 0x3F ) );
204
205 *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
206 ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
207
208 *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
209 ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
210
211 *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
212 ( C3 & 0x3F ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000213 }
214
215 if( i < slen )
216 {
217 C1 = *src++;
Paul Bakker66d5d072014-06-17 16:39:18 +0200218 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000219
Paul Elliott738d2312021-02-05 17:49:23 +0000220 *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
221 ( ( C1 >> 2 ) & 0x3F ) );
222
223 *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
224 ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
Paul Bakker66d5d072014-06-17 16:39:18 +0200226 if( ( i + 1 ) < slen )
Paul Elliott738d2312021-02-05 17:49:23 +0000227 *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
228 ( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000229 else *p++ = '=';
230
231 *p++ = '=';
232 }
233
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100234 *olen = p - dst;
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 *p = 0;
236
237 return( 0 );
238}
239
Gilles Peskinef4a0a272021-07-28 13:54:02 +0200240/* Given a Base64 digit, return its value.
241 * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
242 * return -1.
243 *
244 * The implementation assumes that letters are consecutive (e.g. ASCII
245 * but not EBCDIC).
246 *
247 * The implementation is constant-flow (no branch or memory access depending
248 * on the value of c) unless the compiler inlines and optimizes a specific
249 * access.
250 */
251static signed char dec_value( unsigned char c )
252{
253 unsigned char val = 0;
254 /* For each range of digits, if c is in that range, mask val with
255 * the corresponding value. Since c can only be in a single range,
256 * only at most one masking will change val. Set val to one plus
257 * the desired value so that it stays 0 if c is in none of the ranges. */
258 val |= mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 );
259 val |= mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
260 val |= mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
261 val |= mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
262 val |= mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
263 /* At this point, val is 0 if c is an invalid digit and v+1 if c is
264 * a digit with the value v. */
265 return( val - 1 );
266}
267
Paul Bakker5121ce52009-01-03 21:22:43 +0000268/*
269 * Decode a base64-formatted buffer
270 */
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100271int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
Paul Bakker23986e52011-04-24 08:57:21 +0000272 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000273{
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200274 size_t i; /* index in source */
275 size_t n; /* number of digits or trailing = in source */
276 uint32_t x; /* value accumulator */
277 unsigned equals = 0;
278 int spaces_present = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000279 unsigned char *p;
280
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200281 /* First pass: check for validity and get output length */
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200282 for( i = n = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000283 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200284 /* Skip spaces before checking for EOL */
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200285 spaces_present = 0;
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200286 while( i < slen && src[i] == ' ' )
287 {
288 ++i;
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200289 spaces_present = 1;
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200290 }
291
292 /* Spaces at end of buffer are OK */
293 if( i == slen )
294 break;
295
Paul Bakker5121ce52009-01-03 21:22:43 +0000296 if( ( slen - i ) >= 2 &&
297 src[i] == '\r' && src[i + 1] == '\n' )
298 continue;
299
300 if( src[i] == '\n' )
301 continue;
302
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200303 /* Space inside a line is an error */
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200304 if( spaces_present )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200306
Gilles Peskinea47fdcf2021-07-28 11:33:04 +0200307 if( src[i] > 127 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000309
Gilles Peskinea47fdcf2021-07-28 11:33:04 +0200310 if( src[i] == '=' )
311 {
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200312 if( ++equals > 2 )
Gilles Peskinea47fdcf2021-07-28 11:33:04 +0200313 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
314 }
315 else
316 {
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200317 if( equals != 0 )
Gilles Peskinea47fdcf2021-07-28 11:33:04 +0200318 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
Gilles Peskinef4a0a272021-07-28 13:54:02 +0200319 if( dec_value( src[i] ) < 0 )
Gilles Peskinea47fdcf2021-07-28 11:33:04 +0200320 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
321 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000322 n++;
323 }
324
325 if( n == 0 )
Simon Butchera45aa132015-10-05 00:26:36 +0100326 {
327 *olen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000328 return( 0 );
Simon Butchera45aa132015-10-05 00:26:36 +0100329 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000330
Simon Butchera29c5e9e2017-02-02 08:46:53 +0000331 /* The following expression is to calculate the following formula without
332 * risk of integer overflow in n:
333 * n = ( ( n * 6 ) + 7 ) >> 3;
334 */
Andres AG4623d832017-01-18 17:21:03 +0000335 n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200336 n -= equals;
Paul Bakker5121ce52009-01-03 21:22:43 +0000337
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100338 if( dst == NULL || dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000339 {
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100340 *olen = n;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000342 }
343
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200344 equals = 0;
345 for( n = x = 0, p = dst; i > 0; i--, src++ )
346 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200347 if( *src == '\r' || *src == '\n' || *src == ' ' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000348 continue;
349
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200350 x = x << 6;
Gilles Peskinea47fdcf2021-07-28 11:33:04 +0200351 if( *src == '=' )
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200352 ++equals;
Gilles Peskinea47fdcf2021-07-28 11:33:04 +0200353 else
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200354 x |= dec_value( *src );
Paul Bakker5121ce52009-01-03 21:22:43 +0000355
356 if( ++n == 4 )
357 {
358 n = 0;
Gilles Peskineea96b3a2021-07-28 14:20:06 +0200359 *p++ = (unsigned char)( x >> 16 );
360 if( equals <= 1 ) *p++ = (unsigned char)( x >> 8 );
361 if( equals <= 0 ) *p++ = (unsigned char)( x );
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 }
363 }
364
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100365 *olen = p - dst;
Paul Bakker5121ce52009-01-03 21:22:43 +0000366
367 return( 0 );
368}
369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000371
Paul Bakker5121ce52009-01-03 21:22:43 +0000372static const unsigned char base64_test_dec[64] =
373{
374 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
375 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
376 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
377 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
378 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
379 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
380 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
381 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
382};
383
384static const unsigned char base64_test_enc[] =
385 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
386 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
387
388/*
389 * Checkup routine
390 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391int mbedtls_base64_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000392{
Paul Bakker23986e52011-04-24 08:57:21 +0000393 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200394 const unsigned char *src;
395 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000396
397 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 mbedtls_printf( " Base64 encoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000399
Paul Bakker3c2122f2013-06-24 19:03:14 +0200400 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000401
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100402 if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200403 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000404 {
405 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
408 return( 1 );
409 }
410
411 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 mbedtls_printf( "passed\n Base64 decoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000413
Paul Bakker3c2122f2013-06-24 19:03:14 +0200414 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000415
Manuel Pégourié-Gonnardba561362015-06-02 16:30:35 +0100416 if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
Paul Bakker5121ce52009-01-03 21:22:43 +0000417 memcmp( base64_test_dec, buffer, 64 ) != 0 )
418 {
419 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000421
422 return( 1 );
423 }
424
425 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 mbedtls_printf( "passed\n\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000427
428 return( 0 );
429}
430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433#endif /* MBEDTLS_BASE64_C */