make update
[openssl.git] / crypto / evp / bio_ok.c
index e6ff5f2cdb6b2c4015088e7cb2c35031f00c5c33..ad8cad87662c82d4c413ccffcf3bf1b13a0e3ba1 100644 (file)
 
                *) digest is initialized with random seed instead of 
                standardized one.
-               *) same seed is written to ouput
+               *) same seed is written to output
                *) well-known text is then hashed and the output 
                of the digest is also written to output.
 
 
 #include <stdio.h>
 #include <errno.h>
+#include <assert.h>
 #include "cryptlib.h"
 #include <openssl/buffer.h>
 #include <openssl/bio.h>
 #include <openssl/evp.h>
 #include <openssl/rand.h>
 
-static int ok_write(BIO *h,char *buf,int num);
-static int ok_read(BIO *h,char *buf,int size);
-static long ok_ctrl(BIO *h,int cmd,long arg1,char *arg2);
+static int ok_write(BIO *h, const char *buf, int num);
+static int ok_read(BIO *h, char *buf, int size);
+static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2);
 static int ok_new(BIO *h);
 static int ok_free(BIO *data);
-static long ok_callback_ctrl(BIO *h,int cmd,void (*fp)());
+static long ok_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
 
-static void sig_out(BIO* b);
-static void sig_in(BIO* b);
-static void block_out(BIO* b);
-static void block_in(BIO* b);
+static __owur int sig_out(BIO* b);
+static __owur int sig_in(BIO* b);
+static __owur int block_out(BIO* b);
+static __owur int block_in(BIO* b);
 #define OK_BLOCK_SIZE  (1024*4)
 #define OK_BLOCK_BLOCK 4
 #define IOBS           (OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE)
 #define WELLKNOWN "The quick brown fox jumped over the lazy dog's back."
 
-#ifndef L_ENDIAN
-#define swapem(x) \
-       ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
-                            (((unsigned long int)(x) & 0x0000ff00U) <<  8) | \
-                            (((unsigned long int)(x) & 0x00ff0000U) >>  8) | \
-                            (((unsigned long int)(x) & 0xff000000U) >> 24)))
-#else
-#define swapem(x) (x)
-#endif
-
 typedef struct ok_struct
        {
-       int buf_len;
-       int buf_off;
-       int buf_len_save;
-       int buf_off_save;
+       size_t buf_len;
+       size_t buf_off;
+       size_t buf_len_save;
+       size_t buf_off_save;
        int cont;               /* <= 0 when finished */
        int finished;
        EVP_MD_CTX md;
        int blockout;           /* output block is ready */ 
        int sigio;              /* must process signature */
-       char buf[IOBS];
+       unsigned char buf[IOBS];
        } BIO_OK_CTX;
 
 static BIO_METHOD methods_ok=
