1/*2 * SPDX-FileCopyrightText: 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)3 * SPDX-FileCopyrightText: 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de>4 * SPDX-License-Identifier: LGPL-2.1-only5 */67#pragma once89/**10 * @defgroup sys_base64 Base64 encoder decoder11 * @ingroup sys_serialization12 * @brief Base64 encoder and decoder13 * @{14 *15 * @brief Encoding and decoding functions for base6416 * @author Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de>17 */1819#include <stddef.h> /* for size_t */20#include <stdbool.h> /* for bool */2122#ifdef __cplusplus23extern "C" {24#endif2526#define BASE64_SUCCESS (0) /**< return value for success */27#define BASE64_ERROR_BUFFER_OUT (-1) /**< error value for invalid output buffer pointer */28#define BASE64_ERROR_BUFFER_OUT_SIZE (-2) /**< error value for invalid output buffer size */29#define BASE64_ERROR_DATA_IN (-3) /**< error value for invalid input buffer */30#define BASE64_ERROR_DATA_IN_SIZE (-4) /**< error value for invalid input buffer size */31#define BASE64_ERROR_OVERFLOW (-5) /**< error value for buffer overflow */3233/**34 * @brief Estimates the amount of bytes needed for decoding @p base64_in_size35 * characters from base64.36 *37 * @param[in] base64_in_size Size of the string to be decoded38 *39 * @return Amount of bytes estimated to be used after decoding40 */41static inline size_t base64_estimate_decode_size(size_t base64_in_size)42{43 return (((base64_in_size + 3) / 4) * 3);44}4546/**47 * @brief Estimates the length of the resulting string after encoding48 * @p data_in_size bytes into base64.49 *50 * @pre @p data_in_size must be smaller than ~75% of the SIZE_MAX to51 * prevent integer overflow in the calculation of the return value.52 *53 * @param[in] data_in_size Amount of bytes to be encoded54 *55 * @return Amount of characters the output string is estimated to have56 */57static inline size_t base64_estimate_encode_size(size_t data_in_size)58{59 return (4 * ((data_in_size + 2) / 3));60}6162/**63 * @brief Checks if the given size of data can return a valid estimate for64 * the size without an integer overflow.65 *66 * @param[in] data_in_size Amount of bytes to be encoded67 *68 * @retval true if the given size can be encoded to base6469 * @retval false if the given size would overflow70 */71static inline bool base64_can_estimate_encode_size(size_t data_in_size)72{73 return (data_in_size <= (SIZE_MAX / 4) * 3);74}7576/**77 * @brief Encodes a given datum to base64 and save the result to the given destination.78 *79 * @param[in] data_in Pointer to the datum to encode80 * @param[in] data_in_size The size of `data_in`81 * @param[out] base64_out Pointer to store the encoded base64 string (may be tainted82 * on error)83 * @param[in,out] base64_out_size Pointer to the variable containing the size of `base64_out.`84 * This value is overwritten with the estimated size used for85 * the encoded base64 string on BASE64_ERROR_BUFFER_OUT_SIZE.86 * This value is overwritten with the actual used size for the87 * encoded base64 string on BASE64_SUCCESS.88 *89 * @retval BASE64_SUCCESS on success90 * @retval BASE64_ERROR_BUFFER_OUT_SIZE on insufficient size for encoding to `base64_out`91 * @retval BASE64_ERROR_BUFFER_OUT if `base64_out` equals NULL but the `base64_out_size`92 * is sufficient93 * @retval BASE64_ERROR_DATA_IN if `data_in` equals NULL94 * @retval BASE64_ERROR_OVERFLOW if `data_in_size` is too large to be encoded to base6495 */96int base64_encode(const void *data_in, size_t data_in_size,97 void *base64_out, size_t *base64_out_size);9899/**100 * @brief Encodes a given datum to base64 with URL and Filename Safe Alphabet101 * and save the result to the given destination.102 *103 * @see [RFC 4648, section 5](https://tools.ietf.org/html/rfc4648#section-5)104 *105 * @note Requires the use of the `base64url` module.106 *107 * @param[in] data_in Pointer to the datum to encode108 * @param[in] data_in_size The size of `data_in`109 * @param[out] base64_out Pointer to store the encoded base64 string (may be tainted110 * on error)111 * @param[in,out] base64_out_size Pointer to the variable containing the size of `base64_out.`112 * This value is overwritten with the estimated size used for113 * the encoded base64 string on BASE64_ERROR_BUFFER_OUT_SIZE.114 * This value is overwritten with the actual used size for the115 * encoded base64 string on BASE64_SUCCESS.116 *117 * @retval BASE64_SUCCESS on success118 * @retval BASE64_ERROR_BUFFER_OUT_SIZE on insufficient size for encoding to `base64_out`119 * @retval BASE64_ERROR_BUFFER_OUT if `base64_out` equals NULL but the `base64_out_size`120 * is sufficient121 * @retval BASE64_ERROR_DATA_IN if `data_in` equals NULL122 * @retval BASE64_ERROR_OVERFLOW if `data_in_size` is too large to be encoded to base64123 */124int base64url_encode(const void *data_in, size_t data_in_size,125 void *base64_out, size_t *base64_out_size);126127/**128 * @brief Decodes a given base64 string and save the result to the given destination.129 *130 * @param[in] base64_in Pointer to the datum to decode131 * @param[in] base64_in_size The size of `base64_in`132 * @param[out] data_out Pointer to store the decoded base64 string (may be tainted133 * on error)134 * @param[in,out] data_out_size The size of `data_out`.135 * This value is overwritten with the estimated size used for the136 * decoded string on BASE64_ERROR_BUFFER_OUT_SIZE.137 * This value is overwritten with the actual used size for the138 * decoded string on BASE64_SUCCESS.139 *140 * @retval BASE64_SUCCESS on success141 * @retval BASE64_ERROR_BUFFER_OUT_SIZE on insufficient size for decoding to `data_out`142 * @retval BASE64_ERROR_BUFFER_OUT if `data_out` equals NULL but the size for143 * `data_out_size` is sufficient144 * @retval BASE64_ERROR_DATA_IN if `base64_in` equals NULL145 * @retval BASE64_ERROR_DATA_IN_SIZE if `base64_in_size` has remainder 1 (mod 4)146 */147int base64_decode(const void *base64_in, size_t base64_in_size,148 void *data_out, size_t *data_out_size);149150#ifdef __cplusplus151}152#endif153154/** @} */