added checksums for encrypted resources

Sun, 04 Oct 2015 15:57:40 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 04 Oct 2015 15:57:40 +0200
changeset 150
37fb12574acd
parent 149
509e9e1cbdcc
child 151
a316613205dc

added checksums for encrypted resources

dav/config.c file | annotate | diff | comparison | revisions
dav/main.c file | annotate | diff | comparison | revisions
libidav/crypto.c file | annotate | diff | comparison | revisions
libidav/crypto.h file | annotate | diff | comparison | revisions
libidav/davqlexec.c file | annotate | diff | comparison | revisions
libidav/methods.c file | annotate | diff | comparison | revisions
libidav/methods.h file | annotate | diff | comparison | revisions
libidav/resource.c file | annotate | diff | comparison | revisions
libidav/resource.h file | annotate | diff | comparison | revisions
libidav/session.c file | annotate | diff | comparison | revisions
libidav/utils.c file | annotate | diff | comparison | revisions
libidav/utils.h file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
--- a/dav/config.c	Sat Oct 03 20:10:54 2015 +0200
+++ b/dav/config.c	Sun Oct 04 15:57:40 2015 +0200
@@ -302,6 +302,7 @@
     Key *key = calloc(1, sizeof(Key));
     key->type = KEY_AES256;
     
+    int error = 0;
     while(node) {
         if(node->type == XML_ELEMENT_NODE) {
             char *value = util_xml_get_text(node);
@@ -315,6 +316,9 @@
                 if(key_data.length > 0) {
                     key->data = key_data.ptr;
                     key->length = key_data.length;
+                } else {
+                    fprintf(stderr, "Error: Cannot key from file: %s\n", value);
+                    error = 1;
                 }
             } else if(xstreq(node->name, "type")) {
                 if(!strcmp(value, "aes128")) {
@@ -330,15 +334,16 @@
         node = node->next;
     }
     
-    if(key->name) {
+    if(!error && key->name) {
+        error = 0;
         if(key->type == KEY_AES128) {
             if(key->length < 16) {
                 fprintf(
                         stderr,
-                        "Error: Key %s is too small (%d < 16)\n",
+                        "Error: Key %s is too small (%zu < 16)\n",
                         key->name,
                         key->length);
-                return;
+                error = 1;
             }
             key->length = 16;
         }
@@ -346,10 +351,10 @@
             if(key->length < 32) {
                 fprintf(
                         stderr,
-                        "Error: Key %s is too small (%d < 32)\n",
+                        "Error: Key %s is too small (%zu < 32)\n",
                         key->name,
                         key->length);
-                return;
+                error = 1;
             }
             key->length = 32;
         }
@@ -361,13 +366,20 @@
                 key->data = NULL;
             }
         }
-        ucx_map_cstr_put(keys, key->name, key);
-        dav_context_add_key(context, key);
-    } else {
+        
+        // add key to context
+        if(!error) {
+            ucx_map_cstr_put(keys, key->name, key);
+            dav_context_add_key(context, key);
+        }
+    }
+    
+    // cleanup
+    if(error) {
         if(key->data) {
             free(key->data);
-            free(key);
         }
+        free(key);
     }
 }
 
--- a/dav/main.c	Sat Oct 03 20:10:54 2015 +0200
+++ b/dav/main.c	Sun Oct 04 15:57:40 2015 +0200
@@ -187,12 +187,12 @@
     if(repo->user) {
        user = repo->user; 
     } else {
-        fprintf(stderr, "user: ");
+        fprintf(stderr, "User: ");
         fflush(stderr);
         user = fgets(ubuf, 256, stdin);
     }
     
-    char *password = util_password_input("password: ");
+    char *password = util_password_input("Password: ");
     
     size_t ulen = strlen(user);
     if(user[ulen-1] == '\n') {
@@ -614,7 +614,7 @@
             path,
             depth,
             t);
