If input is bad, we still need to clear the buffer.
[openssl.git] / crypto / evp / encode.c
index 7cd65244e652fc7a5aefea12950f8a3be6d384c7..2d738f4b0108fb8c0f98301d2080426dce7f8424 100644 (file)
@@ -1,5 +1,5 @@
 /* crypto/evp/encode.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
 
 #include <stdio.h>
 #include "cryptlib.h"
-#include "evp.h"
+#include <openssl/evp.h>
 
+#ifndef CHARSET_EBCDIC
 #define conv_bin2ascii(a)      (data_bin2ascii[(a)&0x3f])
 #define conv_ascii2bin(a)      (data_ascii2bin[(a)&0x7f])
+#else
+/* We assume that PEM encoded files are EBCDIC files
+ * (i.e., printable text files). Convert them here while decoding.
+ * When encoding, output is EBCDIC (text) format again.
+ * (No need for conversion in the conv_bin2ascii macro, as the
+ * underlying textstring data_bin2ascii[] is already EBCDIC)
+ */
+#define conv_bin2ascii(a)      (data_bin2ascii[(a)&0x3f])
+#define conv_ascii2bin(a)      (data_ascii2bin[os_toascii[a]&0x7f])
+#endif
 
 /* 64 char lines
  * pad input with 0
@@ -110,26 +121,22 @@ static unsigned char data_ascii2bin[128]={
        0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,
        };
 
-void EVP_EncodeInit(ctx)
-EVP_ENCODE_CTX *ctx;
+void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
        {
        ctx->length=48;
        ctx->num=0;
        ctx->line_num=0;
        }
 
-void EVP_EncodeUpdate(ctx,out,outl,in,inl)
-EVP_ENCODE_CTX *ctx;
-unsigned char *out;
-int *outl;
-unsigned char *in;
-int inl;
+void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
+            const unsigned char *in, int inl)
        {
        int i,j;
        unsigned int total=0;
 
        *outl=0;
        if (inl == 0) return;
+       OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
        if ((ctx->num+inl) < ctx->length)
                {
                memcpy(&(ctx->enc_data[ctx->num]),in,inl);
@@ -165,10 +172,7 @@ int inl;
        *outl=total;
        }
 
-void EVP_EncodeFinal(ctx,out,outl)
-EVP_ENCODE_CTX *ctx;
-unsigned char *out;
-int *outl;
+void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
        {
        unsigned int ret=0;
 
@@ -182,9 +186,7 @@ int *outl;
        *outl=ret;
        }
 
-int EVP_EncodeBlock(t,f,dlen)
-unsigned char *t,*f;
-int dlen;
+int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
        {
        int i,ret=0;
        unsigned long l;
@@ -218,31 +220,28 @@ int dlen;
        return(ret);
        }
 
-void EVP_DecodeInit(ctx)
-EVP_ENCODE_CTX *ctx;
+void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
        {
        ctx->length=30;
        ctx->num=0;
        ctx->line_num=0;
+       ctx->expect_nl=0;
        }
 
 /* -1 for error
  *  0 for last line
  *  1 for full line
  */
-int EVP_DecodeUpdate(ctx,out,outl,in,inl)
-EVP_ENCODE_CTX *ctx;
-unsigned char *out;
-int *outl;
-unsigned char *in;
-int inl;
+int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
+            const unsigned char *in, int inl)
        {
-       int seof= -1,eof=0,rv= -1,ret=0,i,v,tmp,n,ln,tmp2;
+       int seof= -1,eof=0,rv= -1,ret=0,i,v,tmp,n,ln,tmp2,exp_nl;
        unsigned char *d;
 
        n=ctx->num;
        d=ctx->enc_data;
        ln=ctx->line_num;
+       exp_nl=ctx->expect_nl;
 
        /* last line of input. */
        if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF)))
@@ -260,6 +259,7 @@ int inl;
                /* only save the good data :-) */
                if (!B64_NOT_BASE64(v))
                        {
+                       OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
                        d[n++]=tmp;
                        ln++;
                        }
@@ -279,22 +279,52 @@ int inl;
                        eof++;
                        }
 
+               if (v == B64_CR)
+                       {
+                       ln = 0;
+                       if (exp_nl)
+                               continue;
+                       }
+
                /* eoln */
-               if (v == B64_EOLN) ln=0;
+               if (v == B64_EOLN)
+                       {
+                       ln=0;
+                       if (exp_nl)
+                               {
+                               exp_nl=0;
+                               continue;
+                               }
+                       }
+               exp_nl=0;
 
                /* If we are at the end of input and it looks like a
                 * line, process it. */
                if (((i+1) == inl) && (((n&3) == 0) || eof))
+                       {
                        v=B64_EOF;
+                       /* In case things were given us in really small
+                          records (so two '=' were given in separate
+                          updates), eof may contain the incorrect number
+                          of ending bytes to skip, so let's redo the count */
+                       eof = 0;
+                       if (d[n-1] == '=') eof++;
+                       if (d[n-2] == '=') eof++;
+                       /* There will never be more than two '=' */
+                       }
 
                if ((v == B64_EOF) || (n >= 64))
                        {
+                       /* This is needed to work correctly on 64 byte input
+                        * lines.  We process the line and then need to
+                        * accept the '\n' */
+                       if ((v != B64_EOF) && (n >= 64)) exp_nl=1;
                        tmp2=v;
                        if (n > 0)
                                {
                                v=EVP_DecodeBlock(out,d,n);
-                               if (v < 0) { rv=0; goto end; }
                                n=0;
+                               if (v < 0) { rv=0; goto end; }
                                ret+=(v-eof);
                                }
                        else
@@ -322,12 +352,11 @@ end:
        *outl=ret;
        ctx->num=n;
        ctx->line_num=ln;
+       ctx->expect_nl=exp_nl;
        return(rv);
        }
 
-int EVP_DecodeBlock(t,f,n)
-unsigned char *t,*f;
-int n;
+int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
        {
        int i,ret=0,a,b,c,d;
        unsigned long l;
@@ -367,10 +396,7 @@ int n;
        return(ret);
        }
 
-int EVP_DecodeFinal(ctx,out,outl)
-EVP_ENCODE_CTX *ctx;
-unsigned char *out;
-int *outl;
+int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
        {
        int i;
 
@@ -388,9 +414,7 @@ int *outl;
        }
 
 #ifdef undef
-int EVP_DecodeValid(buf,len)
-unsigned char *buf;
-int len;
+int EVP_DecodeValid(unsigned char *buf, int len)
        {
        int i,num=0,bad=0;