@@ -187,7 +178,7 @@ static int ok_new(BIO *bi)
        {
        BIO_OK_CTX *ctx;
 
-       ctx=(BIO_OK_CTX *)Malloc(sizeof(BIO_OK_CTX));
+       ctx=(BIO_OK_CTX *)OPENSSL_malloc(sizeof(BIO_OK_CTX));
        if (ctx == NULL) return(0);
 
        ctx->buf_len=0;
@@ -199,6 +190,8 @@ static int ok_new(BIO *bi)
        ctx->blockout= 0;
        ctx->sigio=1;
 
+       EVP_MD_CTX_init(&ctx->md);
+
        bi->init=0;
        bi->ptr=(char *)ctx;
        bi->flags=0;
@@ -208,8 +201,9 @@ static int ok_new(BIO *bi)
 static int ok_free(BIO *a)
        {
        if (a == NULL) return(0);
-       memset(a->ptr,0,sizeof(BIO_OK_CTX));
-       Free(a->ptr);
+       EVP_MD_CTX_cleanup(&((BIO_OK_CTX *)a->ptr)->md);
+       OPENSSL_cleanse(a->ptr,sizeof(BIO_OK_CTX));
+       OPENSSL_free(a->ptr);
        a->ptr=NULL;
        a->init=0;
        a->flags=0;
@@ -272,10 +266,24 @@ static int ok_read(BIO *b, char *out, int outl)
                ctx->buf_len+= i;
 
                /* no signature yet -- check if we got one */
-               if (ctx->sigio == 1) sig_in(b);
+               if (ctx->sigio == 1)
+                       {
+                       if (!sig_in(b))
+                               {
+                               BIO_clear_retry_flags(b);
+                               return 0;
+                               }
+                       }
 
                /* signature ok -- check if we got block */
-               if (ctx->sigio == 0) block_in(b);
+               if (ctx->sigio == 0)
+                       {
+                       if (!block_in(b))
+                               {
+                               BIO_clear_retry_flags(b);
+                               return 0;
+                               }
+                       }
 
                /* invalid block -- cancel */
                if (ctx->cont <= 0) break;
@@ -287,17 +295,20 @@ static int ok_read(BIO *b, char *out, int outl)
        return(ret);
        }
 
-static int ok_write(BIO *b, char *in, int inl)
+static int ok_write(BIO *b, const char *in, int inl)
        {
        int ret=0,n,i;
        BIO_OK_CTX *ctx;
 
+       if (inl <= 0) return inl;
+
        ctx=(BIO_OK_CTX *)b->ptr;
        ret=inl;
 
        if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0);
 
-       if(ctx->sigio) sig_out(b);
+       if(ctx->sigio && !sig_out(b))
+               return 0;
 
        do{
                BIO_clear_retry_flags(b);
@@ -327,7 +338,7 @@ static int ok_write(BIO *b, char *in, int inl)
                if ((in == NULL) || (inl <= 0)) return(0);
 
                n= (inl+ ctx->buf_len > OK_BLOCK_SIZE+ OK_BLOCK_BLOCK) ? 
-                               OK_BLOCK_SIZE+ OK_BLOCK_BLOCK- ctx->buf_len : inl;
+                       (int)(OK_BLOCK_SIZE+OK_BLOCK_BLOCK-ctx->buf_len) : inl;
 
                memcpy((unsigned char *)(&(ctx->buf[ctx->buf_len])),(unsigned char *)in,n);
                ctx->buf_len+= n;
@@ -336,7 +347,11 @@ static int ok_write(BIO *b, char *in, int inl)
 
                if(ctx->buf_len >= OK_BLOCK_SIZE+ OK_BLOCK_BLOCK)
                        {
-                       block_out(b);
+                       if (!block_out(b))
+                               {
+                               BIO_clear_retry_flags(b);
+                               return 0;
+                               }
                        }
        }while(inl > 0);
 
@@ -345,7 +360,7 @@ static int ok_write(BIO *b, char *in, int inl)
        return(ret);
        }
 
