--- a/libidav/crypto.c Thu Sep 06 12:51:37 2018 +0200 +++ b/libidav/crypto.c Sat Sep 15 11:56:36 2018 +0200 @@ -56,6 +56,10 @@ #endif +int dav_rand_bytes(unsigned char *buf, size_t len) { + return !RAND_bytes(buf, len); +} + AESDecrypter* aes_decrypter_new(DavKey *key, void *stream, dav_write_func write_func) { AESDecrypter *dec = calloc(1, sizeof(AESDecrypter)); SHA256_Init(&dec->sha256); @@ -112,8 +116,8 @@ int outlen = len + 16; unsigned char *out = malloc(outlen); - EVP_DecryptUpdate(dec->ctx, out, &len, buf, len); - ssize_t wlen = dec->write(out, 1, len, dec->stream); + EVP_DecryptUpdate(dec->ctx, out, &outlen, buf, len); + ssize_t wlen = dec->write(out, 1, outlen, dec->stream); SHA256_Update(&dec->sha256, out, wlen); free(out); return (s*n) / s; @@ -344,6 +348,63 @@ return util_hexstr(hash, DAV_SHA256_DIGEST_LENGTH); } +DavKey* dav_pw2key(const char *password, const char *salt, int saltlen, int pwfunc, int enc) { + if(!password) { + return NULL; + } + size_t len = strlen(password); + if(len == 0) { + return NULL; + } + + // setup key data and length + unsigned char keydata[32]; + int keylen = 32; + switch(enc) { + case DAV_KEY_AES128: keylen = 16; break; + case DAV_KEY_AES256: keylen = 32; break; + default: return NULL; + } + + // generate key + switch(pwfunc) { + case DAV_PWFUNC_PBKDF2_SHA256: { + PKCS5_PBKDF2_HMAC( + password, + len, + salt, + saltlen, + DAV_CRYPTO_ITERATION_COUNT, + EVP_sha256(), + keylen, + keydata); + break; + } + case DAV_PWFUNC_PBKDF2_SHA512: { + PKCS5_PBKDF2_HMAC( + password, + len, + salt, + saltlen, + DAV_CRYPTO_ITERATION_COUNT, + EVP_sha512(), + keylen, + keydata); + break; + } + default: return NULL; + } + + // create DavKey with generated data + DavKey *key = malloc(sizeof(DavKey)); + key->data = malloc(keylen); + key->length = keylen; + key->name = NULL; + key->type = enc; + memcpy(key->data, keydata, keylen); + return key; +} + #endif @@ -697,3 +758,46 @@ } #endif + +UcxBuffer* aes_encrypt_buffer(UcxBuffer *in, DavKey *key) { + UcxBuffer *encbuf = ucx_buffer_new( + NULL, + in->size+16, + UCX_BUFFER_AUTOEXTEND); + + AESEncrypter *enc = aes_encrypter_new( + key, + in, + (dav_read_func)ucx_buffer_read); + if(!enc) { + ucx_buffer_free(encbuf); + return NULL; + } + + char buf[1024]; + size_t r; + while((r = aes_read(buf, 1, 1024, enc)) > 0) { + ucx_buffer_write(buf, 1, r, encbuf); + } + aes_encrypter_close(enc); + + encbuf->pos = 0; + return encbuf; +} + +UcxBuffer* aes_decrypt_buffer(UcxBuffer *in, DavKey *key) { + UcxBuffer *decbuf = ucx_buffer_new( + NULL, + in->size, + UCX_BUFFER_AUTOEXTEND); + AESDecrypter *dec = aes_decrypter_new( + key, + decbuf, + (dav_write_func)ucx_buffer_write); + + aes_write(in->space, 1, in->size, dec); + aes_decrypter_shutdown(dec); + aes_decrypter_close(dec); + decbuf->pos = 0; + return decbuf; +}