*) 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>
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=
{
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;
ctx->blockout= 0;
ctx->sigio=1;
+ EVP_MD_CTX_init(&ctx->md);
+
bi->init=0;
bi->ptr=(char *)ctx;
bi->flags=0;
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;
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;
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);
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;
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);
long ret=1;
int i;
- ctx=(BIO_OK_CTX *)b->ptr;
+ ctx=b->ptr;
switch (cmd)
{
case BIO_CTRL_FLUSH:
/* do a final write */
if(ctx->blockout == 0)
- block_out(b);
+ if (!block_out(b))
+ return 0;
while (ctx->blockout)
{
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
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;
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)
{
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 ! */
{
ctx->cont= 0;
}
+ return 1;
+ berr:
+ BIO_clear_retry_flags(b);
+ return 0;
}