Blame src/util/support/base64.c

Packit fd8b60
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit fd8b60
/* util/support/base64.c - base64 encoder and decoder */
Packit fd8b60
/*
Packit fd8b60
 * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
Packit fd8b60
 * (Royal Institute of Technology, Stockholm, Sweden).
Packit fd8b60
 * All rights reserved.
Packit fd8b60
 *
Packit fd8b60
 * Redistribution and use in source and binary forms, with or without
Packit fd8b60
 * modification, are permitted provided that the following conditions
Packit fd8b60
 * are met:
Packit fd8b60
 *
Packit fd8b60
 * 1. Redistributions of source code must retain the above copyright
Packit fd8b60
 *    notice, this list of conditions and the following disclaimer.
Packit fd8b60
 *
Packit fd8b60
 * 2. Redistributions in binary form must reproduce the above copyright
Packit fd8b60
 *    notice, this list of conditions and the following disclaimer in the
Packit fd8b60
 *    documentation and/or other materials provided with the distribution.
Packit fd8b60
 *
Packit fd8b60
 * 3. Neither the name of the Institute nor the names of its contributors
Packit fd8b60
 *    may be used to endorse or promote products derived from this software
Packit fd8b60
 *    without specific prior written permission.
Packit fd8b60
 *
Packit fd8b60
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
Packit fd8b60
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit fd8b60
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit fd8b60
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
Packit fd8b60
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit fd8b60
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit fd8b60
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit fd8b60
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit fd8b60
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit fd8b60
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit fd8b60
 * SUCH DAMAGE.
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
#include <k5-platform.h>
Packit fd8b60
#include <k5-base64.h>
Packit fd8b60
Packit fd8b60
static const char base64_chars[] =
Packit fd8b60
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
Packit fd8b60
Packit fd8b60
char *
Packit fd8b60
k5_base64_encode(const void *data, size_t len)
Packit fd8b60
{
Packit fd8b60
    char *s, *p;
Packit fd8b60
    size_t i;
Packit fd8b60
    unsigned int c;
Packit fd8b60
    const unsigned char *q;
Packit fd8b60
Packit fd8b60
    if (len > SIZE_MAX / 4)
Packit fd8b60
        return NULL;
Packit fd8b60
Packit fd8b60
    p = s = malloc(len * 4 / 3 + 4);
Packit fd8b60
    if (p == NULL)
Packit fd8b60
        return NULL;
Packit fd8b60
    q = (const unsigned char *)data;
Packit fd8b60
Packit fd8b60
    for (i = 0; i < len;) {
Packit fd8b60
        c = q[i++];
Packit fd8b60
        c *= 256;
Packit fd8b60
        if (i < len)
Packit fd8b60
            c += q[i];
Packit fd8b60
        i++;
Packit fd8b60
        c *= 256;
Packit fd8b60
        if (i < len)
Packit fd8b60
            c += q[i];
Packit fd8b60
        i++;
Packit fd8b60
        p[0] = base64_chars[(c & 0x00fc0000) >> 18];
Packit fd8b60
        p[1] = base64_chars[(c & 0x0003f000) >> 12];
Packit fd8b60
        p[2] = base64_chars[(c & 0x00000fc0) >> 6];
Packit fd8b60
        p[3] = base64_chars[(c & 0x0000003f) >> 0];
Packit fd8b60
        if (i > len)
Packit fd8b60
            p[3] = '=';
Packit fd8b60
        if (i > len + 1)
Packit fd8b60
            p[2] = '=';
Packit fd8b60
        p += 4;
Packit fd8b60
    }
Packit fd8b60
    *p = '\0';
Packit fd8b60
    return s;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
#define DECODE_ERROR 0xffffffff
Packit fd8b60
Packit fd8b60
/* Decode token, which must be four bytes long. */
Packit fd8b60
static unsigned int
Packit fd8b60
decode_token(const char *token)
Packit fd8b60
{
Packit fd8b60
    int i, marker = 0;
Packit fd8b60
    unsigned int val = 0;
Packit fd8b60
    const char *p;
Packit fd8b60
Packit fd8b60
    for (i = 0; i < 4; i++) {
Packit fd8b60
        val *= 64;
Packit fd8b60
        if (token[i] == '=') {
Packit fd8b60
            marker++;
Packit fd8b60
        } else if (marker > 0) {
Packit fd8b60
            return DECODE_ERROR;
Packit fd8b60
        } else {
Packit fd8b60
            p = strchr(base64_chars, token[i]);
Packit fd8b60
            if (p == NULL)
Packit fd8b60
                return DECODE_ERROR;
Packit fd8b60
            val += p - base64_chars;
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
    if (marker > 2)
Packit fd8b60
        return DECODE_ERROR;
Packit fd8b60
    return (marker << 24) | val;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
void *
Packit fd8b60
k5_base64_decode(const char *str, size_t *len_out)
Packit fd8b60
{
Packit fd8b60
    unsigned char *data, *q;
Packit fd8b60
    unsigned int val, marker;
Packit fd8b60
    size_t len;
Packit fd8b60
Packit fd8b60
    *len_out = SIZE_MAX;
Packit fd8b60
Packit fd8b60
    /* Allocate the output buffer. */
Packit fd8b60
    len = strlen(str);
Packit fd8b60
    if (len % 4)
Packit fd8b60
        return NULL;
Packit fd8b60
    q = data = malloc(len / 4 * 3);
Packit fd8b60
    if (data == NULL) {
Packit fd8b60
        *len_out = 0;
Packit fd8b60
        return NULL;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* Decode the string. */
Packit fd8b60
    for (; *str != '\0'; str += 4) {
Packit fd8b60
        val = decode_token(str);
Packit fd8b60
        if (val == DECODE_ERROR) {
Packit fd8b60
            free(data);
Packit fd8b60
            return NULL;
Packit fd8b60
        }
Packit fd8b60
        marker = (val >> 24) & 0xff;
Packit fd8b60
        *q++ = (val >> 16) & 0xff;
Packit fd8b60
        if (marker < 2)
Packit fd8b60
            *q++ = (val >> 8) & 0xff;
Packit fd8b60
        if (marker < 1)
Packit fd8b60
            *q++ = val & 0xff;
Packit fd8b60
    }
Packit fd8b60
    *len_out = q - data;
Packit fd8b60
    return data;
Packit fd8b60
}