Blame crypto/evp/encode.c

Packit c4476c
/*
Packit c4476c
 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
 *
Packit c4476c
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
 * this file except in compliance with the License.  You can obtain a copy
Packit c4476c
 * in the file LICENSE in the source distribution or at
Packit c4476c
 * https://www.openssl.org/source/license.html
Packit c4476c
 */
Packit c4476c
Packit c4476c
#include <stdio.h>
Packit c4476c
#include <limits.h>
Packit c4476c
#include "internal/cryptlib.h"
Packit c4476c
#include <openssl/evp.h>
Packit c4476c
#include "crypto/evp.h"
Packit c4476c
#include "evp_local.h"
Packit c4476c
Packit c4476c
static unsigned char conv_ascii2bin(unsigned char a,
Packit c4476c
                                    const unsigned char *table);
Packit c4476c
static int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
Packit c4476c
                               const unsigned char *f, int dlen);
Packit c4476c
static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
Packit c4476c
                               const unsigned char *f, int n);
Packit c4476c
Packit c4476c
#ifndef CHARSET_EBCDIC
Packit c4476c
# define conv_bin2ascii(a, table)       ((table)[(a)&0x3f])
Packit c4476c
#else
Packit c4476c
/*
Packit c4476c
 * We assume that PEM encoded files are EBCDIC files (i.e., printable text
Packit c4476c
 * files). Convert them here while decoding. When encoding, output is EBCDIC
Packit c4476c
 * (text) format again. (No need for conversion in the conv_bin2ascii macro,
Packit c4476c
 * as the underlying textstring data_bin2ascii[] is already EBCDIC)
Packit c4476c
 */
Packit c4476c
# define conv_bin2ascii(a, table)       ((table)[(a)&0x3f])
Packit c4476c
#endif
Packit c4476c
Packit c4476c
/*-
Packit c4476c
 * 64 char lines
Packit c4476c
 * pad input with 0
Packit c4476c
 * left over chars are set to =
Packit c4476c
 * 1 byte  => xx==
Packit c4476c
 * 2 bytes => xxx=
Packit c4476c
 * 3 bytes => xxxx
Packit c4476c
 */
Packit c4476c
#define BIN_PER_LINE    (64/4*3)
Packit c4476c
#define CHUNKS_PER_LINE (64/4)
Packit c4476c
#define CHAR_PER_LINE   (64+1)
Packit c4476c
Packit c4476c
static const unsigned char data_bin2ascii[65] =
Packit c4476c
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
Packit c4476c
Packit c4476c
/* SRP uses a different base64 alphabet */
Packit c4476c
static const unsigned char srpdata_bin2ascii[65] =
Packit c4476c
    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
Packit c4476c
Packit c4476c
Packit c4476c
/*-
Packit c4476c
 * 0xF0 is a EOLN
Packit c4476c
 * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
Packit c4476c
 * 0xF2 is EOF
Packit c4476c
 * 0xE0 is ignore at start of line.
Packit c4476c
 * 0xFF is error
Packit c4476c
 */
Packit c4476c
Packit c4476c
#define B64_EOLN                0xF0
Packit c4476c
#define B64_CR                  0xF1
Packit c4476c
#define B64_EOF                 0xF2
Packit c4476c
#define B64_WS                  0xE0
Packit c4476c
#define B64_ERROR               0xFF
Packit c4476c
#define B64_NOT_BASE64(a)       (((a)|0x13) == 0xF3)
Packit c4476c
#define B64_BASE64(a)           (!B64_NOT_BASE64(a))
Packit c4476c
Packit c4476c
static const unsigned char data_ascii2bin[128] = {
Packit c4476c
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
Packit c4476c
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
Packit c4476c
    0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
Packit c4476c
    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
Packit c4476c
    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
Packit c4476c
    0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
Packit c4476c
    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
Packit c4476c
    0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
Packit c4476c
    0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
};
Packit c4476c
Packit c4476c
static const unsigned char srpdata_ascii2bin[128] = {
Packit c4476c
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x3E, 0x3F,
Packit c4476c
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
Packit c4476c
    0x08, 0x09, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
Packit c4476c
    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
Packit c4476c
    0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
Packit c4476c
    0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
    0xFF, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
Packit c4476c
    0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
Packit c4476c
    0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
Packit c4476c
    0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Packit c4476c
};
Packit c4476c
Packit c4476c
#ifndef CHARSET_EBCDIC
Packit c4476c
static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table)
Packit c4476c
{
Packit c4476c
    if (a & 0x80)
Packit c4476c
        return B64_ERROR;
Packit c4476c
    return table[a];
Packit c4476c
}
Packit c4476c
#else
Packit c4476c
static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table)
Packit c4476c
{
Packit c4476c
    a = os_toascii[a];
Packit c4476c
    if (a & 0x80)
Packit c4476c
        return B64_ERROR;
Packit c4476c
    return table[a];
Packit c4476c
}
Packit c4476c
#endif
Packit c4476c
Packit c4476c
EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
Packit c4476c
{
Packit c4476c
    return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX));
