Ejemplo n.º 1
0
U8_EXPORT
/* u8_grow_input_stream:
     Arguments: a pointer to an input stream and max buffer size
     Returns: the size of the new buffer

     Doubles the size of the input buffer
*/
ssize_t u8_grow_input_stream(struct U8_INPUT *in,ssize_t to_size)
{
  int owns_buf = ((in->u8_streaminfo)&(U8_STREAM_OWNS_BUF));
  size_t max = in->u8_bufsz, 
    bytes_buffered = in->u8_inlim - in->u8_read,
    bytes_read = in->u8_read - in->u8_inbuf;
  size_t new_max = ((max>=U8_BUF_THROTTLE_POINT)?
                    (max+(U8_BUF_THROTTLE_POINT/2)):
                    (max*2));

  if (to_size<0) to_size=new_max;
  else if ((to_size+U8_BUF_MIN_GROW)<max)
    return max;
  else {}
  while (new_max<to_size) 
    new_max = ((new_max>=U8_BUF_THROTTLE_POINT)?
               (new_max+(U8_BUF_THROTTLE_POINT/2)):
               (new_max*2));
  u8_byte *buf = in->u8_inbuf, *new_buf=NULL;
  /* Reset buffer */
  if (bytes_read>0) {
    memcpy(buf, in->u8_read, bytes_buffered);
    in->u8_read = buf;
    in->u8_inlim -= bytes_read;
    *(in->u8_inlim) = '\0';}
  /* Try to allocate a new buffer */
  new_buf=(owns_buf)?(u8_realloc(buf,new_max)):(u8_malloc(new_max));
  if (new_buf==NULL) {
    size_t shrink_by = (new_max-max)/16;
    while (new_buf==NULL) {
      /* The alloc/realloc call failed, so try smaller sizes */
      errno=0; /* Reset errno */
      /* Shrink until it works or the buffer size is smaller than the
         current value */
      new_max=new_max-shrink_by;
      if (new_max<=max) {
        u8_log(LOGCRIT,"MallocFailed/grow_output",
               "Couldn't grow buffer for input stream");
        return max;}
      u8_log(LOGCRIT,"MemoryRestricted",
             "Couldn't grow u8_input_stream buffer (x%llx) to %lld bytes, trying %lld",
             (long long) in,new_max+shrink_by,new_max);
      new_buf=(owns_buf)?(u8_realloc(in->u8_inbuf,new_max)):
        (u8_malloc(new_max));}}
  if (!(owns_buf)) {
    memcpy(new_buf,buf,bytes_buffered);
    in->u8_streaminfo|=U8_STREAM_OWNS_BUF;}
  in->u8_inbuf=new_buf;
  in->u8_read=new_buf;
  in->u8_inlim=new_buf+bytes_buffered;
  in->u8_bufsz=new_max;
  return new_max;
}
Ejemplo n.º 2
0
U8_EXPORT
/* u8_grab_bytes:
    Arguments: a pointer to a string
    Returns: an ASCII string representation of some number of bytes from a string
*/
char *u8_grab_bytes(u8_string s,int n,char *buf)
{
    char *result=((buf)?(buf):(u8_malloc(n))), *write=result, *lim=result+(n-1);
    const u8_byte *scan=s;
    int c=*scan++;
    while ((c>0)&&(write<lim)) {
        if ((c<128)&&((isprint((char)c))||(c==32))) *write++=c;
        else if ((write+2)>lim) break;
        else if ((c=='\n')||(c=='\t')||(c=='\r')) {
            char *s;
            if (c=='\n') s="\\n";
            else if (c=='\t') s="\\t";
            else s="\\r";
            memcpy(write,s,3);
            write=write+2;
        }
        else if ((write+3)>lim) break;
        else {
            char buf[8];
            sprintf(buf,"%%%02x",c);
            memcpy(write,buf,4);
            write=write+3;
        }
        c=*scan++;
    }
    *write++='\0';
    return result;
}
Ejemplo n.º 3
0
/* Inserts a string at the beginning and before every line break
   in another string */