-    
+      
     if(!res) {
         print_resource_error(sn, path);
         return -1;
--- a/libidav/crypto.c	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/crypto.c	Sun Oct 04 15:57:40 2015 +0200
@@ -36,6 +36,7 @@
 
 AESDecrypter* aes_decrypter_new(DavKey *key, void *stream, dav_write_func write_func) {
     AESDecrypter *dec = malloc(sizeof(AESDecrypter));
+    SHA256_Init(&dec->sha256);
     dec->stream = stream;
     dec->write = write_func;
     dec->key = key;
@@ -89,7 +90,8 @@
     int outlen = len + 16;
     unsigned char *out = malloc(outlen);
     EVP_DecryptUpdate(&dec->ctx, out, &len, buf, len);
-    dec->write(out, 1, len, dec->stream);
+    ssize_t wlen = dec->write(out, 1, len, dec->stream);
+    SHA256_Update(&dec->sha256, out, wlen);
     free(out);
     return (s*n) / s;
 }
@@ -113,13 +115,13 @@
     }
     
     AESEncrypter *enc = malloc(sizeof(AESEncrypter));
+    SHA256_Init(&enc->sha256);
     enc->stream = stream;
     enc->read = read_func;
     enc->tmp = NULL;
     enc->tmplen = 0;
     enc->tmpoff = 0;
     enc->end = 0;
-    //enc->iv = iv;
     enc->iv = iv;
     enc->ivlen = 16;
     
@@ -158,6 +160,8 @@
     void *in = malloc(len);
     size_t in_len = enc->read(in, 1, len, enc->stream);
     
+    SHA256_Update(&enc->sha256, in, in_len);
+    
     unsigned char *out = NULL;
     int outlen = 0;
     size_t ivl = enc->ivlen;
@@ -173,12 +177,14 @@
         out = malloc(16);
         EVP_EncryptFinal_ex(&enc->ctx, out, &outlen);
         enc->end = 1;
+        free(in);
     }
     enc->tmp = (char*)out;
     enc->tmplen = outlen + ivl;
     enc->tmpoff = 0;
     
     if(enc->iv) {
+        free(enc->iv);
         enc->iv = NULL;
         enc->ivlen = 0;
     }
@@ -190,12 +196,15 @@
     if(enc->tmp) {
         free(enc->tmp);
     }
+    if(enc->iv) {
+        free(enc->iv);
+    }
     EVP_CIPHER_CTX_cleanup(&enc->ctx);
     free(enc);
 }
 
 
-char* aes_encrypt(char *in, DavKey *key) {
+char* aes_encrypt(char *in, size_t len, DavKey *key) {
     unsigned char iv[16];
     if(!RAND_bytes(iv, 16)) {
         return NULL;
@@ -218,10 +227,11 @@
                 (unsigned char*)key->data,
                 iv);
     } else {
+        EVP_CIPHER_CTX_cleanup(&ctx);
         return NULL;
     }
     
-    int len = strlen(in);
+    //int len = strlen(in);
     int buflen = len + 64;
     unsigned char *buf = calloc(1, buflen);
     memcpy(buf, iv, 16);
@@ -233,10 +243,12 @@
     EVP_EncryptFinal_ex(&ctx, buf + 16 + l, &f);
     char *out = util_base64encode((char*)buf, 16 + l + f);
     free(buf);
+    EVP_CIPHER_CTX_cleanup(&ctx);
+    
     return out;
 }
 
-char* aes_decrypt(char *in, DavKey *key) {
+char* aes_decrypt(char *in, size_t *length, DavKey *key) {
     int len;
     unsigned char *buf = (unsigned char*)util_base64decode_len(in, &len);
     
@@ -257,6 +269,7 @@
                 key->data,
                 buf);
     } else {
+        EVP_CIPHER_CTX_cleanup(&ctx);
         return NULL;
     }
     
@@ -270,5 +283,17 @@
     EVP_DecryptFinal_ex(&ctx, out + outlen, &f);
     out[outlen + f] = '\0';
     free(buf);
+    EVP_CIPHER_CTX_cleanup(&ctx);
+    
+    *length = outlen + f;
     return (char*)out;
 }
+
+
+void dav_get_hash(SHA256_CTX *sha256, char *buf) {
+#ifdef __sun
+    SHA256Final(buf, sha256);
+#else
+    SHA256_Final(buf, sha256);
+#endif
+}
--- a/libidav/crypto.h	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/crypto.h	Sun Oct 04 15:57:40 2015 +0200
@@ -33,12 +33,19 @@
 #include <openssl/evp.h>
 #include <ucx/string.h>
 