Packit c4476c
}
Packit c4476c
Packit c4476c
void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
Packit c4476c
{
Packit c4476c
    OPENSSL_free(ctx);
Packit c4476c
}
Packit c4476c
Packit c4476c
int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, EVP_ENCODE_CTX *sctx)
Packit c4476c
{
Packit c4476c
    memcpy(dctx, sctx, sizeof(EVP_ENCODE_CTX));
Packit c4476c
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx)
Packit c4476c
{
Packit c4476c
    return ctx->num;
Packit c4476c
}
Packit c4476c
Packit c4476c
void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags)
Packit c4476c
{
Packit c4476c
    ctx->flags = flags;
Packit c4476c
}
Packit c4476c
Packit c4476c
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
Packit c4476c
{
Packit c4476c
    ctx->length = 48;
Packit c4476c
    ctx->num = 0;
Packit c4476c
    ctx->line_num = 0;
Packit c4476c
    ctx->flags = 0;
Packit c4476c
}
Packit c4476c
Packit c4476c
int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
Packit c4476c
                      const unsigned char *in, int inl)
Packit c4476c
{
Packit c4476c
    int i, j;
Packit c4476c
    size_t total = 0;
Packit c4476c
Packit c4476c
    *outl = 0;
Packit c4476c
    if (inl <= 0)
Packit c4476c
        return 0;
Packit c4476c
    OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
Packit c4476c
    if (ctx->length - ctx->num > inl) {
Packit c4476c
        memcpy(&(ctx->enc_data[ctx->num]), in, inl);
Packit c4476c
        ctx->num += inl;
Packit c4476c
        return 1;
Packit c4476c
    }
Packit c4476c
    if (ctx->num != 0) {
Packit c4476c
        i = ctx->length - ctx->num;
Packit c4476c
        memcpy(&(ctx->enc_data[ctx->num]), in, i);
Packit c4476c
        in += i;
Packit c4476c
        inl -= i;
Packit c4476c
        j = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->length);
Packit c4476c
        ctx->num = 0;
Packit c4476c
        out += j;
Packit c4476c
        total = j;
Packit c4476c
        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
Packit c4476c
            *(out++) = '\n';
Packit c4476c
            total++;
Packit c4476c
        }
Packit c4476c
        *out = '\0';
Packit c4476c
    }
Packit c4476c
    while (inl >= ctx->length && total <= INT_MAX) {
Packit c4476c
        j = evp_encodeblock_int(ctx, out, in, ctx->length);
Packit c4476c
        in += ctx->length;
Packit c4476c
        inl -= ctx->length;
Packit c4476c
        out += j;
Packit c4476c
        total += j;
Packit c4476c
        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
Packit c4476c
            *(out++) = '\n';
Packit c4476c
            total++;
Packit c4476c
        }
Packit c4476c
        *out = '\0';
Packit c4476c
    }
Packit c4476c
    if (total > INT_MAX) {
Packit c4476c
        /* Too much output data! */
Packit c4476c
        *outl = 0;
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    if (inl != 0)
Packit c4476c
        memcpy(&(ctx->enc_data[0]), in, inl);
Packit c4476c
    ctx->num = inl;
Packit c4476c
    *outl = total;
Packit c4476c
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
Packit c4476c
{
Packit c4476c
    unsigned int ret = 0;
Packit c4476c
Packit c4476c
    if (ctx->num != 0) {
Packit c4476c
        ret = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->num);
Packit c4476c
        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
Packit c4476c
            out[ret++] = '\n';
Packit c4476c
        out[ret] = '\0';
Packit c4476c
        ctx->num = 0;
Packit c4476c
    }
Packit c4476c
    *outl = ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
Packit c4476c
                               const unsigned char *f, int dlen)
