U8_EXPORT u8_string u8_host_primary(u8_string hostname) { struct hostent *h=u8_gethostbyname(hostname,-1); if (h==NULL) return NULL; else { u8_string pname=u8_fromlibc(h->h_name); u8_free(h); return pname;} }
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);} } }