diff --git a/commandline.c b/commandline.c index 3c9bea44..db84a6c0 100644 --- a/commandline.c +++ b/commandline.c @@ -1269,7 +1269,7 @@ int app_rhizome_extract_file(int argc, const char *const *argv, const struct com || cli_arg(argc, argv, o, "filepath", &filepath, NULL, "") == -1) return -1; cli_arg(argc, argv, o, "key", &keyhex, cli_optional_bundle_crypt_key, ""); - unsigned char key[RHIZOME_CRYPT_KEY_STRLEN + 1]; + unsigned char key[RHIZOME_CRYPT_KEY_BYTES]; if (keyhex[0] && fromhexstr(key, keyhex, RHIZOME_CRYPT_KEY_BYTES) == -1) return -1; /* Ensure the Rhizome database exists and is open */ diff --git a/rhizome.h b/rhizome.h index 60818046..cd61fce0 100644 --- a/rhizome.h +++ b/rhizome.h @@ -44,6 +44,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define RHIZOME_CRYPT_KEY_BYTES crypto_stream_xsalsa20_ref_KEYBYTES #define RHIZOME_CRYPT_KEY_STRLEN (RHIZOME_CRYPT_KEY_BYTES * 2) + +// assumed to always be 2^n #define RHIZOME_CRYPT_PAGE_SIZE 4096 #define RHIZOME_HTTP_PORT 4110 @@ -593,7 +595,6 @@ struct http_response_parts { int unpack_http_response(char *response, struct http_response_parts *parts); - /* Rhizome file storage api */ struct rhizome_write{ char id[SHA512_DIGEST_STRING_LENGTH+1]; @@ -606,6 +607,11 @@ struct rhizome_write{ int64_t file_offset; int64_t file_length; + unsigned char key[RHIZOME_CRYPT_KEY_BYTES]; + // note the last 8 bytes will be reset with the current file_offest + unsigned char nonce[crypto_stream_xsalsa20_NONCEBYTES]; + int crypt; + SHA512_CTX sha512_context; int64_t blob_rowid; }; @@ -619,5 +625,7 @@ int rhizome_finish_write(struct rhizome_write *write); int rhizome_import_file(rhizome_manifest *m, const char *filepath); int rhizome_stat_file(rhizome_manifest *m, const char *filepath); int rhizome_add_file(rhizome_manifest *m, const char *filepath); +int rhizome_crypt_xor_block(unsigned char *buffer, int buffer_size, int64_t stream_offset, + const unsigned char *key, unsigned char *nonce); #endif //__SERVALDNA__RHIZOME_H diff --git a/rhizome_crypto.c b/rhizome_crypto.c index 2b1caf52..424c3384 100644 --- a/rhizome_crypto.c +++ b/rhizome_crypto.c @@ -493,3 +493,41 @@ int rhizome_manifest_extract_signature(rhizome_manifest *m,int *ofs) (*ofs)+=len; RETURN(0); } + +int rhizome_crypt_xor_block(unsigned char *buffer, int buffer_size, int64_t stream_offset, + const unsigned char *key, unsigned char *nonce){ + int64_t nonce_offset = stream_offset & ~(RHIZOME_CRYPT_PAGE_SIZE -1); + int offset=0; + + if (nonce_offset < stream_offset){ + int i; for(i=0;i<8;i++) nonce[i]=(nonce_offset>>(i*8))&0xff; + int padding = stream_offset & (RHIZOME_CRYPT_PAGE_SIZE -1); + int size = RHIZOME_CRYPT_PAGE_SIZE - padding; + if (size>buffer_size) + size=buffer_size; + + unsigned char temp[RHIZOME_CRYPT_PAGE_SIZE]; + bcopy(temp + padding, buffer, size); + crypto_stream_xsalsa20_xor(temp, temp, size, nonce, key); + bcopy(buffer, temp + padding, size); + + nonce_offset+=RHIZOME_CRYPT_PAGE_SIZE; + offset+=size; + } + + while(offset < buffer_size){ + // TODO add offset to nonce instead of replacing + int i; for(i=0;i<8;i++) nonce[i]=(nonce_offset>>(i*8))&0xff; + int size = buffer_size - offset; + if (size>RHIZOME_CRYPT_PAGE_SIZE) + size=RHIZOME_CRYPT_PAGE_SIZE; + + crypto_stream_xsalsa20_xor(buffer+offset, buffer+offset, size, nonce, key); + + nonce_offset+=RHIZOME_CRYPT_PAGE_SIZE; + offset+=size; + } + + return 0; +} + diff --git a/rhizome_database.c b/rhizome_database.c index 585e73c2..3452c634 100644 --- a/rhizome_database.c +++ b/rhizome_database.c @@ -1412,7 +1412,7 @@ int rhizome_retrieve_file(const char *fileid, const char *filepath, const unsign */ long long offset; unsigned char nonce[crypto_stream_xsalsa20_NONCEBYTES]; - bzero(nonce,crypto_stream_xsalsa20_NONCEBYTES); + bzero(nonce, crypto_stream_xsalsa20_NONCEBYTES); unsigned char buffer[RHIZOME_CRYPT_PAGE_SIZE]; for (offset = 0; offset < length; offset += RHIZOME_CRYPT_PAGE_SIZE) { long long count=length-offset; @@ -1421,15 +1421,18 @@ int rhizome_retrieve_file(const char *fileid, const char *filepath, const unsign ret = 0; WHYF("query failed, %s: %s", sqlite3_errmsg(rhizome_db), sqlite3_sql(statement)); WHYF("Error reading %lld bytes of data from blob at offset 0x%llx", count, offset); + break; } if (key) { - /* calculate block nonce */ - int i; for(i=0;i<8;i++) nonce[i]=(offset>>(i*8))&0xff; - crypto_stream_xsalsa20_xor(&buffer[0],&buffer[0],count, nonce,key); + if(rhizome_crypt_xor_block(buffer, count, offset, key, nonce)){ + ret=0; + break; + } } if (write(fd,buffer,count)!=count) { ret =0; WHY("Failed to write data to file"); + break; } } sqlite3_blob_close(blob); diff --git a/rhizome_store.c b/rhizome_store.c index 23e27864..52f9e983 100644 --- a/rhizome_store.c +++ b/rhizome_store.c @@ -105,7 +105,9 @@ int rhizome_flush(struct rhizome_write *write){ if (write->data_size<=0) return WHY("No content supplied"); - // TODO encryption? + if (write->crypt){ + rhizome_crypt_xor_block(write->buffer, write->data_size, write->file_offset, write->key, write->nonce); + } sqlite3_blob *blob; int ret = sqlite3_blob_open(rhizome_db, "main", "FILEBLOBS", "data", write->blob_rowid, 1 /* read/write */, &blob);