Packit c4476c
{
Packit c4476c
    int i, ret = 0;
Packit c4476c
    unsigned long l;
Packit c4476c
    const unsigned char *table;
Packit c4476c
Packit c4476c
    if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
Packit c4476c
        table = srpdata_bin2ascii;
Packit c4476c
    else
Packit c4476c
        table = data_bin2ascii;
Packit c4476c
Packit c4476c
    for (i = dlen; i > 0; i -= 3) {
Packit c4476c
        if (i >= 3) {
Packit c4476c
            l = (((unsigned long)f[0]) << 16L) |
Packit c4476c
                (((unsigned long)f[1]) << 8L) | f[2];
Packit c4476c
            *(t++) = conv_bin2ascii(l >> 18L, table);
Packit c4476c
            *(t++) = conv_bin2ascii(l >> 12L, table);
Packit c4476c
            *(t++) = conv_bin2ascii(l >> 6L, table);
Packit c4476c
            *(t++) = conv_bin2ascii(l, table);
Packit c4476c
        } else {
Packit c4476c
            l = ((unsigned long)f[0]) << 16L;
Packit c4476c
            if (i == 2)
Packit c4476c
                l |= ((unsigned long)f[1] << 8L);
Packit c4476c
Packit c4476c
            *(t++) = conv_bin2ascii(l >> 18L, table);
Packit c4476c
            *(t++) = conv_bin2ascii(l >> 12L, table);
Packit c4476c
            *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L, table);
Packit c4476c
            *(t++) = '=';
Packit c4476c
        }
Packit c4476c
        ret += 4;
Packit c4476c
        f += 3;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    *t = '\0';
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
Packit c4476c
{
Packit c4476c
    return evp_encodeblock_int(NULL, t, f, dlen);
Packit c4476c
}
Packit c4476c
Packit c4476c
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
Packit c4476c
{
Packit c4476c
    /* Only ctx->num and ctx->flags are used during decoding. */
Packit c4476c
    ctx->num = 0;
Packit c4476c
    ctx->length = 0;
Packit c4476c
    ctx->line_num = 0;
Packit c4476c
    ctx->flags = 0;
Packit c4476c
}
Packit c4476c
Packit c4476c
/*-
Packit c4476c
 * -1 for error
Packit c4476c
 *  0 for last line
Packit c4476c
 *  1 for full line
Packit c4476c
 *
Packit c4476c
 * Note: even though EVP_DecodeUpdate attempts to detect and report end of
Packit c4476c
 * content, the context doesn't currently remember it and will accept more data
Packit c4476c
 * in the next call. Therefore, the caller is responsible for checking and
Packit c4476c
 * rejecting a 0 return value in the middle of content.
Packit c4476c
 *
Packit c4476c
 * Note: even though EVP_DecodeUpdate has historically tried to detect end of
Packit c4476c
 * content based on line length, this has never worked properly. Therefore,
Packit c4476c
 * we now return 0 when one of the following is true:
Packit c4476c
 *   - Padding or B64_EOF was detected and the last block is complete.
Packit c4476c
 *   - Input has zero-length.
Packit c4476c
 * -1 is returned if:
Packit c4476c
 *   - Invalid characters are detected.
Packit c4476c
 *   - There is extra trailing padding, or data after padding.
Packit c4476c
 *   - B64_EOF is detected after an incomplete base64 block.
Packit c4476c
 */
Packit c4476c
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
Packit c4476c
                     const unsigned char *in, int inl)