+#ifdef __sun
+#include <sha2.h>
+#else
+#include <openssl/sha.h>
+#endif
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
 typedef struct {
     EVP_CIPHER_CTX ctx;
+    SHA256_CTX     sha256;
     void           *stream;
     dav_write_func write;
     DavKey         *key;
@@ -49,6 +56,7 @@
 
 typedef struct {
     EVP_CIPHER_CTX ctx;
+    SHA256_CTX     sha256;
     void           *iv;
     size_t         ivlen;
     void           *stream;
@@ -68,8 +76,10 @@
 size_t aes_read(void *buf, size_t s, size_t n, AESEncrypter *enc);
 void aes_encrypter_close(AESEncrypter *enc);
 
-char* aes_encrypt(char *in, DavKey *key);
-char* aes_decrypt(char *in, DavKey *key);
+char* aes_encrypt(char *in, size_t len, DavKey *key);
+char* aes_decrypt(char *in, size_t *len, DavKey *key);
+
+void dav_get_hash(SHA256_CTX *sha256, char *buf);
 
 #ifdef	__cplusplus
 }
--- a/libidav/davqlexec.c	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/davqlexec.c	Sun Oct 04 15:57:40 2015 +0200
@@ -240,18 +240,24 @@
         ucx_map_put(new_properties, rt_key, value);
     }
     
-    UcxKey cn_key = dav_property_key("DAV:", "crypto-name");
+    UcxKey cn_key = dav_property_key(DAV_NS, "crypto-name");
     value = ucx_map_get(data->properties, cn_key);
     if(value) {
         ucx_map_put(new_properties, cn_key, value);
     }
     
-    UcxKey ck_key = dav_property_key("DAV:", "crypto-key");
+    UcxKey ck_key = dav_property_key(DAV_NS, "crypto-key");
     value = ucx_map_get(data->properties, ck_key);
     if(value) {
         ucx_map_put(new_properties, ck_key, value);
     }
     
+    UcxKey ch_key = dav_property_key(DAV_NS, "crypto-hash");
+    value = ucx_map_get(data->properties, ch_key);
+    if(value) {
+        ucx_map_put(new_properties, ch_key, value);
+    }
+    
     // add properties from field list
     UCX_FOREACH(elm, fields) {
         DavCompiledField *field = elm->data;
@@ -291,6 +297,7 @@
     ucx_map_remove(data->properties, rt_key);
     ucx_map_remove(data->properties, cn_key);
     ucx_map_remove(data->properties, ck_key);
+    ucx_map_remove(data->properties, ch_key);
     
     resource_free_properties(sn, data->properties);
     data->properties = new_properties;
@@ -302,6 +309,7 @@
     free(rt_key.data);
     free(cn_key.data);
     free(ck_key.data);
+    free(ch_key.data);
     
     return 0;
 }
@@ -378,7 +386,9 @@
         ucx_mempool_destroy(mp);
         return result;
     }
-    ucx_mempool_reg_destr(mp, where, (ucx_destructor)ucx_buffer_free);
+    if(where) {
+        ucx_mempool_reg_destr(mp, where, (ucx_destructor)ucx_buffer_free);
+    }
     
     // compile order criterion
     UcxList *ordercr = NULL;
@@ -495,15 +505,15 @@
                     add_properties(root, &response);
                     cleanup_response(&response);
                     