-static long ok_ctrl(BIO *b, int cmd, long num, char *ptr)
+static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
        {
        BIO_OK_CTX *ctx;
        EVP_MD *md;
@@ -353,7 +368,7 @@ static long ok_ctrl(BIO *b, int cmd, long num, char *ptr)
        long ret=1;
        int i;
 
-       ctx=(BIO_OK_CTX *)b->ptr;
+       ctx=b->ptr;
 
        switch (cmd)
                {
@@ -383,7 +398,8 @@ static long ok_ctrl(BIO *b, int cmd, long num, char *ptr)
        case BIO_CTRL_FLUSH:
                /* do a final write */
                if(ctx->blockout == 0)
-                       block_out(b);
+                       if (!block_out(b))
+                               return 0;
 
                while (ctx->blockout)
                        {
@@ -411,14 +427,15 @@ static long ok_ctrl(BIO *b, int cmd, long num, char *ptr)
                ret=(long)ctx->cont;
                break;
        case BIO_C_SET_MD:
-               md=(EVP_MD *)ptr;
-               EVP_DigestInit(&(ctx->md),md);
+               md=ptr;
+               if (!EVP_DigestInit_ex(&ctx->md, md, NULL))
+                       return 0;
                b->init=1;
                break;
        case BIO_C_GET_MD:
                if (b->init)
                        {
-                       ppmd=(const EVP_MD **)ptr;
+                       ppmd=ptr;
                        *ppmd=ctx->md.digest;
                        }
                else
@@ -431,7 +448,7 @@ static long ok_ctrl(BIO *b, int cmd, long num, char *ptr)
        return(ret);
        }
 
-static long ok_callback_ctrl(BIO *b, int cmd, void (*fp)())
+static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
        {
        long ret=1;
 
@@ -445,60 +462,75 @@ static long ok_callback_ctrl(BIO *b, int cmd, void (*fp)())
        return(ret);
        }
 
-static void longswap(void *_ptr, int len)
-{
-#ifndef L_ENDIAN
-       int i;
-       char *ptr=_ptr;
+static void longswap(void *_ptr, size_t len)
+{      const union { long one; char little; } is_endian = {1};
 
-       for(i= 0;i < len;i+= 4){
-               *((unsigned long *)&(ptr[i]))= swapem(*((unsigned long *)&(ptr[i])));
+       if (is_endian.little) {
+               size_t i;
+               unsigned char *p=_ptr,c;
+
+               for(i= 0;i < len;i+= 4) {
+                       c=p[0],p[0]=p[3],p[3]=c;
+                       c=p[1],p[1]=p[2],p[2]=c;
+               }
        }
-#endif
 }
 
-static void sig_out(BIO* b)
+static int sig_out(BIO* b)
        {
        BIO_OK_CTX *ctx;
        EVP_MD_CTX *md;
 
-       ctx=(BIO_OK_CTX *)b->ptr;
-       md= &(ctx->md);
+       ctx=b->ptr;
+       md=&ctx->md;
 
-       if(ctx->buf_len+ 2* md->digest->md_size > OK_BLOCK_SIZE) return;
+       if(ctx->buf_len+ 2* md->digest->md_size > OK_BLOCK_SIZE) return 1;
 
-       EVP_DigestInit(md, md->digest);
-       RAND_pseudo_bytes(&(md->md.base[0]), md->digest->md_size);
-       memcpy(&(ctx->buf[ctx->buf_len]), &(md->md.base[0]), md->digest->md_size);
+       if (!EVP_DigestInit_ex(md, md->digest, NULL))
+               goto berr;
+       /* FIXME: there's absolutely no guarantee this makes any sense at all,
+        * particularly now EVP_MD_CTX has been restructured.
+        */
+       RAND_pseudo_bytes(md->md_data, md->digest->md_size);
+       memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size);
        longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size);
        ctx->buf_len+= md->digest->md_size;
 
-       EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN));
-       md->digest->final(&(ctx->buf[ctx->buf_len]), &(md->md.base[0]));
+       if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
+               goto berr;
+       if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
+               goto berr;
        ctx->buf_len+= md->digest->md_size;
        ctx->blockout= 1;
        ctx->sigio= 0;
+       return 1;
+       berr:
+       BIO_clear_retry_flags(b);
+       return 0;
        }
 
-static void sig_in(BIO* b)
+static int sig_in(BIO* b)
        {
        BIO_OK_CTX *ctx;
        EVP_MD_CTX *md;
        unsigned char tmp[EVP_MAX_MD_SIZE];
        int ret= 0;
 
-       ctx=(BIO_OK_CTX *)b->ptr;
-       md= &(ctx->md);
+       ctx=b->ptr;
+       md=&ctx->md;
 
-       if(ctx->buf_len- ctx->buf_off < 2* md->digest->md_size) return;
+       if((int)(ctx->buf_len-ctx->buf_off) < 2*md->digest->md_size) return 1;
 
-       EVP_DigestInit(md, md->digest);
-       memcpy(&(md->md.base[0]), &(ctx->buf[ctx->buf_off]), md->digest->md_size);
-       longswap(&(md->md.base[0]), md->digest->md_size);
+       if (!EVP_DigestInit_ex(md, md->digest, NULL))
+               goto berr;
+       memcpy(md->md_data, &(ctx->buf[ctx->buf_off]), md->digest->md_size);
+       longswap(md->md_data, md->digest->md_size);
        ctx->buf_off+= md->digest->md_size;
 
-       EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN));
-       md->digest->final(tmp, &(md->md.base[0]));
+       if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN)))
+               goto berr;
+       if (!EVP_DigestFinal_ex(md, tmp, NULL))
+               goto berr;
        ret= memcmp(&(ctx->buf[ctx->buf_off]), tmp, md->digest->md_size) == 0;
        ctx->buf_off+= md->digest->md_size;
        if(ret == 1)
