155714Skris/* crypto/evp/encode.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296341Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296341Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296341Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296341Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296341Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
60299068Sdelphij#include <limits.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/evp.h>
6355714Skris
6455714Skris#ifndef CHARSET_EBCDIC
65296341Sdelphij# define conv_bin2ascii(a)       (data_bin2ascii[(a)&0x3f])
66296341Sdelphij# define conv_ascii2bin(a)       (data_ascii2bin[(a)&0x7f])
6755714Skris#else
68296341Sdelphij/*
69296341Sdelphij * We assume that PEM encoded files are EBCDIC files (i.e., printable text
70296341Sdelphij * files). Convert them here while decoding. When encoding, output is EBCDIC
71296341Sdelphij * (text) format again. (No need for conversion in the conv_bin2ascii macro,
72296341Sdelphij * as the underlying textstring data_bin2ascii[] is already EBCDIC)
7355714Skris */
74296341Sdelphij# define conv_bin2ascii(a)       (data_bin2ascii[(a)&0x3f])
75296341Sdelphij# define conv_ascii2bin(a)       (data_ascii2bin[os_toascii[a]&0x7f])
7655714Skris#endif
7755714Skris
78296341Sdelphij/*-
79296341Sdelphij * 64 char lines
8055714Skris * pad input with 0
8155714Skris * left over chars are set to =
8255714Skris * 1 byte  => xx==
8355714Skris * 2 bytes => xxx=
8455714Skris * 3 bytes => xxxx
8555714Skris */
8655714Skris#define BIN_PER_LINE    (64/4*3)
8755714Skris#define CHUNKS_PER_LINE (64/4)
8855714Skris#define CHAR_PER_LINE   (64+1)
8955714Skris
90296341Sdelphijstatic const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
9155714Skrisabcdefghijklmnopqrstuvwxyz0123456789+/";
9255714Skris
93296341Sdelphij/*-
94296341Sdelphij * 0xF0 is a EOLN
9555714Skris * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
9655714Skris * 0xF2 is EOF
9755714Skris * 0xE0 is ignore at start of line.
9855714Skris * 0xFF is error
9955714Skris */
10055714Skris
101296341Sdelphij#define B64_EOLN                0xF0
102296341Sdelphij#define B64_CR                  0xF1
103296341Sdelphij#define B64_EOF                 0xF2
104296341Sdelphij#define B64_WS                  0xE0
105296341Sdelphij#define B64_ERROR               0xFF
106296341Sdelphij#define B64_NOT_BASE64(a)       (((a)|0x13) == 0xF3)
10755714Skris
108296341Sdelphijstatic const unsigned char data_ascii2bin[128] = {
109296341Sdelphij    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
110296341Sdelphij    0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
111296341Sdelphij    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
112296341Sdelphij    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
113296341Sdelphij    0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
114296341Sdelphij    0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
115296341Sdelphij    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
116296341Sdelphij    0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
117296341Sdelphij    0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
118296341Sdelphij    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
119296341Sdelphij    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
120296341Sdelphij    0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
121296341Sdelphij    0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
122296341Sdelphij    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
123296341Sdelphij    0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
124296341Sdelphij    0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
125296341Sdelphij};
12655714Skris
12755714Skrisvoid EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
128296341Sdelphij{
129296341Sdelphij    ctx->length = 48;
130296341Sdelphij    ctx->num = 0;
131296341Sdelphij    ctx->line_num = 0;
132296341Sdelphij}
13355714Skris
13455714Skrisvoid EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
135296341Sdelphij                      const unsigned char *in, int inl)
136296341Sdelphij{
137296341Sdelphij    int i, j;
138299068Sdelphij    size_t total = 0;
13955714Skris
140296341Sdelphij    *outl = 0;
141296341Sdelphij    if (inl <= 0)
142296341Sdelphij        return;
143296341Sdelphij    OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
144299068Sdelphij    if (ctx->length - ctx->num > inl) {
145296341Sdelphij        memcpy(&(ctx->enc_data[ctx->num]), in, inl);
146296341Sdelphij        ctx->num += inl;
147296341Sdelphij        return;
148296341Sdelphij    }
149296341Sdelphij    if (ctx->num != 0) {
150296341Sdelphij        i = ctx->length - ctx->num;
151296341Sdelphij        memcpy(&(ctx->enc_data[ctx->num]), in, i);
152296341Sdelphij        in += i;
153296341Sdelphij        inl -= i;
154296341Sdelphij        j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
155296341Sdelphij        ctx->num = 0;
156296341Sdelphij        out += j;
157296341Sdelphij        *(out++) = '\n';
158296341Sdelphij        *out = '\0';
159296341Sdelphij        total = j + 1;
160296341Sdelphij    }
161299068Sdelphij    while (inl >= ctx->length && total <= INT_MAX) {
162296341Sdelphij        j = EVP_EncodeBlock(out, in, ctx->length);
163296341Sdelphij        in += ctx->length;
164296341Sdelphij        inl -= ctx->length;
165296341Sdelphij        out += j;
166296341Sdelphij        *(out++) = '\n';
167296341Sdelphij        *out = '\0';
168296341Sdelphij        total += j + 1;
169296341Sdelphij    }
170299068Sdelphij    if (total > INT_MAX) {
171299068Sdelphij        /* Too much output data! */
172299068Sdelphij        *outl = 0;
173299068Sdelphij        return;
174299068Sdelphij    }
175296341Sdelphij    if (inl != 0)
176296341Sdelphij        memcpy(&(ctx->enc_data[0]), in, inl);
177296341Sdelphij    ctx->num = inl;
178296341Sdelphij    *outl = total;
179296341Sdelphij}
18055714Skris
18155714Skrisvoid EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
182296341Sdelphij{
183296341Sdelphij    unsigned int ret = 0;
18455714Skris
185296341Sdelphij    if (ctx->num != 0) {
186296341Sdelphij        ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
187296341Sdelphij        out[ret++] = '\n';
188296341Sdelphij        out[ret] = '\0';
189296341Sdelphij        ctx->num = 0;
190296341Sdelphij    }
191296341Sdelphij    *outl = ret;
192296341Sdelphij}
19355714Skris
19459191Skrisint EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
195296341Sdelphij{
196296341Sdelphij    int i, ret = 0;
197296341Sdelphij    unsigned long l;
19855714Skris
199296341Sdelphij    for (i = dlen; i > 0; i -= 3) {
200296341Sdelphij        if (i >= 3) {
201296341Sdelphij            l = (((unsigned long)f[0]) << 16L) |
202296341Sdelphij                (((unsigned long)f[1]) << 8L) | f[2];
203296341Sdelphij            *(t++) = conv_bin2ascii(l >> 18L);
204296341Sdelphij            *(t++) = conv_bin2ascii(l >> 12L);
205296341Sdelphij            *(t++) = conv_bin2ascii(l >> 6L);
206296341Sdelphij            *(t++) = conv_bin2ascii(l);
207296341Sdelphij        } else {
208296341Sdelphij            l = ((unsigned long)f[0]) << 16L;
209296341Sdelphij            if (i == 2)
210296341Sdelphij                l |= ((unsigned long)f[1] << 8L);
21155714Skris
212296341Sdelphij            *(t++) = conv_bin2ascii(l >> 18L);
213296341Sdelphij            *(t++) = conv_bin2ascii(l >> 12L);
214296341Sdelphij            *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
215296341Sdelphij            *(t++) = '=';
216296341Sdelphij        }
217296341Sdelphij        ret += 4;
218296341Sdelphij        f += 3;
219296341Sdelphij    }
22055714Skris
221296341Sdelphij    *t = '\0';
222296341Sdelphij    return (ret);
223296341Sdelphij}
22455714Skris
22555714Skrisvoid EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
226296341Sdelphij{
227296341Sdelphij    ctx->length = 30;
228296341Sdelphij    ctx->num = 0;
229296341Sdelphij    ctx->line_num = 0;
230296341Sdelphij    ctx->expect_nl = 0;
231296341Sdelphij}
23255714Skris
233296341Sdelphij/*-
234296341Sdelphij * -1 for error
23555714Skris *  0 for last line
23655714Skris *  1 for full line
23755714Skris */
23855714Skrisint EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
239296341Sdelphij                     const unsigned char *in, int inl)
240296341Sdelphij{
241296341Sdelphij    int seof = -1, eof = 0, rv = -1, ret = 0, i, v, tmp, n, ln, exp_nl;
242296341Sdelphij    unsigned char *d;
24355714Skris
244296341Sdelphij    n = ctx->num;
245296341Sdelphij    d = ctx->enc_data;
246296341Sdelphij    ln = ctx->line_num;
247296341Sdelphij    exp_nl = ctx->expect_nl;
24855714Skris
249296341Sdelphij    /* last line of input. */
250296341Sdelphij    if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) {
251296341Sdelphij        rv = 0;
252296341Sdelphij        goto end;
253296341Sdelphij    }
25455714Skris
255296341Sdelphij    /* We parse the input data */
256296341Sdelphij    for (i = 0; i < inl; i++) {
257296341Sdelphij        /* If the current line is > 80 characters, scream alot */
258296341Sdelphij        if (ln >= 80) {
259296341Sdelphij            rv = -1;
260296341Sdelphij            goto end;
261296341Sdelphij        }
26255714Skris
263296341Sdelphij        /* Get char and put it into the buffer */
264296341Sdelphij        tmp = *(in++);
265296341Sdelphij        v = conv_ascii2bin(tmp);
266296341Sdelphij        /* only save the good data :-) */
267296341Sdelphij        if (!B64_NOT_BASE64(v)) {
268296341Sdelphij            OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
269296341Sdelphij            d[n++] = tmp;
270296341Sdelphij            ln++;
271296341Sdelphij        } else if (v == B64_ERROR) {
272296341Sdelphij            rv = -1;
273296341Sdelphij            goto end;
274296341Sdelphij        }
27555714Skris
276296341Sdelphij        /*
277296341Sdelphij         * have we seen a '=' which is 'definitly' the last input line.  seof
278296341Sdelphij         * will point to the character that holds it. and eof will hold how
279296341Sdelphij         * many characters to chop off.
280296341Sdelphij         */
281296341Sdelphij        if (tmp == '=') {
282296341Sdelphij            if (seof == -1)
283296341Sdelphij                seof = n;
284296341Sdelphij            eof++;
285296341Sdelphij        }
286100928Snectar
287296341Sdelphij        if (v == B64_CR) {
288296341Sdelphij            ln = 0;
289296341Sdelphij            if (exp_nl)
290296341Sdelphij                continue;
291296341Sdelphij        }
29255714Skris
293296341Sdelphij        /* eoln */
294296341Sdelphij        if (v == B64_EOLN) {
295296341Sdelphij            ln = 0;
296296341Sdelphij            if (exp_nl) {
297296341Sdelphij                exp_nl = 0;
298296341Sdelphij                continue;
299296341Sdelphij            }
300296341Sdelphij        }
301296341Sdelphij        exp_nl = 0;
30255714Skris
303296341Sdelphij        /*
304296341Sdelphij         * If we are at the end of input and it looks like a line, process
305296341Sdelphij         * it.
306296341Sdelphij         */
307296341Sdelphij        if (((i + 1) == inl) && (((n & 3) == 0) || eof)) {
308296341Sdelphij            v = B64_EOF;
309296341Sdelphij            /*
310296341Sdelphij             * In case things were given us in really small records (so two
311296341Sdelphij             * '=' were given in separate updates), eof may contain the
312296341Sdelphij             * incorrect number of ending bytes to skip, so let's redo the
313296341Sdelphij             * count
314296341Sdelphij             */
315296341Sdelphij            eof = 0;
316296341Sdelphij            if (d[n - 1] == '=')
317296341Sdelphij                eof++;
318296341Sdelphij            if (d[n - 2] == '=')
319296341Sdelphij                eof++;
320296341Sdelphij            /* There will never be more than two '=' */
321296341Sdelphij        }
32255714Skris
323296341Sdelphij        if ((v == B64_EOF && (n & 3) == 0) || (n >= 64)) {
324296341Sdelphij            /*
325296341Sdelphij             * This is needed to work correctly on 64 byte input lines.  We
326296341Sdelphij             * process the line and then need to accept the '\n'
327296341Sdelphij             */
328296341Sdelphij            if ((v != B64_EOF) && (n >= 64))
329296341Sdelphij                exp_nl = 1;
330296341Sdelphij            if (n > 0) {
331296341Sdelphij                v = EVP_DecodeBlock(out, d, n);
332296341Sdelphij                n = 0;
333296341Sdelphij                if (v < 0) {
334296341Sdelphij                    rv = 0;
335296341Sdelphij                    goto end;
336296341Sdelphij                }
337296341Sdelphij                if (eof > v) {
338296341Sdelphij                    rv = -1;
339296341Sdelphij                    goto end;
340296341Sdelphij                }
341296341Sdelphij                ret += (v - eof);
342296341Sdelphij            } else {
343296341Sdelphij                eof = 1;
344296341Sdelphij                v = 0;
345296341Sdelphij            }
34655714Skris
347296341Sdelphij            /*
348296341Sdelphij             * This is the case where we have had a short but valid input
349296341Sdelphij             * line
350296341Sdelphij             */
351296341Sdelphij            if ((v < ctx->length) && eof) {
352296341Sdelphij                rv = 0;
353296341Sdelphij                goto end;
354296341Sdelphij            } else
355296341Sdelphij                ctx->length = v;
35655714Skris
357296341Sdelphij            if (seof >= 0) {
358296341Sdelphij                rv = 0;
359296341Sdelphij                goto end;
360296341Sdelphij            }
361296341Sdelphij            out += v;
362296341Sdelphij        }
363296341Sdelphij    }
364296341Sdelphij    rv = 1;
365296341Sdelphij end:
366296341Sdelphij    *outl = ret;
367296341Sdelphij    ctx->num = n;
368296341Sdelphij    ctx->line_num = ln;
369296341Sdelphij    ctx->expect_nl = exp_nl;
370296341Sdelphij    return (rv);
371296341Sdelphij}
372296341Sdelphij
37359191Skrisint EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
374296341Sdelphij{
375296341Sdelphij    int i, ret = 0, a, b, c, d;
376296341Sdelphij    unsigned long l;
37755714Skris
378296341Sdelphij    /* trim white space from the start of the line. */
379296341Sdelphij    while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
380296341Sdelphij        f++;
381296341Sdelphij        n--;
382296341Sdelphij    }
38355714Skris
384296341Sdelphij    /*
385296341Sdelphij     * strip off stuff at the end of the line ascii2bin values B64_WS,
386296341Sdelphij     * B64_EOLN, B64_EOLN and B64_EOF
387296341Sdelphij     */
388296341Sdelphij    while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1]))))
389296341Sdelphij        n--;
39055714Skris
391296341Sdelphij    if (n % 4 != 0)
392296341Sdelphij        return (-1);
39355714Skris
394296341Sdelphij    for (i = 0; i < n; i += 4) {
395296341Sdelphij        a = conv_ascii2bin(*(f++));
396296341Sdelphij        b = conv_ascii2bin(*(f++));
397296341Sdelphij        c = conv_ascii2bin(*(f++));
398296341Sdelphij        d = conv_ascii2bin(*(f++));
399296341Sdelphij        if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80))
400296341Sdelphij            return (-1);
401296341Sdelphij        l = ((((unsigned long)a) << 18L) |
402296341Sdelphij             (((unsigned long)b) << 12L) |
403296341Sdelphij             (((unsigned long)c) << 6L) | (((unsigned long)d)));
404296341Sdelphij        *(t++) = (unsigned char)(l >> 16L) & 0xff;
405296341Sdelphij        *(t++) = (unsigned char)(l >> 8L) & 0xff;
406296341Sdelphij        *(t++) = (unsigned char)(l) & 0xff;
407296341Sdelphij        ret += 3;
408296341Sdelphij    }
409296341Sdelphij    return (ret);
410296341Sdelphij}
41155714Skris
41255714Skrisint EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
413296341Sdelphij{
414296341Sdelphij    int i;
41555714Skris
416296341Sdelphij    *outl = 0;
417296341Sdelphij    if (ctx->num != 0) {
418296341Sdelphij        i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
419296341Sdelphij        if (i < 0)
420296341Sdelphij            return (-1);
421296341Sdelphij        ctx->num = 0;
422296341Sdelphij        *outl = i;
423296341Sdelphij        return (1);
424296341Sdelphij    } else
425296341Sdelphij        return (1);
426296341Sdelphij}
42755714Skris
42855714Skris#ifdef undef
42955714Skrisint EVP_DecodeValid(unsigned char *buf, int len)
430296341Sdelphij{
431296341Sdelphij    int i, num = 0, bad = 0;
43255714Skris
433296341Sdelphij    if (len == 0)
434296341Sdelphij        return (-1);
435296341Sdelphij    while (conv_ascii2bin(*buf) == B64_WS) {
436296341Sdelphij        buf++;
437296341Sdelphij        len--;
438296341Sdelphij        if (len == 0)
439296341Sdelphij            return (-1);
440296341Sdelphij    }
44155714Skris
442296341Sdelphij    for (i = len; i >= 4; i -= 4) {
443296341Sdelphij        if ((conv_ascii2bin(buf[0]) >= 0x40) ||
444296341Sdelphij            (conv_ascii2bin(buf[1]) >= 0x40) ||
445296341Sdelphij            (conv_ascii2bin(buf[2]) >= 0x40) ||
446296341Sdelphij            (conv_ascii2bin(buf[3]) >= 0x40))
447296341Sdelphij            return (-1);
448296341Sdelphij        buf += 4;
449296341Sdelphij        num += 1 + (buf[2] != '=') + (buf[3] != '=');
450296341Sdelphij    }
451296341Sdelphij    if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN))
452296341Sdelphij        return (num);
453296341Sdelphij    if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) &&
454296341Sdelphij        (conv_ascii2bin(buf[0]) == B64_EOLN))
455296341Sdelphij        return (num);
456296341Sdelphij    return (1);
457296341Sdelphij}
45855714Skris#endif
459