LCOV - code coverage report
Current view: top level - lib/util - base64.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 69 72 95.8 %
Date: 2024-12-08 02:21:43 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2018 Intel Corporation. All rights reserved.
       3             :  *   Copyright(c) ARM Limited. 2021 All rights reserved.
       4             :  *   All rights reserved.
       5             :  */
       6             : 
       7             : #include "spdk/stdinc.h"
       8             : #include "spdk/endian.h"
       9             : #include "spdk/base64.h"
      10             : 
      11             : #ifdef __aarch64__
      12             : #ifdef __ARM_FEATURE_SVE
      13             : #include "base64_sve.c"
      14             : #else
      15             : #include "base64_neon.c"
      16             : #endif
      17             : #endif
      18             : 
      19             : 
      20             : #define BASE64_ENC_BITMASK 0x3FUL
      21             : #define BASE64_PADDING_CHAR '='
      22             : 
      23             : static const char base64_enc_table[] =
      24             :         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      25             :         "abcdefghijklmnopqrstuvwxyz"
      26             :         "0123456789+/";
      27             : 
      28             : static const char base64_urlsafe_enc_table[] =
      29             :         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      30             :         "abcdefghijklmnopqrstuvwxyz"
      31             :         "0123456789-_";
      32             : 
      33             : static const uint8_t
      34             : base64_dec_table[] = {
      35             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      36             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      37             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
      38             :         52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255, 255, 255, 255, 255,
      39             :         255,   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
      40             :         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
      41             :         255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
      42             :         41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51, 255, 255, 255, 255, 255,
      43             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      44             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      45             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      46             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      47             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      48             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      49             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      50             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      51             : };
      52             : 
      53             : static const uint8_t
      54             : base64_urlsafe_dec_table[] = {
      55             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      56             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      57             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  62, 255, 255,
      58             :         52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255, 255, 255, 255, 255,
      59             :         255,   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
      60             :         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255,  63,
      61             :         255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
      62             :         41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51, 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             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      70             :         255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      71             : };
      72             : 
      73             : static int
      74          18 : base64_encode(char *dst, const char *enc_table, const void *src, size_t src_len)
      75             : {
      76             :         uint32_t raw_u32;
      77             : 
      78          18 :         if (!dst || !src || src_len <= 0) {
      79           6 :                 return -EINVAL;
      80             :         }
      81             : 
      82             : #ifdef __aarch64__
      83             : #ifdef __ARM_FEATURE_SVE
      84             :         base64_encode_sve(&dst, enc_table, &src, &src_len);
      85             : #else
      86             :         base64_encode_neon64(&dst, enc_table, &src, &src_len);
      87             : #endif
      88             : #endif
      89             : 
      90             : 
      91         118 :         while (src_len >= 4) {
      92         106 :                 raw_u32 = from_be32(src);
      93             : 
      94         106 :                 *dst++ = enc_table[(raw_u32 >> 26) & BASE64_ENC_BITMASK];
      95         106 :                 *dst++ = enc_table[(raw_u32 >> 20) & BASE64_ENC_BITMASK];
      96         106 :                 *dst++ = enc_table[(raw_u32 >> 14) & BASE64_ENC_BITMASK];
      97         106 :                 *dst++ = enc_table[(raw_u32 >> 8) & BASE64_ENC_BITMASK];
      98             : 
      99         106 :                 src_len -= 3;
     100         106 :                 src = (uint8_t *)src + 3;
     101             :         }
     102             : 
     103          12 :         if (src_len == 0) {
     104           0 :                 goto out;
     105             :         }
     106             : 
     107          12 :         raw_u32 = 0;
     108          12 :         memcpy(&raw_u32, src, src_len);
     109          12 :         raw_u32 = from_be32(&raw_u32);
     110             : 
     111          12 :         *dst++ = enc_table[(raw_u32 >> 26) & BASE64_ENC_BITMASK];
     112          12 :         *dst++ = enc_table[(raw_u32 >> 20) & BASE64_ENC_BITMASK];
     113          12 :         *dst++ = (src_len >= 2) ? enc_table[(raw_u32 >> 14) & BASE64_ENC_BITMASK] : BASE64_PADDING_CHAR;
     114          12 :         *dst++ = (src_len == 3) ? enc_table[(raw_u32 >> 8) & BASE64_ENC_BITMASK] : BASE64_PADDING_CHAR;
     115             : 
     116             : out:
     117          12 :         *dst = '\0';
     118             : 
     119          12 :         return 0;
     120          18 : }
     121             : 
     122             : int
     123           9 : spdk_base64_encode(char *dst, const void *src, size_t src_len)
     124             : {
     125           9 :         return base64_encode(dst, base64_enc_table, src, src_len);
     126             : }
     127             : 
     128             : int
     129           9 : spdk_base64_urlsafe_encode(char *dst, const void *src, size_t src_len)
     130             : {
     131           9 :         return base64_encode(dst, base64_urlsafe_enc_table, src, src_len);
     132             : }
     133             : 
     134             : #if defined(__aarch64__) && !defined(__ARM_FEATURE_SVE)
     135             : static int
     136             : base64_decode(void *dst, size_t *_dst_len, const uint8_t *dec_table,
     137             :               const uint8_t *dec_table_opt, const char *src)
     138             : #else
     139             : static int
     140          35 : base64_decode(void *dst, size_t *_dst_len, const uint8_t *dec_table, const char *src)
     141             : #endif
     142             : {
     143             :         size_t src_strlen;
     144          35 :         size_t tail_len = 0;
     145             :         const uint8_t *src_in;
     146             :         uint32_t tmp[4];
     147             :         int i;
     148             : 
     149          35 :         if (!src) {
     150           2 :                 return -EINVAL;
     151             :         }
     152             : 
     153          33 :         src_strlen = strlen(src);
     154             : 
     155             :         /* strlen of src should be 4n */
     156          33 :         if (src_strlen == 0 || src_strlen % 4 != 0) {
     157           6 :                 return -EINVAL;
     158             :         }
     159             : 
     160             :         /* Consider Base64 padding, it at most has 2 padding characters. */
     161          51 :         for (i = 0; i < 2; i++) {
     162          41 :                 if (src[src_strlen - 1] != BASE64_PADDING_CHAR) {
     163          17 :                         break;
     164             :                 }
     165          24 :                 src_strlen--;
     166          24 :         }
     167             : 
     168             :         /* strlen of src without padding shouldn't be 4n+1 */
     169          27 :         if (src_strlen == 0 || src_strlen % 4 == 1) {
     170           0 :                 return -EINVAL;
     171             :         }
     172             : 
     173          27 :         if (_dst_len) {
     174          27 :                 *_dst_len = spdk_base64_get_decoded_len(src_strlen);
     175          27 :         }
     176             : 
     177             :         /* If dst is NULL, the client is only concerned w/ _dst_len, return */
     178          27 :         if (!dst) {
     179          12 :                 return 0;
     180             :         }
     181             : 
     182          15 :         src_in = (const uint8_t *) src;
     183             : 
     184             : #ifdef __aarch64__
     185             : #ifdef __ARM_FEATURE_SVE
     186             :         base64_decode_sve(&dst, dec_table, &src_in, &src_strlen);
     187             : #else
     188             :         base64_decode_neon64(&dst, dec_table_opt, &src_in, &src_strlen);
     189             : #endif
     190             : 
     191             :         if (src_strlen == 0) {
     192             :                 return 0;
     193             :         }
     194             : #endif
     195             : 
     196             : 
     197             :         /* space of dst can be used by to_be32 */
     198         134 :         while (src_strlen > 4) {
     199         119 :                 tmp[0] = dec_table[*src_in++];
     200         119 :                 tmp[1] = dec_table[*src_in++];
     201         119 :                 tmp[2] = dec_table[*src_in++];
     202         119 :                 tmp[3] = dec_table[*src_in++];
     203             : 
     204         119 :                 if (tmp[0] == 255 || tmp[1] == 255 || tmp[2] == 255 || tmp[3] == 255) {
     205           0 :                         return -EINVAL;
     206             :                 }
     207             : 
     208         119 :                 to_be32(dst, tmp[3] << 8 | tmp[2] << 14 | tmp[1] << 20 | tmp[0] << 26);
     209             : 
     210         119 :                 dst = (uint8_t *)dst + 3;
     211         119 :                 src_strlen -= 4;
     212             :         }
     213             : 
     214             :         /* space of dst is not enough to be used by to_be32 */
     215          15 :         tmp[0] = dec_table[src_in[0]];
     216          15 :         tmp[1] = dec_table[src_in[1]];
     217          15 :         tmp[2] = (src_strlen >= 3) ? dec_table[src_in[2]] : 0;
     218          15 :         tmp[3] = (src_strlen == 4) ? dec_table[src_in[3]] : 0;
     219          15 :         tail_len = src_strlen - 1;
     220             : 
     221          15 :         if (tmp[0] == 255 || tmp[1] == 255 || tmp[2] == 255 || tmp[3] == 255) {
     222           2 :                 return -EINVAL;
     223             :         }
     224             : 
     225          13 :         to_be32(&tmp[3], tmp[3] << 8 | tmp[2] << 14 | tmp[1] << 20 | tmp[0] << 26);
     226          13 :         memcpy(dst, (uint8_t *)&tmp[3], tail_len);
     227             : 
     228          13 :         return 0;
     229          35 : }
     230             : 
     231             : int
     232          18 : spdk_base64_decode(void *dst, size_t *dst_len, const char *src)
     233             : {
     234             : #if defined(__aarch64__) && !defined(__ARM_FEATURE_SVE)
     235             :         return base64_decode(dst, dst_len, base64_dec_table, base64_dec_table_neon64, src);
     236             : #else
     237          18 :         return base64_decode(dst, dst_len, base64_dec_table, src);
     238             : #endif
     239             : }
     240             : 
     241             : int
     242          17 : spdk_base64_urlsafe_decode(void *dst, size_t *dst_len, const char *src)
     243             : {
     244             : #if defined(__aarch64__) && !defined(__ARM_FEATURE_SVE)
     245             :         return base64_decode(dst, dst_len, base64_urlsafe_dec_table, base64_urlsafe_dec_table_neon64,
     246             :                              src);
     247             : #else
     248          17 :         return base64_decode(dst, dst_len, base64_urlsafe_dec_table, src);
     249             : #endif
     250             : }

Generated by: LCOV version 1.15