Example #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;
}
Example #2
0
static int peekc(struct U8_INPUT *f,int fill)
{
  int i, ch, byte, size;
  const u8_byte *start=f->u8_read, *scan=start;
  if (f->u8_read>=f->u8_inlim) {
    if (fill) {
      /* Try to get more data */
      if (f->u8_fillfn) f->u8_fillfn(f);
      /* If you can't, just return */
      if (f->u8_read>=f->u8_inlim) return -1;}
    else return -1;}
  byte=*(f->u8_read);
  if (byte < 0x80) return byte;
  else if (byte < 0xc0) {   /* Catch this error */
    if ((u8_utf8err)||
        ((f->u8_streaminfo&U8_STREAM_UTF8ERR)==U8_STREAM_UTF8ERR)) {
      char *details=u8_grab_bytes(f->u8_read,U8_UTF8BUG_WINDOW,NULL);
      u8_seterr(u8_BadUTF8,"u8_getc",details);
      return -2;}
    else if ((u8_utf8warn)||(f->u8_streaminfo&U8_STREAM_UTF8WARN)) {
      char window[UTF8_BUGWINDOW];
      u8_grab_bytes(scan,UTF8_BUGWINDOW,window);
      u8_log(LOG_WARN,u8_BadUTF8,_("Truncated UTF-8 sequence: '%s'"),window);}
    return 0xFFFD;}
  /* Otherwise, figure out the size and initial byte fragment */
  else if (byte < 0xE0) {size=2; ch=byte&0x1F;}
  else if (byte < 0xF0) {size=3; ch=byte&0x0F;}
  else if (byte < 0xF8) {size=4; ch=byte&0x07;}
  else if (byte < 0xFC) {size=5; ch=byte&0x3;}
  else if (byte < 0xFE) {size=6; ch=byte&0x1;}
  else { /* Bad data, return the character */
    return 0xFFFD;}
  /* Now, we now how many u8_inbuf we need, so we check if we have
     that much data. */
  if (f->u8_read+size>f->u8_inlim) /* Not enough data */
    if (!(fill)) return -1;
    else if (f->u8_fillfn) {
      /* Try to fill the buffer */
      int n_u8_inbuf=f->u8_inlim-f->u8_read;
      while (n_u8_inbuf<size) {
        if (f->u8_fillfn(f)==0) return -1;
        else n_u8_inbuf=f->u8_inlim-f->u8_read;}}
    else return -1;
  else {}
  /* We have enough data, so now we just do a UTF-8 read. */
  i=size=1; scan=f->u8_read;
  while (i) {
    if ((*scan<0x80) || (*scan>=0xC0)) {
      f->u8_read=(u8_byte *)scan;
      if ((u8_utf8err)||
	  ((f->u8_streaminfo&U8_STREAM_UTF8ERR)==U8_STREAM_UTF8ERR)) {
	return u8_reterr(u8_BadUTF8,"u8_getc",u8_strdup(start));}
      else return 0xFFFD;}
    else {ch=(ch<<6)|(*scan&0x3F); scan++; i--;}}
  return ch;
}
Example #3
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);
}
Example #4
0
U8_EXPORT int _u8_getc(struct U8_INPUT *f)
{
  int i, ch, byte, size;
  const u8_byte *scan;
  if (f->u8_read>=f->u8_inlim) {
    /* Try to get more data */
    if (f->u8_fillfn) f->u8_fillfn(f);
    /* If you can't, just return */
    if (f->u8_read>=f->u8_inlim) return -1;}
  byte=*(f->u8_read);
  if (byte < 0x80) {
    f->u8_read++; return byte;}
  else if (byte < 0xc0) {
    /* Unexpected continuation byte */
    if ((u8_utf8err)||
        ((f->u8_streaminfo&U8_STREAM_UTF8ERR)==U8_STREAM_UTF8ERR)) {
      char *details=u8_grab_bytes(f->u8_read,UTF8_BUGWINDOW,NULL);
      u8_log(LOG_WARN,u8_BadUTF8,
             _("Unexpected UTF-8 continuation byte: '%s'"),details);
      u8_seterr(u8_BadUTF8byte,"u8_getc",details);
      (f->u8_read)++;
      return -2;}
    else if ((u8_utf8warn)||
             ((f->u8_streaminfo&U8_STREAM_UTF8WARN)==U8_STREAM_UTF8WARN)) {
      char window[UTF8_BUGWINDOW];
      u8_grab_bytes(f->u8_read,UTF8_BUGWINDOW,window);
      u8_log(LOG_WARN,u8_BadUTF8,
             _("Unexpected UTF-8 continuation byte: '%s'"),window);}
    (f->u8_read)++;
    return 0xFFFD;}
  /* Otherwise, figure out the size and initial byte fragment */
  else if (byte < 0xE0) {size=2; ch=byte&0x1F;}
  else if (byte < 0xF0) {size=3; ch=byte&0x0F;}
  else if (byte < 0xF8) {size=4; ch=byte&0x07;}
  else if (byte < 0xFC) {size=5; ch=byte&0x3;}
  else if (byte < 0xFE) {size=6; ch=byte&0x1;}
  else if ((u8_utf8err)||
           ((f->u8_streaminfo&U8_STREAM_UTF8ERR)==U8_STREAM_UTF8ERR)) {
    char *details=u8_grab_bytes(f->u8_read,UTF8_BUGWINDOW,NULL);
    u8_log(LOG_WARN,u8_BadUTF8,_("Illegal UTF-8 byte: '%s'"),details);
    u8_seterr(u8_BadUTF8byte,"u8_getc",details);
    f->u8_read++;  /* Consume the byte */
    return -2;}
  else { /* Bad data, return the character */
    if ((u8_utf8warn)||
        ((f->u8_streaminfo&U8_STREAM_UTF8WARN)==U8_STREAM_UTF8WARN)) {
      char window[UTF8_BUGWINDOW];
      u8_grab_bytes(f->u8_read,UTF8_BUGWINDOW,window);
      u8_log(LOG_WARN,u8_BadUTF8,_("Illegal UTF-8 byte: '%s'"),window);}
    f->u8_read++;  /* Consume the byte */
    return 0xFFFD;}
  /* Now, we now how many u8_inbuf we need, so we check if we have
     that much data. */
  if (f->u8_read+size>f->u8_inlim) /* Not enough data */
    if (f->u8_fillfn) {
      /* Try to fill the buffer */
      int n_u8_inbuf=f->u8_inlim-f->u8_read;
      while (n_u8_inbuf<size) {
        if (f->u8_fillfn(f)==0) return -1;
        else n_u8_inbuf=f->u8_inlim-f->u8_read;}}
    else return -1;
  else {}
  /* We have enough data, so now we just do a UTF-8 read. */
  i=size-1; f->u8_read++; scan=f->u8_read;
  while (i) {
    if ((*scan<0x80) || (*scan>=0xC0)) {
      if ((u8_utf8err)||
          ((f->u8_streaminfo&U8_STREAM_UTF8ERR)==U8_STREAM_UTF8ERR)) {
        char *details=u8_grab_bytes(scan,UTF8_BUGWINDOW,NULL);
        u8_log(LOG_WARN,u8_BadUTF8,
               _("Truncated UTF-8 sequence: '%s'"),details);
        u8_seterr(u8_TruncatedUTF8,"u8_getc",details);
        f->u8_read=(u8_byte *)scan; /* Consume the bad sequence */
        return -2;}
      else if ((u8_utf8warn)||(f->u8_streaminfo&U8_STREAM_UTF8WARN)) {
        char window[UTF8_BUGWINDOW];
        u8_grab_bytes(scan,UTF8_BUGWINDOW,window);
        u8_log(LOG_WARN,u8_BadUTF8,
               _("Truncated UTF-8 sequence: '%s'"),window);}
      f->u8_read=(u8_byte *)scan; /* Consume the truncated byte sequence */
      return 0xFFFD;}
    else {ch=(ch<<6)|(*scan&0x3F); scan++; i--;}}
  /* And now we update the data structure */
  f->u8_read=(u8_byte *)scan;
  return ch;
}
Example #5
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);}
  }
}
Example #6
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) {
    u8_seterr(_("RSA support NYI"),"u8_cryptic/CommonCrypto",u8_strdup(cname));
    return -1;}
  else {
    CCCryptorRef ctx;
    CCOptions options=0;
    ssize_t inlen, outlen, totalin=0, totalout=0, retval=0;
    unsigned char inbuf[1024], outbuf[1024];
    struct U8_CCCIPHER *cipher=get_cipher(cname);
    if (cipher) {
      size_t blocksize=cipher->cc_blocksize;
      ssize_t needivlen=cipher->cc_ivlen;
      if (!((keylen<=cipher->cc_keymax)&&(keylen>=cipher->cc_keymin)))
	return u8_reterr(u8_BadCryptoKey,
			 ((caller)?(caller):((u8_context)"u8_cryptic")),
			 u8_mkstring("%d!=[%d,%d](%s)",keylen,
				     cipher->cc_keymin,cipher->cc_keymax,
				     cname));
      if ((needivlen)&&(ivlen!=needivlen))
	return u8_reterr(u8_BadCryptoIV,
			 ((caller)?(caller):(COMMONCRYPTO_CRYPTIC)),
			 u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname));

      if (needivlen==0) iv=NULL;

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

      CCCryptorStatus status=CCCryptorCreate
	(((do_encrypt)? (kCCEncrypt) : (kCCDecrypt)),
	 cipher->cc_algorithm,cipher->cc_opts,key,keylen,iv,&ctx);

      u8_log(CRYPTO_LOGLEVEL,COMMONCRYPTO_CRYPTIC,
	     " %s cipher=%s, keylen=%d/[%d,%d], ivlen=%d, blocksize=%d\n",
	     ((do_encrypt)?("encrypt"):("decrypt")),
	     cname,keylen,cipher->cc_keymin,cipher->cc_keymax,
	     ivlen,blocksize);

      while (1) {
	inlen = reader(inbuf,blocksize,readstate);
	if (inlen <= 0) {
	  u8_log(CRYPTO_LOGLEVEL,COMMONCRYPTO_CRYPTIC,
		 "Finished %s(%s) with %ld in, %ld out",
		 ((do_encrypt)?("encrypt"):("decrypt")),cname,
		 totalin,totalout);
	  break;}
	if ((status=CCCryptorUpdate(ctx,inbuf,inlen,outbuf,1024,&outlen))
	    !=kCCSuccess) {
	  CCCryptorRelease(ctx);
	  return u8_reterr(u8_InternalCryptoError,
			   ((caller)?(caller):((u8_context)"u8_cryptic")),
			   NULL);}
	else {
	  u8_log(CRYPTO_LOGLEVEL,COMMONCRYPTO_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 ((status=CCCryptorFinal(ctx,outbuf,1024,&outlen))!=kCCSuccess) {
	CCCryptorRelease(ctx);
	return u8_reterr(u8_InternalCryptoError,
			 ((caller)?(caller):((u8_context)"u8_cryptic")),
			 NULL);}
      else {
	writer(outbuf,outlen,writestate);
	u8_log(CRYPTO_LOGLEVEL,COMMONCRYPTO_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);
	CCCryptorRelease(ctx);
	totalout=totalout+outlen;
	return totalout;}}
    else return u8_reterr("Unknown cipher",
			  ((caller)?(caller):((u8_context)"u8_cryptic")),
			  u8_strdup(cname));
  }
}