libidav/crypto.c

changeset 470
6bf798ad3aec
parent 462
efda9aa1bbad
child 478
baa63fef5c5c
--- 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;
+}

mercurial