@@ -515,43 +547,62 @@ static void sig_in(BIO* b)
                {
                ctx->cont= 0;
                }
+       return 1;
+       berr:
+       BIO_clear_retry_flags(b);
+       return 0;
        }
 
-static void block_out(BIO* b)
+static int block_out(BIO* b)
        {
        BIO_OK_CTX *ctx;
        EVP_MD_CTX *md;
        unsigned long tl;
 
-       ctx=(BIO_OK_CTX *)b->ptr;
-       md= &(ctx->md);
+       ctx=b->ptr;
+       md=&ctx->md;
 
        tl= ctx->buf_len- OK_BLOCK_BLOCK;
-       tl= swapem(tl);
-       memcpy(ctx->buf, &tl, OK_BLOCK_BLOCK);
-       tl= swapem(tl);
-       EVP_DigestUpdate(md, (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl);
-       md->digest->final(&(ctx->buf[ctx->buf_len]), &(md->md.base[0]));
+       ctx->buf[0]=(unsigned char)(tl>>24);
+       ctx->buf[1]=(unsigned char)(tl>>16);
+       ctx->buf[2]=(unsigned char)(tl>>8);
+       ctx->buf[3]=(unsigned char)(tl);
+       if (!EVP_DigestUpdate(md,
+               (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl))
+               goto berr;
+       if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL))
+               goto berr;
        ctx->buf_len+= md->digest->md_size;
        ctx->blockout= 1;
+       return 1;
+       berr:
+       BIO_clear_retry_flags(b);
+       return 0;
        }
 
-static void block_in(BIO* b)
+static int block_in(BIO* b)
        {
        BIO_OK_CTX *ctx;
        EVP_MD_CTX *md;
-       long tl= 0;
+       unsigned long tl= 0;
        unsigned char tmp[EVP_MAX_MD_SIZE];
 
-       ctx=(BIO_OK_CTX *)b->ptr;
-       md= &(ctx->md);
+       ctx=b->ptr;
+       md=&ctx->md;
+
+       assert(sizeof(tl)>=OK_BLOCK_BLOCK);     /* always true */
+       tl =ctx->buf[0]; tl<<=8;
+       tl|=ctx->buf[1]; tl<<=8;
+       tl|=ctx->buf[2]; tl<<=8;
+       tl|=ctx->buf[3];
 
-       memcpy(&tl, ctx->buf, OK_BLOCK_BLOCK);
-       tl= swapem(tl);
-       if (ctx->buf_len < tl+ OK_BLOCK_BLOCK+ md->digest->md_size) return;
+       if (ctx->buf_len < tl+ OK_BLOCK_BLOCK+ md->digest->md_size) return 1;
  
-       EVP_DigestUpdate(md, (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl);
-       md->digest->final(tmp, &(md->md.base[0]));
+       if (!EVP_DigestUpdate(md,
+                       (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl))
+               goto berr;
+       if (!EVP_DigestFinal_ex(md, tmp, NULL))
+               goto berr;
        if(memcmp(&(ctx->buf[tl+ OK_BLOCK_BLOCK]), tmp, md->digest->md_size) == 0)
                {
                /* there might be parts from next block lurking around ! */
@@ -565,5 +616,9 @@ static void block_in(BIO* b)
                {
                ctx->cont= 0;
                }
+       return 1;
+       berr:
+       BIO_clear_retry_flags(b);
+       return 0;
        }