Packit c4476c
{
Packit c4476c
    int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
Packit c4476c
    unsigned char *d;
Packit c4476c
    const unsigned char *table;
Packit c4476c
Packit c4476c
    n = ctx->num;
Packit c4476c
    d = ctx->enc_data;
Packit c4476c
Packit c4476c
    if (n > 0 && d[n - 1] == '=') {
Packit c4476c
        eof++;
Packit c4476c
        if (n > 1 && d[n - 2] == '=')
Packit c4476c
            eof++;
Packit c4476c
    }
Packit c4476c
Packit c4476c
     /* Legacy behaviour: an empty input chunk signals end of input. */
Packit c4476c
    if (inl == 0) {
Packit c4476c
        rv = 0;
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if ((ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
Packit c4476c
        table = srpdata_ascii2bin;
Packit c4476c
    else
Packit c4476c
        table = data_ascii2bin;
Packit c4476c
Packit c4476c
    for (i = 0; i < inl; i++) {
Packit c4476c
        tmp = *(in++);
Packit c4476c
        v = conv_ascii2bin(tmp, table);
Packit c4476c
        if (v == B64_ERROR) {
Packit c4476c
            rv = -1;
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if (tmp == '=') {
Packit c4476c
            eof++;
Packit c4476c
        } else if (eof > 0 && B64_BASE64(v)) {
Packit c4476c
            /* More data after padding. */
Packit c4476c
            rv = -1;
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if (eof > 2) {
Packit c4476c
            rv = -1;
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if (v == B64_EOF) {
Packit c4476c
            seof = 1;
Packit c4476c
            goto tail;
Packit c4476c
        }
Packit c4476c
Packit c4476c
        /* Only save valid base64 characters. */
Packit c4476c
        if (B64_BASE64(v)) {
Packit c4476c
            if (n >= 64) {
Packit c4476c
                /*
Packit c4476c
                 * We increment n once per loop, and empty the buffer as soon as
Packit c4476c
                 * we reach 64 characters, so this can only happen if someone's
Packit c4476c
                 * manually messed with the ctx. Refuse to write any more data.
Packit c4476c
                 */
Packit c4476c
                rv = -1;
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
            OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
Packit c4476c
            d[n++] = tmp;
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if (n == 64) {
Packit c4476c
            decoded_len = evp_decodeblock_int(ctx, out, d, n);
Packit c4476c
            n = 0;
Packit c4476c
            if (decoded_len < 0 || eof > decoded_len) {
Packit c4476c
                rv = -1;
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
            ret += decoded_len - eof;
Packit c4476c
            out += decoded_len - eof;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    /*
Packit c4476c
     * Legacy behaviour: if the current line is a full base64-block (i.e., has
Packit c4476c
     * 0 mod 4 base64 characters), it is processed immediately. We keep this
Packit c4476c
     * behaviour as applications may not be calling EVP_DecodeFinal properly.
Packit c4476c
     */
Packit c4476c
tail:
Packit c4476c
    if (n > 0) {
Packit c4476c
        if ((n & 3) == 0) {
Packit c4476c
            decoded_len = evp_decodeblock_int(ctx, out, d, n);
Packit c4476c
            n = 0;
Packit c4476c
            if (decoded_len < 0 || eof > decoded_len) {
Packit c4476c
                rv = -1;
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
            ret += (decoded_len - eof);
Packit c4476c
        } else if (seof) {
Packit c4476c
            /* EOF in the middle of a base64 block. */
Packit c4476c
            rv = -1;
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    rv = seof || (n == 0 && eof) ? 0 : 1;
Packit c4476c
end:
Packit c4476c
    /* Legacy behaviour. This should probably rather be zeroed on error. */
Packit c4476c
    *outl = ret;
Packit c4476c
    ctx->num = n;
Packit c4476c
    return rv;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
Packit c4476c
                               const unsigned char *f, int n)
Packit c4476c
{
Packit c4476c
    int i, ret = 0, a, b, c, d;
Packit c4476c
    unsigned long l;
Packit c4476c
    const unsigned char *table;
Packit c4476c
Packit c4476c
    if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
Packit c4476c
        table = srpdata_ascii2bin;
Packit c4476c
    else
Packit c4476c
        table = data_ascii2bin;
Packit c4476c
Packit c4476c
    /* trim white space from the start of the line. */
Packit c4476c
    while ((conv_ascii2bin(*f, table) == B64_WS) && (n > 0)) {
Packit c4476c
        f++;
Packit c4476c
        n--;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    /*
Packit c4476c
     * strip off stuff at the end of the line ascii2bin values B64_WS,
Packit c4476c
     * B64_EOLN, B64_EOLN and B64_EOF
Packit c4476c
     */
Packit c4476c
    while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1], table))))
Packit c4476c
        n--;
Packit c4476c
Packit c4476c
    if (n % 4 != 0)
Packit c4476c
        return -1;
Packit c4476c
Packit c4476c
    for (i = 0; i < n; i += 4) {
Packit c4476c
        a = conv_ascii2bin(*(f++), table);
Packit c4476c
        b = conv_ascii2bin(*(f++), table);
Packit c4476c
        c = conv_ascii2bin(*(f++), table);
Packit c4476c
        d = conv_ascii2bin(*(f++), table);
Packit c4476c
        if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80))
Packit c4476c
            return -1;
Packit c4476c
        l = ((((unsigned long)a) << 18L) |
Packit c4476c
             (((unsigned long)b) << 12L) |
Packit c4476c
             (((unsigned long)c) << 6L) | (((unsigned long)d)));
Packit c4476c
        *(t++) = (unsigned char)(l >> 16L) & 0xff;
Packit c4476c
        *(t++) = (unsigned char)(l >> 8L) & 0xff;
Packit c4476c
        *(t++) = (unsigned char)(l) & 0xff;
Packit c4476c
        ret += 3;
Packit c4476c
    }
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
Packit c4476c
{
Packit c4476c
    return evp_decodeblock_int(NULL, t, f, n);
Packit c4476c
}
Packit c4476c
Packit c4476c
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
Packit c4476c
{
Packit c4476c
    int i;
Packit c4476c
Packit c4476c
    *outl = 0;
Packit c4476c
    if (ctx->num != 0) {
Packit c4476c
        i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num);
Packit c4476c
        if (i < 0)
Packit c4476c
            return -1;
Packit c4476c
        ctx->num = 0;
Packit c4476c
        *outl = i;
Packit c4476c
        return 1;
Packit c4476c
    } else
Packit c4476c
        return 1;
Packit c4476c
}