-                    if(root == selroot) {
+                    if(root == selroot) {                     
                         // The current root is the root of the select query.
                         // In this case we have to check the where clause.
                         // If root is not selroot, the where clause was
                         // already checked for the resource before it was
                         // added to the stack.
                         DavQLStackObj where_result;
-                        if(!dav_exec_expr(where, root, &where_result)) {
-                            if(where_result.data.integer != 0) {
+                        if(!dav_exec_expr(where, root, &where_result)) {                           
+                            if(where_result.data.integer != 0) { 
                                 if(!reset_properties(sn, &result, root, cfieldlist)) {
                                     continue;
                                 }
--- a/libidav/methods.c	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/methods.c	Sun Oct 04 15:57:40 2015 +0200
@@ -87,6 +87,7 @@
     
     int add_crypto_name = 1;
     int add_crypto_key = 1;
+    int add_crypto_hash = 1;
     char *crypto_ns = "idav";
     UcxMap *namespaces = ucx_map_new(8);
     UCX_FOREACH(elm, properties) {
@@ -104,6 +105,9 @@
             } else if(!strcmp(p->name, "crypto-key")) {
                 add_crypto_key = 0;
                 crypto_ns = p->ns->prefix;
+            } else if(!strcmp(p->name, "crypto-hash")) {
+                add_crypto_hash = 0;
+                crypto_ns = p->ns->prefix;
             }
         }
     }
@@ -166,6 +170,12 @@
             s = S(":crypto-key />\n");
             ucx_buffer_write(s.ptr, 1, s.length, buf);
         }
+        if(add_crypto_hash) {
+            ucx_buffer_putc(buf, '<');
+            ucx_buffer_puts(buf, crypto_ns);
+            s = S(":crypto-hash />\n");
+            ucx_buffer_write(s.ptr, 1, s.length, buf);
+        }
     }
     
     // extra properties
@@ -214,6 +224,8 @@
     ucx_buffer_write(s.ptr, 1, s.length, buf);
     s = S("<i:crypto-name />\n");
     ucx_buffer_write(s.ptr, 1, s.length, buf);
+    s = S("<i:crypto-hash />\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
     s = S("</D:prop>\n");
     ucx_buffer_write(s.ptr, 1, s.length, buf);
     
@@ -785,7 +797,7 @@
     return buf;
 }
 
-UcxBuffer* create_crypto_proppatch_request(DavSession *sn, DavKey *key, char *name) {
+UcxBuffer* create_crypto_proppatch_request(DavSession *sn, DavKey *key, char *name, char *hash) {
     UcxBuffer *buf = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND);
     sstr_t s;
     
@@ -801,7 +813,7 @@
     if(DAV_ENCRYPT_NAME(sn)) {
         s = S("<idav:crypto-name>");
         ucx_buffer_write(s.ptr, 1, s.length, buf);
-        char *crname = aes_encrypt(name, key);
+        char *crname = aes_encrypt(name, strlen(name), key);
         ucx_buffer_puts(buf, crname);
         free(crname);
         s = S("</idav:crypto-name>\n");
@@ -814,6 +826,14 @@
     s = S("</idav:crypto-key>\n");
     ucx_buffer_write(s.ptr, 1, s.length, buf);
     
+    if(hash) {
+        s = S("<idav:crypto-hash>");
+        ucx_buffer_write(s.ptr, 1, s.length, buf);
+        ucx_buffer_puts(buf, hash);
+        s = S("</idav:crypto-hash>\n");
+        ucx_buffer_write(s.ptr, 1, s.length, buf);
+    }
+    
     s = S("</D:prop>\n</D:set>\n</D:propertyupdate>\n");
     ucx_buffer_write(s.ptr, 1, s.length, buf);
     
--- a/libidav/methods.h	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/methods.h	Sun Oct 04 15:57:40 2015 +0200
@@ -88,7 +88,7 @@
 void set_davprops(DavResource *res);
 
 UcxBuffer* create_proppatch_request(DavResourceData *data);
-UcxBuffer* create_crypto_proppatch_request(DavSession *sn, DavKey *key, char *name);
+UcxBuffer* create_crypto_proppatch_request(DavSession *sn, DavKey *key, char *name, char *hash);
 
 CURLcode do_delete_request(CURL *handle, UcxBuffer *response);
 
--- a/libidav/resource.c	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/resource.c	Sun Oct 04 15:57:40 2015 +0200
@@ -84,7 +84,7 @@
     // set name, path and href
     sstr_t n = sstr(name);
     res->name = sstrdup_a(sn->mp->allocator, n).ptr;
-    if(n.ptr[n.length-1] == '/') {
+    if(n.length > 0 && n.ptr[n.length-1] == '/') {
         res->name[n.length-1] = '\0';
     }
     
@@ -570,12 +570,18 @@
                         (dav_read_func)ucx_buffer_read);
             }
             
-            // create an empty resource
+            // put resource
             ret = do_put_request(
                     sn->handle,
                     enc,
                     (dav_read_func)aes_read,
                     0);
+            
+            // get sha256 hash
+            char sha[SHA256_DIGEST_LENGTH];
+            dav_get_hash(&enc->sha256, sha);
+            char *enc_hash = aes_encrypt(sha, SHA256_DIGEST_LENGTH, sn->key);
+            
             aes_encrypter_close(enc);
             if(buf) {
                 ucx_buffer_free(buf);
@@ -583,9 +589,12 @@
             
             // add crypto properties
             // TODO: store the properties later
-            if(resource_add_crypto_info(sn, res->href, res->name)) {
+            if(resource_add_crypto_info(sn, res->href, res->name, enc_hash)) {
+                free(enc_hash);
                 return 1;
             }
+            resource_add_property(res, DAV_NS, "crypto-hash", enc_hash);
+            free(enc_hash);
         } else {
             ret = do_put_request(
                     sn->handle,
@@ -663,13 +672,41 @@
     
     CURLcode ret = curl_easy_perform(handle);
     
+    char *hash = NULL;
     if(dec) {
+        // get hash
+        char sha[SHA256_DIGEST_LENGTH];
+        dav_get_hash(&dec->sha256, sha);
+        hash = util_hexstr(sha, 32);
+        
         aes_decrypter_close(dec);
     }
     
     int status = 0;
     curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status);
     if(ret == CURLE_OK && (status >= 200 && status < 300)) {
+        int verify_failed = 0;
+        if(DAV_DECRYPT_CONTENT(sn)) {
+            // try to verify the content
+            char *res_hash = dav_get_property_ns(res, DAV_NS, "crypto-hash");
+
+            if(res_hash) {
+                size_t len = 0;
+                char *dec_hash = aes_decrypt(res_hash, &len, sn->key);
+                char *hex_hash = util_hexstr(dec_hash, 32);
+                if(strcmp(hash, hex_hash)) {
+                    verify_failed = 1;
+                }
+                free(dec_hash);
+                free(hex_hash);
+            }
+        }
+        
+        if(verify_failed) {
+            res->session->error = DAV_CONTENT_VERIFICATION_ERROR;
+            return 1;
+        }
+        
         res->session->error = DAV_OK;
         return 0;
     } else {
@@ -733,7 +770,7 @@
             if(name[len - 1] == '/') {
                 name[len - 1] = '\0';
             }
-            if(resource_add_crypto_info(sn, h, name)) {
+            if(resource_add_crypto_info(sn, h, name, NULL)) {
                 // TODO: error
             }
             break;
@@ -775,7 +812,7 @@
     if(code == CURLE_OK && (s >= 200 && s < 300)) {
         sn->error = DAV_OK;
         // if the session has encrypted file names, add crypto infos
-        resource_add_crypto_info(sn, res->href, res->name); // TODO: check return type
+        resource_add_crypto_info(sn, res->href, res->name, NULL); // TODO: check return type
         
         // do a minimal propfind request
         UcxBuffer *rqbuf = create_propfind_request(sn, NULL);
@@ -822,24 +859,27 @@
 }
 
 
-int resource_add_crypto_info(DavSession *sn, char *href, char *name) {
+int resource_add_crypto_info(DavSession *sn, char *href, char *name, char *hash) {
     if(!DAV_IS_ENCRYPTED(sn)) {
         return 0;
     }
     
-    UcxBuffer *request = create_crypto_proppatch_request(sn, sn->key, name);
+    UcxBuffer *request = create_crypto_proppatch_request(sn, sn->key, name, hash);
     UcxBuffer *response = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND);
     
     util_set_url(sn, href);
     CURLcode ret = do_proppatch_request(sn->handle, request, response);
+    ucx_buffer_free(request);
     int status = 0;
     curl_easy_getinfo (sn->handle, CURLINFO_RESPONSE_CODE, &status);
     if(ret == CURLE_OK && status == 207) {
         // TODO: parse response
-        sn->error = DAV_OK;
+        sn->error = DAV_OK;   
+        ucx_buffer_free(response);
         return 0;
     } else {
         dav_session_set_error(sn, ret, status);
+        ucx_buffer_free(response);
         return 1;
     }
 }
--- a/libidav/resource.h	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/resource.h	Sun Oct 04 15:57:40 2015 +0200
@@ -55,6 +55,11 @@
      * content length
      */
     size_t    length;
+    
+    /*
+     * sha256 content hash
+     */
+    char hash[32];
 };
 
 DavResource* dav_resource_new_full(DavSession *sn, char *parent_path, char *name, char *href);
@@ -70,7 +75,7 @@
 char* resource_get_property_k(DavResource *res, UcxKey key);
 void resource_add_child(DavResource *parent, DavResource *child);
 void resource_add_ordered_child(DavResource *parent, DavResource *child, UcxList *ordercr);
-int resource_add_crypto_info(DavSession *sn, char *href, char *name);
+int resource_add_crypto_info(DavSession *sn, char *href, char *name, char *hash);
 
 UcxKey dav_property_key_a(UcxAllocator *a, char *ns, char *name);
 
--- a/libidav/session.c	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/session.c	Sun Oct 04 15:57:40 2015 +0200
@@ -264,6 +264,7 @@
         // create resource for name lookup
         sstr_t rp = sstrdup(sstrn(path, start));
         DavResource *root = dav_resource_new(sn, rp.ptr);
+        free(rp.ptr);
         resource_set_href(root, sstrn(href->space, href->pos));
         
         // create request buffer for propfind requests
@@ -326,6 +327,7 @@
         
         // cleanup
         dav_resource_free_all(root);
+        ucx_buffer_free(rqbuf);
         ucx_buffer_free(pbuf);
         ucx_buffer_free(href);
         
--- a/libidav/utils.c	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/utils.c	Sun Oct 04 15:57:40 2015 +0200
@@ -49,9 +49,6 @@
 #include "crypto.h"
 #include "webdav.h"
 
-#ifdef __sun
-#include <sha2.h>
-#endif
 
 time_t util_parse_creationdate(char *str) {
     // example: 2012-11-29T21:35:35Z
@@ -167,7 +164,7 @@
     }
     
     int add_separator = 0;
-    if(base.ptr[base.length-1] == '/') {
+    if(base.length != 0 && base.ptr[base.length-1] == '/') {
         if(path.ptr[0] == '/') {
             base.length--;
         }
@@ -268,7 +265,7 @@
     size_t len = strlen(in);
     char *out = calloc(1, len);
     
-    BIO* b = BIO_new_mem_buf(in, len);
+    BIO *b = BIO_new_mem_buf(in, len);
     BIO *d = BIO_new(BIO_f_base64());
     BIO_set_flags(d, BIO_FLAGS_BASE64_NO_NL);
     b = BIO_push(d, b);
@@ -286,15 +283,16 @@
 
     e = BIO_new(BIO_f_base64());
     b = BIO_new(BIO_s_mem());
+    BIO_set_flags(e, BIO_FLAGS_BASE64_NO_NL);
     
     e = BIO_push(e, b);
     BIO_write(e, in, len);
     BIO_flush(e);
     
     BIO_get_mem_ptr(e, &mem);
-    char *out = malloc(mem->length);
-    memcpy(out, mem->data, mem->length -1);
-    out[mem->length - 1] = '\0';
+    char *out = malloc(mem->length + 1);
+    memcpy(out, mem->data, mem->length);
+    out[mem->length] = '\0';
 
     BIO_free_all(e);
 
@@ -312,7 +310,7 @@
 }
 
 char* util_encrypt_str_k(DavSession *sn, char *str, DavKey *key) {
-    char *enc_str = aes_encrypt(str, key);
+    char *enc_str = aes_encrypt(str, strlen(str), key);
     char *ret_str = dav_session_strdup(sn, enc_str);
     free(enc_str);
     return ret_str;
@@ -329,7 +327,8 @@
 }
 
 char* util_decrypt_str_k(DavSession *sn, char *str, DavKey *key) {
-    char *dec_str = aes_decrypt(str, key);
+    size_t len = 0;
+    char *dec_str = aes_decrypt(str, &len, key);
     char *ret_str = dav_session_strdup(sn, dec_str);
     free(dec_str);
     return ret_str;
@@ -478,3 +477,16 @@
     free(prompt.ptr);
     return password;
 }
+
+
+char* util_hexstr(unsigned char *data, size_t len) {
+    size_t buflen = 2*len + 4;
+    UcxBuffer *buf = ucx_buffer_new(malloc(buflen), buflen + 1, 0);
+    for(int i=0;i<len;i++) {
+        ucx_bprintf(buf, "%x", data[i]);
+    }
+    ucx_buffer_putc(buf, 0);
+    char *str = buf->space;
+    ucx_buffer_free(buf);
+    return str;
+}
--- a/libidav/utils.h	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/utils.h	Sun Oct 04 15:57:40 2015 +0200
@@ -91,6 +91,8 @@
 void util_generate_key(DavKey *key, char *password);
 char* util_key_input(DavContext *ctx, DavKey *key);
 
+char* util_hexstr(unsigned char *data, size_t len);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/libidav/webdav.h	Sat Oct 03 20:10:54 2015 +0200
+++ b/libidav/webdav.h	Sun Oct 04 15:57:40 2015 +0200
@@ -68,7 +68,8 @@
     DAV_COULDNT_CONNECT,
     DAV_TIMEOUT,
     DAV_SSL_ERROR,
-    DAV_QL_ERROR
+    DAV_QL_ERROR,
+    DAV_CONTENT_VERIFICATION_ERROR
 };
 
 typedef enum DavError DavError;

mercurial