U8_EXPORT u8_string u8_indent_text(u8_string input,u8_string indent)
{
    int len=strlen(input), n_lines=1, indent_len=strlen(indent);
    const u8_byte *scan=input;
    u8_byte *output;
    while ((scan=strchr(scan+1,'\n'))) n_lines++;
    output=u8_malloc(len+(n_lines*indent_len)+1);
    if (output==NULL) {
        errno=0;
        return NULL;
    }
    else {
        const u8_byte *read=input;
        scan=read;
        u8_byte *write=output;
        while ((scan=strchr(read,'\n'))) {
            int n_bytes=scan-read;
            strncpy(write,read,n_bytes);
            write=write+n_bytes;
            *write++='\n';
            strncpy(write,indent,indent_len);
            write=write+indent_len;
            read=scan+1;
        }
        strcpy(write,read);
        return (u8_string)output;
    }
}
Ejemplo n.º 4
0
U8_EXPORT void u8_grow_contour(u8_contour c)
{
  if (c->u8c_max_blocks==0) {
    c->u8c_blocks=u8_malloc(U8_CONTOUR_INIT_N_BLOCKS*sizeof(void *));
    c->u8c_max_blocks=U8_CONTOUR_INIT_N_BLOCKS;}
  else if ((c->u8c_flags)&(U8_CONTOUR_BLOCKS_MALLOCD)) {
    int new_max=c->u8c_max_blocks*2;
    void **new_blocks=u8_realloc(c->u8c_blocks,new_max*sizeof(void *));
    c->u8c_blocks=new_blocks;
    c->u8c_max_blocks=new_max;}
  else {
    int new_max=c->u8c_max_blocks*2;
    void **new_blocks=u8_malloc(new_max*sizeof(void *));
    memcpy(new_blocks,c->u8c_blocks,sizeof(void *)*(c->u8c_n_blocks));
    c->u8c_blocks=new_blocks;
    c->u8c_max_blocks=new_max;}
}
Ejemplo n.º 5
0
u8_string u8_strndup(u8_string s,int len)
{
  int newlen=len+1;
  newlen=(((newlen%4)==0)?(newlen):(((newlen/4)+1)*4));
  u8_byte *nstring=u8_malloc(newlen);
  strncpy(nstring,s,len); nstring[len]='\0';
  return (u8_string)nstring;
}
Ejemplo n.º 6
0
U8_EXPORT unsigned char *u8_random_vector(int len)
{
  unsigned char *vec=u8_malloc(len);
  if (vec) {
    int i=0; while (i<len) {
      int randomval=u8_random(256);
      vec[i++]=randomval;}
    return vec;}
  else return vec;
}
Ejemplo n.º 7
0
/* This isn't entirely threadsafe */
static void add_cc_cipher(u8_string name,CCAlgorithm alg,CCOptions opts,
			  ssize_t keymin,ssize_t keymax,
			  ssize_t ivlen,ssize_t blocksize)
{
  if (n_ciphers<MAX_CIPHERS) {
    u8_cipher fresh=u8_malloc(sizeof(struct U8_CCCIPHER));
    fresh->cc_name=name; fresh->cc_algorithm=alg; fresh->cc_opts=opts;
    fresh->cc_keymin=keymin; fresh->cc_keymax=keymax;
    fresh->cc_ivlen=ivlen; fresh->cc_blocksize=blocksize;
    ciphers[n_ciphers++]=fresh;}
  else u8_log(LOG_CRIT,_("TooManyCiphers"),"Can't declare cipher#%d %s",
	      n_ciphers,name);
}
Ejemplo n.º 8
0
U8_EXPORT u8_string u8_parse_addr
    (u8_string spec,int *portp,u8_byte *result,ssize_t buflen)
{
  u8_byte *split=strchr(spec,'@'); int len=strlen(spec);
  if ((result==NULL)||(buflen<0)) {
    buflen=len+1; result=u8_malloc(buflen); }
  if (split==spec) {
    *portp=0; strcpy(result,spec+1);
    return result;}
  else if (split) {
    int portlen=split-spec, hostlen=len-(portlen+1);
    u8_byte _portspec[32], *portspec;
    if (portlen>31) portspec=u8_malloc(1+(split-spec));
    else portspec=_portspec;
    strncpy(portspec,spec,portlen); portspec[portlen]='\0';
    *portp=u8_get_portno(portspec);
    if (portspec!=_portspec) u8_free(portspec);
    if (hostlen>=buflen) result=u8_malloc(hostlen+1);
    strncpy(result,split+1,hostlen); result[hostlen]='\0';
    return result;}
  else if ((split=strrchr(spec,':'))) {
    /* We search backwards for the colon because we want to handle
       IPv6 addresses with double colons separating octets (?) */
    if ((split[1]=='\0')||((split>spec)&&(split[-1]==':'))) {
      *portp=0; strcpy(result,spec+1);
      return result;}
    *portp=u8_get_portno(split+1);
    if (buflen<(split-spec)) {
      buflen=(split-spec)+1; result=u8_malloc(buflen);}
    strncpy(result,spec,split-spec);
    if (result[split-spec-1]==':')
      /* Accept a double colon before the port number, in case the address
	 portion is an IPV6 numeric address. */
      result[split-spec-1]='\0';
    else result[split-spec]='\0';
    return result;}
  else return NULL;
}
Ejemplo n.º 9
0
static struct hostent *copy_hostent(struct hostent *he)
{
  struct hostent *copy; char *buf, *alloc;
  int n_bytes=sizeof(struct hostent);
  int addr_len=he->h_length, n_aliases=0, n_addrs=0;
  char **scanner, **writer;
  n_bytes=n_bytes+strlen(he->h_name)+1;
  /* Count the space for the aliases, counting each string. */
  scanner=he->h_aliases; while (*scanner) {
    n_bytes=n_bytes+strlen(*scanner)+1;
    scanner++; n_aliases++;}
  n_bytes=n_bytes+sizeof(char *)*(n_aliases+1);
  scanner=he->h_addr_list; while (*scanner) {
    n_bytes=n_bytes+addr_len;
    scanner++; n_addrs++;}
  n_bytes=n_bytes+sizeof(char *)*(n_addrs+1);
  alloc=buf=u8_malloc(n_bytes);
  copy=(struct hostent *)buf;
  copy->h_length=he->h_length; copy->h_addrtype=he->h_addrtype;
  alloc=buf+sizeof(struct hostent);
  /* Copy aliases */
  writer=copy->h_aliases=(char **) alloc;
  alloc=alloc+sizeof(char *)*(n_aliases+1);
  scanner=he->h_aliases; while (*scanner) {
    int len=strlen(*scanner);
    strcpy(alloc,*scanner);
    *writer++=alloc;
    alloc=alloc+len+1;
    scanner++;}
  *writer++=NULL;
  /* Copy addrs */
  writer=copy->h_addr_list=(char **) alloc;
  alloc=alloc+sizeof(char *)*(n_addrs+1);
  scanner=he->h_addr_list; while (*scanner) {
    memcpy(alloc,*scanner,addr_len);
    *writer++=alloc;
    alloc=alloc+addr_len;
    scanner++;}
  *writer++=NULL;
  /* Copy main name */
  {
    int namelen=strlen(he->h_name);
    strcpy(alloc,he->h_name);
    copy->h_name=alloc;
    alloc=alloc+namelen+1;}
  if (alloc != buf+n_bytes) {
    u8_raise(InternalError,"copy_hostent",NULL);
    return NULL;}
  else return copy;
}
Ejemplo n.º 10
0
U8_EXPORT
/* u8_gets_x:
    Arguments: a pointer to a character buffer, it size, an input stream,
               a terminating string, and a pointer to a size value.
    Returns: a string or NULL.

    Reads UTF-8 u8_inbuf UTF-8 from an input stream up until *eos* (which might be,
    for instance, a newline "\n") or stream end and null-terminates the result.
    If buf is provided and has enough space (according to len), it is used
    for the data.  Otherwise, the function returns NULL.  If buf is NULL,
    a string is allocated with u8_malloc and used to store the results.
    In either case, the number of u8_inbuf needed is stored on the indicated
    size pointer.
*/
u8_string u8_gets_x(u8_byte *buf,int len,
                    struct U8_INPUT *f,u8_string eos,
                    int *sizep)
{
  const u8_byte *found=NULL, *start=f->u8_read, *end=NULL;
  int size, ec=-1;
  if (f->u8_read>=f->u8_inlim) {
    if (sizep) *sizep=0;
    return NULL;}
  while (((found=strstr(start,eos))==NULL)||(found>f->u8_inlim)) {
    int start_pos=f->u8_inlim-f->u8_read, retval=0;
    /* Quit if we have length constraints which
       we are already past. */
    if (f->u8_fillfn) retval=f->u8_fillfn(f);
    if (retval==0) break;
    else if (retval<0) {
      if (sizep) *sizep=retval;
      return NULL;}
    start=f->u8_read+start_pos;}
  if (found) {
    size=(found-f->u8_read);
    if (sizep) *sizep=size;
    /* No data, return NULL */
    if ((buf) && (size>=len)) return NULL;
    else if (buf==NULL) buf=u8_malloc(size+1);
    if (size)
      u8_getn(buf,size,f);
    else buf[0]='\0';
    /* Advance past the separator */
    f->u8_read=f->u8_read+strlen(eos);
    return buf;}
  else return NULL;
}
Ejemplo n.º 11
0
U8_EXPORT
/* u8_slice:
    Arguments: two pointers into a UTF8-encoded string
    Returns: the substring between the pointers
*/
u8_string u8_slice(const u8_byte *start,const u8_byte *end)
{
  if (end<start) return NULL;
  else if (end-start>65536*8) return NULL;
  else {
    unsigned int newlen=(end-start)+1; u8_byte *slice;
    newlen=(((newlen%4)==0)?(newlen):(((newlen/4)+1)*4));
    slice=u8_malloc(newlen);
    strncpy(slice,start,(end-start));
    slice[end-start]='\0';
    return (u8_string)slice;}
}
Ejemplo n.º 12
0
U8_EXPORT struct hostent *u8_gethostbyname(u8_string hname,int type)
{
  char *name=u8_tolibc(hname);
  struct hostent *fetched, *copied;
  char _buf[1024], *buf=_buf;
  int bufsiz=0, herrno=0, retval;
#if HAVE_GETHOSTBYNAME2_R
  struct hostent _fetched, *result; fetched=&_fetched;
  if (type>0)
    retval=
      gethostbyname2_r(name,type,fetched,buf,1024,&result,&herrno);
  else retval=gethostbyname_r(name,fetched,buf,1024,&result,&herrno);
  while (retval==ERANGE) {
    if (bufsiz) bufsiz=2048; else {u8_free(buf); bufsiz=bufsiz*2;}
    buf=u8_malloc(bufsiz);
    if (type>0)
      retval=
	gethostbyname2_r(name,type,fetched,buf,1024,&result,&herrno);
    else retval=gethostbyname_r(name,fetched,buf,1024,&result,&herrno);}
  if (result==NULL) {
    if (bufsiz) u8_free(buf);
    u8_graberr(herrno,"u8_gethostbyname",u8_strdup(hname));
    return NULL;}
  copied=((fetched==NULL) ? (NULL) :(copy_hostent(fetched)));
  if (bufsiz) u8_free(buf);
#else
  u8_lock_mutex(&netfns_lock);
  fetched=gethostbyname(name);
  if (fetched==NULL) {
    u8_seterr(UnknownHost,"u8_gethostbyname",name);
    u8_unlock_mutex(&netfns_lock);
    return NULL;}
  copied=copy_hostent(fetched);
  u8_unlock_mutex(&netfns_lock);
#endif
  u8_free(name);
  return copied;
}
Ejemplo n.º 13
0
U8_EXPORT unsigned char *u8_decrypt
(const unsigned char *input,size_t len,
 const char *cipher,
 const unsigned char *key,size_t keylen,
 const unsigned char *iv,size_t ivlen,
 size_t *result_len)
{
  ssize_t bytecount;
  struct U8_BYTEBUF in, out;
  unsigned char *outbuf=u8_malloc(2*len);
  memset(&in,0,sizeof(in)); memset(&out,0,sizeof(in));
  in.u8_direction=u8_input_buffer;
  in.u8_buf=in.u8_ptr=(u8_byte *)input; in.u8_lim=(u8_byte *)(input+len);
  in.u8_direction=u8_output_buffer; out.u8_growbuf=len;
  out.u8_ptr=out.u8_buf=outbuf; out.u8_lim=outbuf+2*len;
  bytecount=u8_cryptic
    (0,cipher,key,keylen,iv,ivlen,
     (u8_block_reader)u8_bbreader,(u8_block_writer)u8_bbwriter,
     &in,&out,"u8_decrypt");
  if (bytecount<0) return NULL;
  else *result_len=bytecount;
  return out.u8_buf;
}
Ejemplo n.º 14
0
U8_EXPORT ssize_t u8_cryptic
(int do_encrypt,const char *cname,
 const unsigned char *key,int keylen,
 const unsigned char *iv,int ivlen,
 u8_block_reader reader,u8_block_writer writer,
 void *readstate,void *writestate,
 u8_context caller)
{
  if (strncasecmp(cname,"rsa",3)==0) {
    ENGINE *eng=ENGINE_get_default_RSA();
    EVP_PKEY _pkey, *pkey; EVP_PKEY_CTX *ctx; 
    int pubkeyin=(strncasecmp(cname,"rsapub",6)==0);
    const unsigned char *scankey=key;
    struct U8_BYTEBUF bb;
    int retval=-1;
    if (pubkeyin) pkey=d2i_PUBKEY(NULL,&scankey,keylen);
    else pkey=d2i_PrivateKey((EVP_PKEY_RSA),NULL,&scankey,keylen);
    if (!(pkey)) ctx=NULL;
    else {
#if (OPENSSL_VERSION_NUMBER>=0x1000204fL)
      ctx=EVP_PKEY_CTX_new(pkey,eng);
#else
      ctx=EVP_PKEY_CTX_new(pkey,NULL);
#endif
    }
    if (ctx) {
      memset(&bb,0,sizeof(bb));
      bb.u8_direction=u8_output_buffer;
      bb.u8_buf=bb.u8_ptr=(u8_byte *)u8_malloc(1024);
      bb.u8_lim=(u8_byte *)(bb.u8_buf+1024);
      bb.u8_growbuf=1;
      fill_bytebuf(&bb,reader,readstate);}
    if (!(ctx)) {}
    else if ((pubkeyin)?
	     ((do_encrypt)?((retval=EVP_PKEY_encrypt_init(ctx))<0):
	      ((retval=EVP_PKEY_verify_recover_init(ctx))<0)):
	     ((do_encrypt)?((retval=EVP_PKEY_sign_init(ctx))<0):
	      ((retval=EVP_PKEY_decrypt_init(ctx))<0))) {}
    else {
      unsigned char *in=bb.u8_buf; size_t inlen=bb.u8_ptr-bb.u8_buf;
      unsigned char *out=NULL; size_t outlen;
      if (pubkeyin) {
	if (do_encrypt) retval=EVP_PKEY_encrypt(ctx,NULL,&outlen,in,inlen);
	else retval=EVP_PKEY_verify_recover(ctx,NULL,&outlen,in,inlen);}
      else if (do_encrypt) retval=EVP_PKEY_sign(ctx,NULL,&outlen,in,inlen);
      else retval=EVP_PKEY_decrypt(ctx,NULL,&outlen,in,inlen);
      if (retval<0) {}
      else if ((out=u8_malloc(outlen))==NULL) {}
      else if (pubkeyin) {
	if (do_encrypt) retval=EVP_PKEY_encrypt(ctx,out,&outlen,in,inlen);
	else retval=EVP_PKEY_verify_recover(ctx,out,&outlen,in,inlen);}
      else if (do_encrypt) retval=EVP_PKEY_sign(ctx,out,&outlen,in,inlen);
      else retval=EVP_PKEY_decrypt(ctx,out,&outlen,in,inlen);
      if (retval<0) {}
      else retval=writer(out,outlen,writestate);
      if (out) u8_free(out);}
    u8_free(bb.u8_buf);
    if (retval<0) {
      unsigned long err=ERR_get_error(); char buf[512];
      buf[0]='\0'; ERR_error_string_n(err,buf,512);
      u8_seterr(u8_InternalCryptoError,OPENSSL_CRYPTIC,u8_fromlibc((char *)buf));
      ERR_clear_error();}
    if (ctx) EVP_PKEY_CTX_free(ctx);
    if (pkey)  EVP_PKEY_free(pkey);
    return retval;}
  else {
    EVP_CIPHER_CTX ctx;
    int inlen, outlen, retval=0;
    ssize_t totalout=0, totalin=0;
    unsigned char inbuf[1024], outbuf[1024+EVP_MAX_BLOCK_LENGTH];
    const EVP_CIPHER *cipher=((cname)?(EVP_get_cipherbyname(cname)):
			      (EVP_aes_128_cbc()));

    if (cipher) {
      int needkeylen=EVP_CIPHER_key_length(cipher);
      int needivlen=EVP_CIPHER_iv_length(cipher);
      int blocksize=EVP_CIPHER_block_size(cipher);
      if (blocksize>1024) blocksize=1024;
      u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC,
	     " %s cipher=%s, keylen=%d/%d, ivlen=%d/%d, blocksize=%d\n",
	     ((do_encrypt)?("encrypt"):("decrypt")),
	     cname,keylen,needkeylen,ivlen,needivlen,blocksize);

      if ((needivlen)&&(ivlen)&&(ivlen!=needivlen))
	return u8_reterr(u8_BadCryptoIV,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname));

      memset(&ctx,0,sizeof(ctx));

      EVP_CIPHER_CTX_init(&ctx);

      retval=EVP_CipherInit(&ctx, cipher, NULL, NULL, do_encrypt);
      if (retval==0)
	return u8_reterr(u8_CipherInit_Failed,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_strdup(cname));

      retval=EVP_CIPHER_CTX_set_key_length(&ctx,keylen);
      if (retval==0)
	return u8_reterr(u8_BadCryptoKey,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_mkstring("%d!=%d(%s)",keylen,needkeylen,cname));

      if ((needivlen)&&(ivlen!=needivlen))
	return u8_reterr(u8_BadCryptoIV,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname));

      retval=EVP_CipherInit(&ctx, cipher, key, iv, do_encrypt);
      if (retval==0)
	return u8_reterr(u8_CipherInit_Failed,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_strdup(cname));

      while (1) {
	inlen = reader(inbuf,blocksize,readstate);
	if (inlen <= 0) {
	  u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC,
		 "Finished %s(%s) with %ld in, %ld out",
		 ((do_encrypt)?("encrypt"):("decrypt")),
		 cname,totalin,totalout);
	  break;}
	else totalin=totalin+inlen;
	if (!(EVP_CipherUpdate(&ctx,outbuf,&outlen,inbuf,inlen))) {
	  char *details=u8_malloc(256);
	  unsigned long err=ERR_get_error();
	  ERR_error_string_n(err,details,256);
	  EVP_CIPHER_CTX_cleanup(&ctx);
	  return u8_reterr(u8_InternalCryptoError,
			   ((caller)?(caller):((u8_context)"u8_cryptic")),
			   details);}
	else {
	  u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC,
		 "%s(%s) consumed %d/%ld bytes, emitted %d/%ld bytes"
		 " in=<%v>\n out=<%v>",
		 ((do_encrypt)?("encrypt"):("decrypt")),cname,
		 inlen,totalin,outlen,totalout+outlen,
		 inbuf,inlen,outbuf,outlen);
	  writer(outbuf,outlen,writestate);
	  totalout=totalout+outlen;}}
      if (!(EVP_CipherFinal(&ctx,outbuf,&outlen))) {
	char *details=u8_malloc(256);
	unsigned long err=ERR_get_error();
	ERR_error_string_n(err,details,256);
	EVP_CIPHER_CTX_cleanup(&ctx);
	return u8_reterr(u8_InternalCryptoError,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 details);}
      else {
	writer(outbuf,outlen,writestate);
	u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC,
	       "%s(%s) done after consuming %ld/%ld bytes, emitting %ld/%ld bytes"
	       "\n final out=<%v>",
	       ((do_encrypt)?("encrypt"):("decrypt")),cname,
	       inlen,totalin,outlen,totalout+outlen,
	       outbuf,outlen);
	EVP_CIPHER_CTX_cleanup(&ctx);
	totalout=totalout+outlen;
	return totalout;}}
    else {
      char *details=u8_malloc(256);
      unsigned long err=ERR_get_error();
      ERR_error_string_n(err,details,256);
      return u8_reterr("Unknown cipher",
		       ((caller)?(caller):((u8_context)"u8_cryptic")),
		       details);}
  }
}