LCOV - code coverage report
Current view: top level - os_stub/mbedtlslib/mbedtls/library - base64.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 39.2 % 125 49
Test Date: 2025-06-29 08:09:00 Functions: 40.0 % 5 2

            Line data    Source code
       1              : /*
       2              :  *  RFC 1521 base64 encoding/decoding
       3              :  *
       4              :  *  Copyright The Mbed TLS Contributors
       5              :  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       6              :  */
       7              : 
       8              : #include <limits.h>
       9              : 
      10              : #include "common.h"
      11              : 
      12              : #if defined(MBEDTLS_BASE64_C)
      13              : 
      14              : #include "mbedtls/base64.h"
      15              : #include "base64_internal.h"
      16              : #include "constant_time_internal.h"
      17              : 
      18              : #include <stdint.h>
      19              : 
      20              : #if defined(MBEDTLS_SELF_TEST)
      21              : #include <string.h>
      22              : #include "mbedtls/platform.h"
      23              : #endif /* MBEDTLS_SELF_TEST */
      24              : 
      25              : MBEDTLS_STATIC_TESTABLE
      26            0 : unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
      27              : {
      28            0 :     unsigned char digit = 0;
      29              :     /* For each range of values, if value is in that range, mask digit with
      30              :      * the corresponding value. Since value can only be in a single range,
      31              :      * only at most one masking will change digit. */
      32            0 :     digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value);
      33            0 :     digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26);
      34            0 :     digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52);
      35            0 :     digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+');
      36            0 :     digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/');
      37            0 :     return digit;
      38              : }
      39              : 
      40              : MBEDTLS_STATIC_TESTABLE
      41       255432 : signed char mbedtls_ct_base64_dec_value(unsigned char c)
      42              : {
      43       255432 :     unsigned char val = 0;
      44              :     /* For each range of digits, if c is in that range, mask val with
      45              :      * the corresponding value. Since c can only be in a single range,
      46              :      * only at most one masking will change val. Set val to one plus
      47              :      * the desired value so that it stays 0 if c is in none of the ranges. */
      48       255432 :     val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' +  0 + 1);
      49       255432 :     val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1);
      50       255432 :     val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1);
      51       255432 :     val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1);
      52       255432 :     val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1);
      53              :     /* At this point, val is 0 if c is an invalid digit and v+1 if c is
      54              :      * a digit with the value v. */
      55       255432 :     return val - 1;
      56              : }
      57              : 
      58              : /*
      59              :  * Encode a buffer into base64 format
      60              :  */
      61            0 : int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
      62              :                           const unsigned char *src, size_t slen)
      63              : {
      64              :     size_t i, n;
      65              :     int C1, C2, C3;
      66              :     unsigned char *p;
      67              : 
      68            0 :     if (slen == 0) {
      69            0 :         *olen = 0;
      70            0 :         return 0;
      71              :     }
      72              : 
      73            0 :     n = slen / 3 + (slen % 3 != 0);
      74              : 
      75            0 :     if (n > (SIZE_MAX - 1) / 4) {
      76            0 :         *olen = SIZE_MAX;
      77            0 :         return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
      78              :     }
      79              : 
      80            0 :     n *= 4;
      81              : 
      82            0 :     if ((dlen < n + 1) || (NULL == dst)) {
      83            0 :         *olen = n + 1;
      84            0 :         return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
      85              :     }
      86              : 
      87            0 :     n = (slen / 3) * 3;
      88              : 
      89            0 :     for (i = 0, p = dst; i < n; i += 3) {
      90            0 :         C1 = *src++;
      91            0 :         C2 = *src++;
      92            0 :         C3 = *src++;
      93              : 
      94            0 :         *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);
      95            0 :         *p++ = mbedtls_ct_base64_enc_char((((C1 &  3) << 4) + (C2 >> 4))
      96            0 :                                           & 0x3F);
      97            0 :         *p++ = mbedtls_ct_base64_enc_char((((C2 & 15) << 2) + (C3 >> 6))
      98            0 :                                           & 0x3F);
      99            0 :         *p++ = mbedtls_ct_base64_enc_char(C3 & 0x3F);
     100              :     }
     101              : 
     102            0 :     if (i < slen) {
     103            0 :         C1 = *src++;
     104            0 :         C2 = ((i + 1) < slen) ? *src++ : 0;
     105              : 
     106            0 :         *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);
     107            0 :         *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4))
     108            0 :                                           & 0x3F);
     109              : 
     110            0 :         if ((i + 1) < slen) {
     111            0 :             *p++ = mbedtls_ct_base64_enc_char(((C2 & 15) << 2) & 0x3F);
     112              :         } else {
     113            0 :             *p++ = '=';
     114              :         }
     115              : 
     116            0 :         *p++ = '=';
     117              :     }
     118              : 
     119            0 :     *olen = (size_t) (p - dst);
     120            0 :     *p = 0;
     121              : 
     122            0 :     return 0;
     123              : }
     124              : 
     125              : /*
     126              :  * Decode a base64-formatted buffer
     127              :  */
     128          362 : int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen,
     129              :                           const unsigned char *src, size_t slen)
     130              : {
     131              :     size_t i; /* index in source */
     132              :     size_t n; /* number of digits or trailing = in source */
     133              :     uint32_t x; /* value accumulator */
     134          362 :     unsigned accumulated_digits = 0;
     135          362 :     unsigned equals = 0;
     136          362 :     int spaces_present = 0;
     137              :     unsigned char *p;
     138              : 
     139              :     /* First pass: check for validity and get output length */
     140       176134 :     for (i = n = 0; i < slen; i++) {
     141              :         /* Skip spaces before checking for EOL */
     142       175772 :         spaces_present = 0;
     143       175772 :         while (i < slen && src[i] == ' ') {
     144            0 :             ++i;
     145            0 :             spaces_present = 1;
     146              :         }
     147              : 
     148              :         /* Spaces at end of buffer are OK */
     149       175772 :         if (i == slen) {
     150            0 :             break;
     151              :         }
     152              : 
     153       175772 :         if ((slen - i) >= 2 &&
     154       175410 :             src[i] == '\r' && src[i + 1] == '\n') {
     155         2742 :             continue;
     156              :         }
     157              : 
     158       173030 :         if (src[i] == '\n') {
     159         2742 :             continue;
     160              :         }
     161              : 
     162              :         /* Space inside a line is an error */
     163       170288 :         if (spaces_present) {
     164            0 :             return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
     165              :         }
     166              : 
     167       170288 :         if (src[i] > 127) {
     168            0 :             return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
     169              :         }
     170              : 
     171       170288 :         if (src[i] == '=') {
     172            0 :             if (++equals > 2) {
     173            0 :                 return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
     174              :             }
     175              :         } else {
     176       170288 :             if (equals != 0) {
     177            0 :                 return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
     178              :             }
     179       170288 :             if (mbedtls_ct_base64_dec_value(src[i]) < 0) {
     180            0 :                 return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
     181              :             }
     182              :         }
     183       170288 :         n++;
     184              :     }
     185              : 
     186          362 :     if (n == 0) {
     187            0 :         *olen = 0;
     188            0 :         return 0;
     189              :     }
     190              : 
     191              :     /* The following expression is to calculate the following formula without
     192              :      * risk of integer overflow in n:
     193              :      *     n = ( ( n * 6 ) + 7 ) >> 3;
     194              :      */
     195          362 :     n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3);
     196          362 :     n -= equals;
     197              : 
     198          362 :     if (dst == NULL || dlen < n) {
     199          181 :         *olen = n;
     200          181 :         return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
     201              :     }
     202              : 
     203          181 :     equals = 0;
     204        88067 :     for (x = 0, p = dst; i > 0; i--, src++) {
     205        87886 :         if (*src == '\r' || *src == '\n' || *src == ' ') {
     206         2742 :             continue;
     207              :         }
     208              : 
     209        85144 :         x = x << 6;
     210        85144 :         if (*src == '=') {
     211            0 :             ++equals;
     212              :         } else {
     213        85144 :             x |= mbedtls_ct_base64_dec_value(*src);
     214              :         }
     215              : 
     216        85144 :         if (++accumulated_digits == 4) {
     217        21286 :             accumulated_digits = 0;
     218        21286 :             *p++ = MBEDTLS_BYTE_2(x);
     219        21286 :             if (equals <= 1) {
     220        21286 :                 *p++ = MBEDTLS_BYTE_1(x);
     221              :             }
     222        21286 :             if (equals <= 0) {
     223        21286 :                 *p++ = MBEDTLS_BYTE_0(x);
     224              :             }
     225              :         }
     226              :     }
     227              : 
     228          181 :     *olen = (size_t) (p - dst);
     229              : 
     230          181 :     return 0;
     231              : }
     232              : 
     233              : #if defined(MBEDTLS_SELF_TEST)
     234              : 
     235              : static const unsigned char base64_test_dec[64] =
     236              : {
     237              :     0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
     238              :     0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
     239              :     0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
     240              :     0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
     241              :     0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
     242              :     0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
     243              :     0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
     244              :     0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
     245              : };
     246              : 
     247              : static const unsigned char base64_test_enc[] =
     248              :     "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
     249              :     "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
     250              : 
     251              : /*
     252              :  * Checkup routine
     253              :  */
     254            0 : int mbedtls_base64_self_test(int verbose)
     255              : {
     256              :     size_t len;
     257              :     const unsigned char *src;
     258              :     unsigned char buffer[128];
     259              : 
     260            0 :     if (verbose != 0) {
     261            0 :         mbedtls_printf("  Base64 encoding test: ");
     262              :     }
     263              : 
     264            0 :     src = base64_test_dec;
     265              : 
     266            0 :     if (mbedtls_base64_encode(buffer, sizeof(buffer), &len, src, 64) != 0 ||
     267            0 :         memcmp(base64_test_enc, buffer, 88) != 0) {
     268            0 :         if (verbose != 0) {
     269            0 :             mbedtls_printf("failed\n");
     270              :         }
     271              : 
     272            0 :         return 1;
     273              :     }
     274              : 
     275            0 :     if (verbose != 0) {
     276            0 :         mbedtls_printf("passed\n  Base64 decoding test: ");
     277              :     }
     278              : 
     279            0 :     src = base64_test_enc;
     280              : 
     281            0 :     if (mbedtls_base64_decode(buffer, sizeof(buffer), &len, src, 88) != 0 ||
     282            0 :         memcmp(base64_test_dec, buffer, 64) != 0) {
     283            0 :         if (verbose != 0) {
     284            0 :             mbedtls_printf("failed\n");
     285              :         }
     286              : 
     287            0 :         return 1;
     288              :     }
     289              : 
     290            0 :     if (verbose != 0) {
     291            0 :         mbedtls_printf("passed\n\n");
     292              :     }
     293              : 
     294            0 :     return 0;
     295              : }
     296              : 
     297              : #endif /* MBEDTLS_SELF_TEST */
     298              : 
     299              : #endif /* MBEDTLS_BASE64_C */
        

Generated by: LCOV version 2.0-1