diff options
author | Ladar Levison <ladar@lavabit.com> | 2017-06-20 07:46:14 +0300 |
---|---|---|
committer | Ladar Levison <ladar@lavabit.com> | 2017-06-20 07:46:14 +0300 |
commit | ec00019570d224896e4dc7f181b8b43fb42e6dce (patch) | |
tree | 9eee9d3c66b0e655d7b7a289e38886e1da8d44a0 /src/providers | |
parent | 3b82a57bcb1b32751b256d63c8aef3c7c5963cc3 (diff) | |
parent | d19064af6b8f44a16fbf79e5ca8dff8fbe895897 (diff) |
Merge remote-tracking branch 'jpadkins/feature/spanning-chunks' into fix/networking-code-cleanup
Diffstat (limited to 'src/providers')
-rw-r--r-- | src/providers/prime/messages/chunks/chunks.h | 4 | ||||
-rw-r--r-- | src/providers/prime/messages/chunks/encrypted.c | 25 | ||||
-rw-r--r-- | src/providers/prime/messages/messages.c | 131 | ||||
-rw-r--r-- | src/providers/prime/prime.h | 4 |
4 files changed, 142 insertions, 22 deletions
diff --git a/src/providers/prime/messages/chunks/chunks.h b/src/providers/prime/messages/chunks/chunks.h index 19c77197..6d9f914b 100644 --- a/src/providers/prime/messages/chunks/chunks.h +++ b/src/providers/prime/messages/chunks/chunks.h @@ -55,8 +55,8 @@ prime_encrypted_chunk_t * encrypted_chunk_alloc(void); stringer_t * encrypted_chunk_buffer(prime_encrypted_chunk_t *chunk); void encrypted_chunk_cleanup(prime_encrypted_chunk_t *chunk); void encrypted_chunk_free(prime_encrypted_chunk_t *chunk); -prime_encrypted_chunk_t * encrypted_chunk_get(prime_message_chunk_type_t type, ed25519_key_t *signing, prime_chunk_keks_t *keks, stringer_t *data); -stringer_t * encrypted_chunk_set(ed25519_key_t *signing, prime_chunk_keks_t *keks, stringer_t *chunk, stringer_t *output); +prime_encrypted_chunk_t * encrypted_chunk_set(prime_message_chunk_type_t type, ed25519_key_t *signing, prime_chunk_keks_t *keks, stringer_t *data, uint8_t flags); +stringer_t * encrypted_chunk_get(ed25519_key_t *signing, prime_chunk_keks_t *keks, stringer_t *chunk, stringer_t *output); #endif diff --git a/src/providers/prime/messages/chunks/encrypted.c b/src/providers/prime/messages/chunks/encrypted.c index 59d4cd35..5d5a300f 100644 --- a/src/providers/prime/messages/chunks/encrypted.c +++ b/src/providers/prime/messages/chunks/encrypted.c @@ -1,4 +1,3 @@ - /** * @file /magma/providers/prime/messages/chunks/encrypted.c * @@ -11,12 +10,12 @@ void encrypted_chunk_free(prime_encrypted_chunk_t *chunk) { if (chunk) { - if (chunk->signature) st_free(chunk->signature); if (chunk->data) st_free(chunk->data); + if (chunk->slots) slots_free(chunk->slots); if (chunk->trailing) st_free(chunk->trailing); if (chunk->encrypted) st_free(chunk->encrypted); - - if (chunk->slots) slots_free(chunk->slots); + if (chunk->signature) st_free(chunk->signature); + if (chunk->next) encrypted_chunk_free(chunk->next); mm_free(chunk); } @@ -59,6 +58,13 @@ stringer_t * encrypted_chunk_buffer(prime_encrypted_chunk_t *chunk) { buffer = chunk->encrypted; } + // If the *next pointer is set then this is part of a series of + // spanning chunks. + while (chunk->next) { + buffer = st_append(buffer, chunk->next); + chunk = chunk->next; + } + return buffer; } @@ -66,7 +72,7 @@ stringer_t * encrypted_chunk_buffer(prime_encrypted_chunk_t *chunk) { * @brief Generate an encrypted message chunk. The signing and encryption keys are required, along with the public encryption * key for at least one actor. */ -prime_encrypted_chunk_t * encrypted_chunk_get(prime_message_chunk_type_t type, ed25519_key_t *signing, prime_chunk_keks_t *keks, stringer_t *data) { +prime_encrypted_chunk_t * encrypted_chunk_set(prime_message_chunk_type_t type, ed25519_key_t *signing, prime_chunk_keks_t *keks, stringer_t *data, uint8_t flags) { uint32_t big_endian_length = 0; prime_chunk_slots_t *slots = NULL; @@ -102,7 +108,7 @@ prime_encrypted_chunk_t * encrypted_chunk_get(prime_message_chunk_type_t type, e result->pad += (256 - (result->pad + result->length + 69)); } - result->flags = 0; + result->flags = flags; big_endian_length = htobe32(result->length); // Allocate a buffer for the serialized payload, and a buffer to store the padding bytes, then initialize the padding @@ -162,7 +168,8 @@ prime_encrypted_chunk_t * encrypted_chunk_get(prime_message_chunk_type_t type, e return result; } -stringer_t * encrypted_chunk_set(ed25519_key_t *signing, prime_chunk_keks_t *keks, stringer_t *chunk, stringer_t *output) { +// Decrypt +stringer_t * encrypted_chunk_get(ed25519_key_t *signing, prime_chunk_keks_t *keks, stringer_t *chunk, stringer_t *output) { int32_t payload_size = 0; uint32_t big_endian_size = 0; @@ -209,14 +216,12 @@ stringer_t * encrypted_chunk_set(ed25519_key_t *signing, prime_chunk_keks_t *kek st_length_get(chunk), (payload_size + slot_size + 4)); return NULL; } - // Key slots. else if (!(key = slots_get(type, PLACER(st_data_get(chunk) + payload_size + 4, slot_size), keks, MANAGEDBUF(32))) || !(stretched = hash_sha512(key, MANAGEDBUF(64)))) { log_pedantic("Key slot parsing failed.s"); return NULL; } - // Decrypt. else if (!(payload = aes_chunk_decrypt(stretched, PLACER(st_data_get(chunk), st_length_get(chunk) - slot_size), NULL))) { log_pedantic("Chunk decryption failed."); @@ -228,7 +233,6 @@ stringer_t * encrypted_chunk_set(ed25519_key_t *signing, prime_chunk_keks_t *kek st_free(payload); return NULL; } - // Verify the signature. else if (ed25519_verify(signing, PLACER(st_data_get(payload) + ED25519_SIGNATURE_LEN, st_length_get(payload) - ED25519_SIGNATURE_LEN), PLACER(st_data_get(payload), ED25519_SIGNATURE_LEN))) { @@ -280,4 +284,3 @@ stringer_t * encrypted_chunk_set(ed25519_key_t *signing, prime_chunk_keks_t *kek st_free(payload); return result; } - diff --git a/src/providers/prime/messages/messages.c b/src/providers/prime/messages/messages.c index 3bc72653..10441e03 100644 --- a/src/providers/prime/messages/messages.c +++ b/src/providers/prime/messages/messages.c @@ -69,10 +69,116 @@ prime_message_t * encrypted_message_alloc(void) { return result; } +/* @brief Get the part as an encrypted data buffer. + * + * @param payload + * @param type + * @param keks + * @param signing + * + * @return + */ +prime_encrypted_chunk_t * part_encrypt(stringer_t *payload, uint8_t type, prime_chunk_keks_t *keks, ed25519_key_t *signing) { + + size_t num_chunks = 0; + stringer_t *slice = NULL; + prime_encrypted_chunk_t *chunk = NULL, *prev = NULL, *curr = NULL; + + if (!(slice = PLACER(st_data_get(payload), st_length_get(payload))) || + !(num_chunks = (st_length_get(payload) / 16777098) + 1)) { + return NULL; + } + + // Create a stringer with a serialized set of encrypted chunks. If necessary the payload is split into multiple chunks. + // Pass this into encrypted_chunk_get() each portion of the payload. Note you'll need to tell the set that it's a span, + // or have the chunk get do the splitting.Return the serialized encrypted_chunk_get() values buffer, combining as necessary. + + for (size_t i = 0; i < num_chunks; i++) { + + // Set chunk to a stringer pointing at the section of the payload that is the data for this iteration. + st_length_set(slice, (i + 1 < num_chunks) ? 16777098 : (st_length_get(payload) % 16777098)); + st_data_set(slice, st_data_get(payload) + (16777098 * i)); + + // Process the chunk stringer into an encrypted chunk. + if (!(curr = encrypted_chunk_set(type, signing, keks, slice, ((i + i < num_chunks) ? 128 : 0)))) { + encrypted_chunk_cleanup(chunk); + return NULL; + } + + if (!chunk) { + chunk = curr; + prev = curr; + curr = NULL; + } + else { + prev->next = curr; + prev = curr; + curr = NULL; + } + } + + return chunk; +} + +/* @brief Get the part as a decrypted data buffer. + * + * @param payload + * @param part + * @param keks + * @param signing + * @param type + * + * @return + */ +stringer_t * part_decrypt(stringer_t *payload, stringer_t *part, prime_chunk_keks_t *keks, ed25519_key_t *signing, uint8_t type) { + + size_t part_size; + uint8_t curr_type; + uint32_t chunk_size = 0; + placer_t slice = pl_null(); + stringer_t *result = NULL, *curr_chunk = NULL; + + // Set the data buffer of the part stringer to the beginning of the payload. + st_data_set(part, st_data_get(payload)); + + while (true) { + + // Read the chunk headers from the beginning of the remaining payload. + if (chunk_header_read(payload, &curr_type, &chunk_size, &slice) != 0) break; + part_size += st_length_get(&slice); + + // TODO: Instead, check if the spanning-chunk flag (128) is set in the header. + // Check if the chunk is still a part of the part that we are decrypting. + if (curr_type != type) break; + + // Pass this into encrypted_chunk_get(). + if (!(curr_chunk = encrypted_chunk_get(signing, keks, &slice, NULL))) { + st_cleanup(result); + return NULL; + } + + // Either append curr_chunk onto result or set result equal to chunk. + result = st_append(result, curr_chunk); + + // Free curr_chunk. + st_free(curr_chunk); + + // Update payload and loop if necessary. + st_data_set(payload, st_data_get(payload) + st_length_get(&slice)); + st_length_set(payload, st_length_get(payload) - st_length_get(&slice)); + } + + // Construct the part-spanning chunk placer. + st_length_set(part, part_size); + + return result; +} + +// Return the binary representation of an encrypted message. stringer_t * naked_message_get(stringer_t *message, prime_org_signet_t *org, prime_user_key_t *user) { - placer_t chunk[7]; uint8_t type = 0; + placer_t chunk[7]; uint32_t size = 0; uint16_t object = 0; uchr_t *data = NULL; @@ -131,7 +237,7 @@ stringer_t * naked_message_get(stringer_t *message, prime_org_signet_t *org, pri remaining -= st_length_get(&chunk[1]); if (chunk_header_read(PLACER(data, remaining), &type, &size, &chunk[2]) < 0 || type != PRIME_CHUNK_HEADERS || - !(headers = encrypted_chunk_set(keys.signing, keks, &chunk[2], NULL))) { + !(headers = encrypted_chunk_get(keys.signing, keks, &chunk[2], NULL))) { ephemeral_chunk_cleanup(ephemeral); keks_free(keks); return NULL; @@ -141,8 +247,10 @@ stringer_t * naked_message_get(stringer_t *message, prime_org_signet_t *org, pri data += st_length_get(&chunk[2]); remaining -= st_length_get(&chunk[2]); - if (chunk_header_read(PLACER(data, remaining), &type, &size, &chunk[3]) < 0 || type != PRIME_CHUNK_BODY || - !(body = encrypted_chunk_set(keys.signing, keks, &chunk[3], NULL))) { + //(void)body_size; + if (//chunk_header_read(PLACER(data, remaining), &type, &size, &chunk[3]) < 0 || type != PRIME_CHUNK_BODY || + !(body = part_decrypt(PLACER(data, remaining), &chunk[3], keks, keys.signing, PRIME_CHUNK_BODY))) { + //!(body = encrypted_chunk_get(keys.signing, keks, &chunk[3], NULL))) { ephemeral_chunk_cleanup(ephemeral); st_free(headers); keks_free(keks); @@ -150,8 +258,12 @@ stringer_t * naked_message_get(stringer_t *message, prime_org_signet_t *org, pri } // Tree signature. + // 191892 data += st_length_get(&chunk[3]); remaining -= st_length_get(&chunk[3]); + // 191824 + //data += body_size; + //remaining -= body_size; if (chunk_header_read(PLACER(data, remaining), &type, &size, &chunk[4]) < 0 || type != PRIME_SIGNATURE_TREE || !(tree = signature_tree_alloc())) { @@ -213,6 +325,7 @@ stringer_t * naked_message_get(stringer_t *message, prime_org_signet_t *org, pri return result; } +// Return a workable struct representation of a message. prime_message_t * naked_message_set(stringer_t *message, prime_org_key_t *destination, prime_user_signet_t *recipient) { size_t length = 0; @@ -273,7 +386,7 @@ prime_message_t * naked_message_set(stringer_t *message, prime_org_key_t *destin st_cleanup(holder[0], holder[1], holder[2], holder[3], holder[4], holder[5], holder[6], holder[7], holder[8], holder[9]); - if (!(result->metadata.common = encrypted_chunk_get(PRIME_CHUNK_COMMON, result->keys.signing, &(result->keks), common))) { + if (!(result->metadata.common = encrypted_chunk_set(PRIME_CHUNK_COMMON, result->keys.signing, &(result->keks), common, 0))) { encrypted_message_free(result); st_cleanup(common); return NULL; @@ -282,14 +395,18 @@ prime_message_t * naked_message_set(stringer_t *message, prime_org_key_t *destin st_cleanup(common); // Encrypt the headers, and the body. - if (!(result->metadata.headers = encrypted_chunk_get(PRIME_CHUNK_HEADERS, result->keys.signing, &(result->keks), &header))) { + if (!(result->metadata.headers = encrypted_chunk_set(PRIME_CHUNK_HEADERS, result->keys.signing, &(result->keks), &header, 0))) { encrypted_message_free(result); return NULL; } - else if (!(result->content.body = encrypted_chunk_get(PRIME_CHUNK_BODY, result->keys.signing, &(result->keks), &body))) { + else if (!(result->content.body = part_encrypt(&body, PRIME_CHUNK_BODY, &(result->keks), result->keys.signing))) { encrypted_message_free(result); return NULL; } + /*else if (!(result->content.body = encrypted_chunk_set(PRIME_CHUNK_BODY, result->keys.signing, &(result->keks), &body, 0))) { + encrypted_message_free(result); + return NULL; + }*/ // Generate the signatures. if (!(tree = signature_tree_alloc())) { diff --git a/src/providers/prime/prime.h b/src/providers/prime/prime.h index 385ab412..ac97c4fc 100644 --- a/src/providers/prime/prime.h +++ b/src/providers/prime/prime.h @@ -260,7 +260,7 @@ typedef struct __attribute__ ((packed)) { /** * @typedef prime_encrypted_chunk_t */ -typedef struct __attribute__ ((packed)) { +typedef struct __attribute__ ((packed)) prime_encrypted_chunk_t { struct { uint8_t type; /**< Chunk type, 1 through 255. >*/ uint32_t length; /**< Payload length, must be divisible by 16 and less than 2^24 - 1. >*/ @@ -272,9 +272,9 @@ typedef struct __attribute__ ((packed)) { uint8_t pad; stringer_t *data; stringer_t *trailing; - stringer_t *encrypted; prime_chunk_slots_t *slots; + struct prime_encrypted_chunk_t *next; } prime_encrypted_chunk_t; |