From 0efc07f2811c8fa0edffad28c31ded45186fcdb1 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Mon, 14 Nov 2022 14:31:10 +0100 Subject: [PATCH] Updates for full omemo:2 compliance --- CMakeLists.txt | 2 +- README.md | 6 +- protobuf/FingerprintProtocol.proto | 15 - protobuf/LocalStorageProtocol.proto | 5 +- protobuf/Makefile | 2 +- src/CMakeLists.txt | 13 - src/FingerprintProtocol.pb-c.c | 214 ------- src/FingerprintProtocol.pb-c.h | 114 ---- src/LocalStorageProtocol.pb-c.c | 38 +- src/LocalStorageProtocol.pb-c.h | 70 +-- src/OMEMO.pb-c.h | 14 +- src/WhisperTextProtocol.pb-c.h | 26 +- src/curve.c | 126 +++- src/curve.h | 3 + src/device_consistency.c | 681 ---------------------- src/device_consistency.h | 60 -- src/fingerprint.c | 851 ---------------------------- src/fingerprint.h | 103 ---- src/group_cipher.c | 333 ----------- src/group_cipher.h | 114 ---- src/group_session_builder.c | 149 ----- src/group_session_builder.h | 70 --- src/key_helper.c | 72 ++- src/key_helper.h | 4 + src/protocol.c | 58 +- src/protocol.h | 2 + src/ratchet.c | 2 + src/session_builder.c | 6 +- src/session_cipher.c | 2 + src/session_pre_key.c | 59 +- src/session_pre_key.h | 5 +- src/session_state.c | 41 +- src/session_state.h | 3 + src/signal_protocol_internal.h | 2 + src/signal_protocol_types.h | 16 - tests/CMakeLists.txt | 14 +- tests/test_device_consistency.c | 251 -------- tests/test_fingerprint.c | 586 ------------------- tests/test_group_cipher.c | 829 --------------------------- tests/test_key_helper.c | 10 +- tests/test_protocol.c | 8 +- tests/test_session_builder.c | 130 ++++- tests/test_simultaneous_initiate.c | 32 +- 43 files changed, 604 insertions(+), 4537 deletions(-) delete mode 100644 protobuf/FingerprintProtocol.proto delete mode 100644 src/FingerprintProtocol.pb-c.c delete mode 100644 src/FingerprintProtocol.pb-c.h delete mode 100644 src/device_consistency.c delete mode 100644 src/device_consistency.h delete mode 100644 src/fingerprint.c delete mode 100644 src/fingerprint.h delete mode 100644 src/group_cipher.c delete mode 100644 src/group_cipher.h delete mode 100644 src/group_session_builder.c delete mode 100644 src/group_session_builder.h delete mode 100644 tests/test_device_consistency.c delete mode 100644 tests/test_fingerprint.c delete mode 100644 tests/test_group_cipher.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 873dd9de..a1e2d8cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ if(POLICY CMP0042) endif() SET(OMEMO_C_VERSION_MAJOR 0) -SET(OMEMO_C_VERSION_MINOR 4) +SET(OMEMO_C_VERSION_MINOR 5) SET(OMEMO_C_VERSION_PATCH 0) SET(OMEMO_C_VERSION ${OMEMO_C_VERSION_MAJOR}.${OMEMO_C_VERSION_MINOR}.${OMEMO_C_VERSION_PATCH}) diff --git a/README.md b/README.md index e78c1be9..eeda844d 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ versions 0.3.0 and later. - HKDF info strings - Protocol buffer encoding - Signature scheme (uses XEd25519 instead of custom "Curve25519 signatures") + - Specification-compliant double ratchet + - Support for Ed25519 public keys + - Various serializations + - Removes unused functionality # Building libomemo-c @@ -221,7 +225,7 @@ The form and manner of this distribution makes it eligible for export under the ## License ``` Copyright 2015-2016 Open Whisper Systems -Copyright 2020 Dino Team +Copyright 2020-2022 Dino Team Licensed under the GPLv3: http://www.gnu.org/licenses/gpl-3.0.html diff --git a/protobuf/FingerprintProtocol.proto b/protobuf/FingerprintProtocol.proto deleted file mode 100644 index ac5a890b..00000000 --- a/protobuf/FingerprintProtocol.proto +++ /dev/null @@ -1,15 +0,0 @@ -package textsecure; - -option java_package = "org.whispersystems.libsignal.fingerprint"; -option java_outer_classname = "FingerprintProtos"; - -message LogicalFingerprint { - optional bytes content = 1; - optional bytes identifier = 2; // Version 0 -} - -message CombinedFingerprints { - optional uint32 version = 1; - optional LogicalFingerprint localFingerprint = 2; - optional LogicalFingerprint remoteFingerprint = 3; -} diff --git a/protobuf/LocalStorageProtocol.proto b/protobuf/LocalStorageProtocol.proto index 7de2f192..9f00a671 100644 --- a/protobuf/LocalStorageProtocol.proto +++ b/protobuf/LocalStorageProtocol.proto @@ -59,6 +59,8 @@ message SessionStructure { optional bool needsRefresh = 12; optional bytes aliceBaseKey = 13; + + optional bool localIsAlice = 14; } message RecordStructure { @@ -78,6 +80,7 @@ message SignedPreKeyRecordStructure { optional bytes privateKey = 3; optional bytes signature = 4; optional fixed64 timestamp = 5; + optional bytes signature_omemo = 6; } message IdentityKeyPairStructure { @@ -109,4 +112,4 @@ message SenderKeyStateStructure { message SenderKeyRecordStructure { repeated SenderKeyStateStructure senderKeyStates = 1; -} \ No newline at end of file +} diff --git a/protobuf/Makefile b/protobuf/Makefile index 6e551dce..8ec840a9 100644 --- a/protobuf/Makefile +++ b/protobuf/Makefile @@ -1,3 +1,3 @@ all: - protoc-c --c_out=../src/ WhisperTextProtocol.proto LocalStorageProtocol.proto FingerprintProtocol.proto OMEMO.proto + protoc-c --c_out=../src/ WhisperTextProtocol.proto LocalStorageProtocol.proto OMEMO.proto diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 87d1ff1f..f57a92a1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,7 +14,6 @@ include_directories( set(protobuf_SRCS LocalStorageProtocol.pb-c.c WhisperTextProtocol.pb-c.c - FingerprintProtocol.pb-c.c OMEMO.pb-c.c ) @@ -52,14 +51,6 @@ set(omemo_SRCS sender_key_state.h sender_key_record.c sender_key_record.h - group_session_builder.c - group_session_builder.h - group_cipher.c - group_cipher.h - fingerprint.c - fingerprint.h - device_consistency.c - device_consistency.h ) add_subdirectory(curve25519) @@ -99,10 +90,6 @@ INSTALL( sender_key.h sender_key_state.h sender_key_record.h - group_session_builder.h - group_cipher.h - fingerprint.h - device_consistency.h DESTINATION ${INCLUDE_INSTALL_DIR}/omemo ) diff --git a/src/FingerprintProtocol.pb-c.c b/src/FingerprintProtocol.pb-c.c deleted file mode 100644 index 966a81b5..00000000 --- a/src/FingerprintProtocol.pb-c.c +++ /dev/null @@ -1,214 +0,0 @@ -/* Generated by the protocol buffer compiler. DO NOT EDIT! */ -/* Generated from: FingerprintProtocol.proto */ - -/* Do not generate deprecated warnings for self */ -#ifndef PROTOBUF_C__NO_DEPRECATED -#define PROTOBUF_C__NO_DEPRECATED -#endif - -#include "FingerprintProtocol.pb-c.h" -void textsecure__logical_fingerprint__init - (Textsecure__LogicalFingerprint *message) -{ - static const Textsecure__LogicalFingerprint init_value = TEXTSECURE__LOGICAL_FINGERPRINT__INIT; - *message = init_value; -} -size_t textsecure__logical_fingerprint__get_packed_size - (const Textsecure__LogicalFingerprint *message) -{ - assert(message->base.descriptor == &textsecure__logical_fingerprint__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t textsecure__logical_fingerprint__pack - (const Textsecure__LogicalFingerprint *message, - uint8_t *out) -{ - assert(message->base.descriptor == &textsecure__logical_fingerprint__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t textsecure__logical_fingerprint__pack_to_buffer - (const Textsecure__LogicalFingerprint *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &textsecure__logical_fingerprint__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -Textsecure__LogicalFingerprint * - textsecure__logical_fingerprint__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (Textsecure__LogicalFingerprint *) - protobuf_c_message_unpack (&textsecure__logical_fingerprint__descriptor, - allocator, len, data); -} -void textsecure__logical_fingerprint__free_unpacked - (Textsecure__LogicalFingerprint *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &textsecure__logical_fingerprint__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -void textsecure__combined_fingerprints__init - (Textsecure__CombinedFingerprints *message) -{ - static const Textsecure__CombinedFingerprints init_value = TEXTSECURE__COMBINED_FINGERPRINTS__INIT; - *message = init_value; -} -size_t textsecure__combined_fingerprints__get_packed_size - (const Textsecure__CombinedFingerprints *message) -{ - assert(message->base.descriptor == &textsecure__combined_fingerprints__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t textsecure__combined_fingerprints__pack - (const Textsecure__CombinedFingerprints *message, - uint8_t *out) -{ - assert(message->base.descriptor == &textsecure__combined_fingerprints__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t textsecure__combined_fingerprints__pack_to_buffer - (const Textsecure__CombinedFingerprints *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &textsecure__combined_fingerprints__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -Textsecure__CombinedFingerprints * - textsecure__combined_fingerprints__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (Textsecure__CombinedFingerprints *) - protobuf_c_message_unpack (&textsecure__combined_fingerprints__descriptor, - allocator, len, data); -} -void textsecure__combined_fingerprints__free_unpacked - (Textsecure__CombinedFingerprints *message, - ProtobufCAllocator *allocator) -{ - if(!message) - return; - assert(message->base.descriptor == &textsecure__combined_fingerprints__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -static const ProtobufCFieldDescriptor textsecure__logical_fingerprint__field_descriptors[2] = -{ - { - "content", - 1, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_BYTES, - offsetof(Textsecure__LogicalFingerprint, has_content), - offsetof(Textsecure__LogicalFingerprint, content), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "identifier", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_BYTES, - offsetof(Textsecure__LogicalFingerprint, has_identifier), - offsetof(Textsecure__LogicalFingerprint, identifier), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned textsecure__logical_fingerprint__field_indices_by_name[] = { - 0, /* field[0] = content */ - 1, /* field[1] = identifier */ -}; -static const ProtobufCIntRange textsecure__logical_fingerprint__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 2 } -}; -const ProtobufCMessageDescriptor textsecure__logical_fingerprint__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "textsecure.LogicalFingerprint", - "LogicalFingerprint", - "Textsecure__LogicalFingerprint", - "textsecure", - sizeof(Textsecure__LogicalFingerprint), - 2, - textsecure__logical_fingerprint__field_descriptors, - textsecure__logical_fingerprint__field_indices_by_name, - 1, textsecure__logical_fingerprint__number_ranges, - (ProtobufCMessageInit) textsecure__logical_fingerprint__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor textsecure__combined_fingerprints__field_descriptors[3] = -{ - { - "version", - 1, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_UINT32, - offsetof(Textsecure__CombinedFingerprints, has_version), - offsetof(Textsecure__CombinedFingerprints, version), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "localFingerprint", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(Textsecure__CombinedFingerprints, localfingerprint), - &textsecure__logical_fingerprint__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "remoteFingerprint", - 3, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(Textsecure__CombinedFingerprints, remotefingerprint), - &textsecure__logical_fingerprint__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned textsecure__combined_fingerprints__field_indices_by_name[] = { - 1, /* field[1] = localFingerprint */ - 2, /* field[2] = remoteFingerprint */ - 0, /* field[0] = version */ -}; -static const ProtobufCIntRange textsecure__combined_fingerprints__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 3 } -}; -const ProtobufCMessageDescriptor textsecure__combined_fingerprints__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "textsecure.CombinedFingerprints", - "CombinedFingerprints", - "Textsecure__CombinedFingerprints", - "textsecure", - sizeof(Textsecure__CombinedFingerprints), - 3, - textsecure__combined_fingerprints__field_descriptors, - textsecure__combined_fingerprints__field_indices_by_name, - 1, textsecure__combined_fingerprints__number_ranges, - (ProtobufCMessageInit) textsecure__combined_fingerprints__init, - NULL,NULL,NULL /* reserved[123] */ -}; diff --git a/src/FingerprintProtocol.pb-c.h b/src/FingerprintProtocol.pb-c.h deleted file mode 100644 index 08e8c5ce..00000000 --- a/src/FingerprintProtocol.pb-c.h +++ /dev/null @@ -1,114 +0,0 @@ -/* Generated by the protocol buffer compiler. DO NOT EDIT! */ -/* Generated from: FingerprintProtocol.proto */ - -#ifndef PROTOBUF_C_FingerprintProtocol_2eproto__INCLUDED -#define PROTOBUF_C_FingerprintProtocol_2eproto__INCLUDED - -#include - -PROTOBUF_C__BEGIN_DECLS - -#if PROTOBUF_C_VERSION_NUMBER < 1000000 -# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION -# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. -#endif - - -typedef struct _Textsecure__LogicalFingerprint Textsecure__LogicalFingerprint; -typedef struct _Textsecure__CombinedFingerprints Textsecure__CombinedFingerprints; - - -/* --- enums --- */ - - -/* --- messages --- */ - -struct _Textsecure__LogicalFingerprint -{ - ProtobufCMessage base; - protobuf_c_boolean has_content; - ProtobufCBinaryData content; - /* - * Version 0 - */ - protobuf_c_boolean has_identifier; - ProtobufCBinaryData identifier; -}; -#define TEXTSECURE__LOGICAL_FINGERPRINT__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&textsecure__logical_fingerprint__descriptor) \ - , 0, {0,NULL}, 0, {0,NULL} } - - -struct _Textsecure__CombinedFingerprints -{ - ProtobufCMessage base; - protobuf_c_boolean has_version; - uint32_t version; - Textsecure__LogicalFingerprint *localfingerprint; - Textsecure__LogicalFingerprint *remotefingerprint; -}; -#define TEXTSECURE__COMBINED_FINGERPRINTS__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&textsecure__combined_fingerprints__descriptor) \ - , 0, 0, NULL, NULL } - - -/* Textsecure__LogicalFingerprint methods */ -void textsecure__logical_fingerprint__init - (Textsecure__LogicalFingerprint *message); -size_t textsecure__logical_fingerprint__get_packed_size - (const Textsecure__LogicalFingerprint *message); -size_t textsecure__logical_fingerprint__pack - (const Textsecure__LogicalFingerprint *message, - uint8_t *out); -size_t textsecure__logical_fingerprint__pack_to_buffer - (const Textsecure__LogicalFingerprint *message, - ProtobufCBuffer *buffer); -Textsecure__LogicalFingerprint * - textsecure__logical_fingerprint__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void textsecure__logical_fingerprint__free_unpacked - (Textsecure__LogicalFingerprint *message, - ProtobufCAllocator *allocator); -/* Textsecure__CombinedFingerprints methods */ -void textsecure__combined_fingerprints__init - (Textsecure__CombinedFingerprints *message); -size_t textsecure__combined_fingerprints__get_packed_size - (const Textsecure__CombinedFingerprints *message); -size_t textsecure__combined_fingerprints__pack - (const Textsecure__CombinedFingerprints *message, - uint8_t *out); -size_t textsecure__combined_fingerprints__pack_to_buffer - (const Textsecure__CombinedFingerprints *message, - ProtobufCBuffer *buffer); -Textsecure__CombinedFingerprints * - textsecure__combined_fingerprints__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void textsecure__combined_fingerprints__free_unpacked - (Textsecure__CombinedFingerprints *message, - ProtobufCAllocator *allocator); -/* --- per-message closures --- */ - -typedef void (*Textsecure__LogicalFingerprint_Closure) - (const Textsecure__LogicalFingerprint *message, - void *closure_data); -typedef void (*Textsecure__CombinedFingerprints_Closure) - (const Textsecure__CombinedFingerprints *message, - void *closure_data); - -/* --- services --- */ - - -/* --- descriptors --- */ - -extern const ProtobufCMessageDescriptor textsecure__logical_fingerprint__descriptor; -extern const ProtobufCMessageDescriptor textsecure__combined_fingerprints__descriptor; - -PROTOBUF_C__END_DECLS - - -#endif /* PROTOBUF_C_FingerprintProtocol_2eproto__INCLUDED */ diff --git a/src/LocalStorageProtocol.pb-c.c b/src/LocalStorageProtocol.pb-c.c index 00eff10d..f6102a9b 100644 --- a/src/LocalStorageProtocol.pb-c.c +++ b/src/LocalStorageProtocol.pb-c.c @@ -756,7 +756,7 @@ const ProtobufCMessageDescriptor textsecure__session_structure__pending_pre_key_ (ProtobufCMessageInit) textsecure__session_structure__pending_pre_key__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor textsecure__session_structure__field_descriptors[13] = +static const ProtobufCFieldDescriptor textsecure__session_structure__field_descriptors[14] = { { "sessionVersion", @@ -914,10 +914,23 @@ static const ProtobufCFieldDescriptor textsecure__session_structure__field_descr 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "localIsAlice", + 14, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(Textsecure__SessionStructure, has_localisalice), + offsetof(Textsecure__SessionStructure, localisalice), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned textsecure__session_structure__field_indices_by_name[] = { 12, /* field[12] = aliceBaseKey */ 1, /* field[1] = localIdentityPublic */ + 13, /* field[13] = localIsAlice */ 10, /* field[10] = localRegistrationId */ 11, /* field[11] = needsRefresh */ 7, /* field[7] = pendingKeyExchange */ @@ -933,7 +946,7 @@ static const unsigned textsecure__session_structure__field_indices_by_name[] = { static const ProtobufCIntRange textsecure__session_structure__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 13 } + { 0, 14 } }; const ProtobufCMessageDescriptor textsecure__session_structure__descriptor = { @@ -943,7 +956,7 @@ const ProtobufCMessageDescriptor textsecure__session_structure__descriptor = "Textsecure__SessionStructure", "textsecure", sizeof(Textsecure__SessionStructure), - 13, + 14, textsecure__session_structure__field_descriptors, textsecure__session_structure__field_indices_by_name, 1, textsecure__session_structure__number_ranges, @@ -1065,7 +1078,7 @@ const ProtobufCMessageDescriptor textsecure__pre_key_record_structure__descripto (ProtobufCMessageInit) textsecure__pre_key_record_structure__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor textsecure__signed_pre_key_record_structure__field_descriptors[5] = +static const ProtobufCFieldDescriptor textsecure__signed_pre_key_record_structure__field_descriptors[6] = { { "id", @@ -1127,18 +1140,31 @@ static const ProtobufCFieldDescriptor textsecure__signed_pre_key_record_structur 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "signature_omemo", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(Textsecure__SignedPreKeyRecordStructure, has_signature_omemo), + offsetof(Textsecure__SignedPreKeyRecordStructure, signature_omemo), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned textsecure__signed_pre_key_record_structure__field_indices_by_name[] = { 0, /* field[0] = id */ 2, /* field[2] = privateKey */ 1, /* field[1] = publicKey */ 3, /* field[3] = signature */ + 5, /* field[5] = signature_omemo */ 4, /* field[4] = timestamp */ }; static const ProtobufCIntRange textsecure__signed_pre_key_record_structure__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 5 } + { 0, 6 } }; const ProtobufCMessageDescriptor textsecure__signed_pre_key_record_structure__descriptor = { @@ -1148,7 +1174,7 @@ const ProtobufCMessageDescriptor textsecure__signed_pre_key_record_structure__de "Textsecure__SignedPreKeyRecordStructure", "textsecure", sizeof(Textsecure__SignedPreKeyRecordStructure), - 5, + 6, textsecure__signed_pre_key_record_structure__field_descriptors, textsecure__signed_pre_key_record_structure__field_indices_by_name, 1, textsecure__signed_pre_key_record_structure__number_ranges, diff --git a/src/LocalStorageProtocol.pb-c.h b/src/LocalStorageProtocol.pb-c.h index dc75991d..88835c0c 100644 --- a/src/LocalStorageProtocol.pb-c.h +++ b/src/LocalStorageProtocol.pb-c.h @@ -10,26 +10,26 @@ PROTOBUF_C__BEGIN_DECLS #if PROTOBUF_C_VERSION_NUMBER < 1000000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION +#elif 1004001 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. #endif -typedef struct _Textsecure__SessionStructure Textsecure__SessionStructure; -typedef struct _Textsecure__SessionStructure__Chain Textsecure__SessionStructure__Chain; -typedef struct _Textsecure__SessionStructure__Chain__ChainKey Textsecure__SessionStructure__Chain__ChainKey; -typedef struct _Textsecure__SessionStructure__Chain__MessageKey Textsecure__SessionStructure__Chain__MessageKey; -typedef struct _Textsecure__SessionStructure__PendingKeyExchange Textsecure__SessionStructure__PendingKeyExchange; -typedef struct _Textsecure__SessionStructure__PendingPreKey Textsecure__SessionStructure__PendingPreKey; -typedef struct _Textsecure__RecordStructure Textsecure__RecordStructure; -typedef struct _Textsecure__PreKeyRecordStructure Textsecure__PreKeyRecordStructure; -typedef struct _Textsecure__SignedPreKeyRecordStructure Textsecure__SignedPreKeyRecordStructure; -typedef struct _Textsecure__IdentityKeyPairStructure Textsecure__IdentityKeyPairStructure; -typedef struct _Textsecure__SenderKeyStateStructure Textsecure__SenderKeyStateStructure; -typedef struct _Textsecure__SenderKeyStateStructure__SenderChainKey Textsecure__SenderKeyStateStructure__SenderChainKey; -typedef struct _Textsecure__SenderKeyStateStructure__SenderMessageKey Textsecure__SenderKeyStateStructure__SenderMessageKey; -typedef struct _Textsecure__SenderKeyStateStructure__SenderSigningKey Textsecure__SenderKeyStateStructure__SenderSigningKey; -typedef struct _Textsecure__SenderKeyRecordStructure Textsecure__SenderKeyRecordStructure; +typedef struct Textsecure__SessionStructure Textsecure__SessionStructure; +typedef struct Textsecure__SessionStructure__Chain Textsecure__SessionStructure__Chain; +typedef struct Textsecure__SessionStructure__Chain__ChainKey Textsecure__SessionStructure__Chain__ChainKey; +typedef struct Textsecure__SessionStructure__Chain__MessageKey Textsecure__SessionStructure__Chain__MessageKey; +typedef struct Textsecure__SessionStructure__PendingKeyExchange Textsecure__SessionStructure__PendingKeyExchange; +typedef struct Textsecure__SessionStructure__PendingPreKey Textsecure__SessionStructure__PendingPreKey; +typedef struct Textsecure__RecordStructure Textsecure__RecordStructure; +typedef struct Textsecure__PreKeyRecordStructure Textsecure__PreKeyRecordStructure; +typedef struct Textsecure__SignedPreKeyRecordStructure Textsecure__SignedPreKeyRecordStructure; +typedef struct Textsecure__IdentityKeyPairStructure Textsecure__IdentityKeyPairStructure; +typedef struct Textsecure__SenderKeyStateStructure Textsecure__SenderKeyStateStructure; +typedef struct Textsecure__SenderKeyStateStructure__SenderChainKey Textsecure__SenderKeyStateStructure__SenderChainKey; +typedef struct Textsecure__SenderKeyStateStructure__SenderMessageKey Textsecure__SenderKeyStateStructure__SenderMessageKey; +typedef struct Textsecure__SenderKeyStateStructure__SenderSigningKey Textsecure__SenderKeyStateStructure__SenderSigningKey; +typedef struct Textsecure__SenderKeyRecordStructure Textsecure__SenderKeyRecordStructure; /* --- enums --- */ @@ -37,7 +37,7 @@ typedef struct _Textsecure__SenderKeyRecordStructure Textsecure__SenderKeyRecord /* --- messages --- */ -struct _Textsecure__SessionStructure__Chain__ChainKey +struct Textsecure__SessionStructure__Chain__ChainKey { ProtobufCMessage base; protobuf_c_boolean has_index; @@ -50,7 +50,7 @@ struct _Textsecure__SessionStructure__Chain__ChainKey , 0, 0, 0, {0,NULL} } -struct _Textsecure__SessionStructure__Chain__MessageKey +struct Textsecure__SessionStructure__Chain__MessageKey { ProtobufCMessage base; protobuf_c_boolean has_index; @@ -67,7 +67,7 @@ struct _Textsecure__SessionStructure__Chain__MessageKey , 0, 0, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL} } -struct _Textsecure__SessionStructure__Chain +struct Textsecure__SessionStructure__Chain { ProtobufCMessage base; protobuf_c_boolean has_senderratchetkey; @@ -83,7 +83,7 @@ struct _Textsecure__SessionStructure__Chain , 0, {0,NULL}, 0, {0,NULL}, NULL, 0,NULL } -struct _Textsecure__SessionStructure__PendingKeyExchange +struct Textsecure__SessionStructure__PendingKeyExchange { ProtobufCMessage base; protobuf_c_boolean has_sequence; @@ -106,7 +106,7 @@ struct _Textsecure__SessionStructure__PendingKeyExchange , 0, 0, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL} } -struct _Textsecure__SessionStructure__PendingPreKey +struct Textsecure__SessionStructure__PendingPreKey { ProtobufCMessage base; protobuf_c_boolean has_prekeyid; @@ -121,7 +121,7 @@ struct _Textsecure__SessionStructure__PendingPreKey , 0, 0, 0, 0, 0, {0,NULL} } -struct _Textsecure__SessionStructure +struct Textsecure__SessionStructure { ProtobufCMessage base; protobuf_c_boolean has_sessionversion; @@ -147,13 +147,15 @@ struct _Textsecure__SessionStructure protobuf_c_boolean needsrefresh; protobuf_c_boolean has_alicebasekey; ProtobufCBinaryData alicebasekey; + protobuf_c_boolean has_localisalice; + protobuf_c_boolean localisalice; }; #define TEXTSECURE__SESSION_STRUCTURE__INIT \ { PROTOBUF_C_MESSAGE_INIT (&textsecure__session_structure__descriptor) \ - , 0, 0, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL}, 0, 0, NULL, 0,NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, {0,NULL} } + , 0, 0, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL}, 0, 0, NULL, 0,NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, {0,NULL}, 0, 0 } -struct _Textsecure__RecordStructure +struct Textsecure__RecordStructure { ProtobufCMessage base; Textsecure__SessionStructure *currentsession; @@ -165,7 +167,7 @@ struct _Textsecure__RecordStructure , NULL, 0,NULL } -struct _Textsecure__PreKeyRecordStructure +struct Textsecure__PreKeyRecordStructure { ProtobufCMessage base; protobuf_c_boolean has_id; @@ -180,7 +182,7 @@ struct _Textsecure__PreKeyRecordStructure , 0, 0, 0, {0,NULL}, 0, {0,NULL} } -struct _Textsecure__SignedPreKeyRecordStructure +struct Textsecure__SignedPreKeyRecordStructure { ProtobufCMessage base; protobuf_c_boolean has_id; @@ -193,13 +195,15 @@ struct _Textsecure__SignedPreKeyRecordStructure ProtobufCBinaryData signature; protobuf_c_boolean has_timestamp; uint64_t timestamp; + protobuf_c_boolean has_signature_omemo; + ProtobufCBinaryData signature_omemo; }; #define TEXTSECURE__SIGNED_PRE_KEY_RECORD_STRUCTURE__INIT \ { PROTOBUF_C_MESSAGE_INIT (&textsecure__signed_pre_key_record_structure__descriptor) \ - , 0, 0, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL}, 0, 0 } + , 0, 0, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL}, 0, 0, 0, {0,NULL} } -struct _Textsecure__IdentityKeyPairStructure +struct Textsecure__IdentityKeyPairStructure { ProtobufCMessage base; protobuf_c_boolean has_publickey; @@ -212,7 +216,7 @@ struct _Textsecure__IdentityKeyPairStructure , 0, {0,NULL}, 0, {0,NULL} } -struct _Textsecure__SenderKeyStateStructure__SenderChainKey +struct Textsecure__SenderKeyStateStructure__SenderChainKey { ProtobufCMessage base; protobuf_c_boolean has_iteration; @@ -225,7 +229,7 @@ struct _Textsecure__SenderKeyStateStructure__SenderChainKey , 0, 0, 0, {0,NULL} } -struct _Textsecure__SenderKeyStateStructure__SenderMessageKey +struct Textsecure__SenderKeyStateStructure__SenderMessageKey { ProtobufCMessage base; protobuf_c_boolean has_iteration; @@ -238,7 +242,7 @@ struct _Textsecure__SenderKeyStateStructure__SenderMessageKey , 0, 0, 0, {0,NULL} } -struct _Textsecure__SenderKeyStateStructure__SenderSigningKey +struct Textsecure__SenderKeyStateStructure__SenderSigningKey { ProtobufCMessage base; protobuf_c_boolean has_public_; @@ -251,7 +255,7 @@ struct _Textsecure__SenderKeyStateStructure__SenderSigningKey , 0, {0,NULL}, 0, {0,NULL} } -struct _Textsecure__SenderKeyStateStructure +struct Textsecure__SenderKeyStateStructure { ProtobufCMessage base; protobuf_c_boolean has_senderkeyid; @@ -266,7 +270,7 @@ struct _Textsecure__SenderKeyStateStructure , 0, 0, NULL, NULL, 0,NULL } -struct _Textsecure__SenderKeyRecordStructure +struct Textsecure__SenderKeyRecordStructure { ProtobufCMessage base; size_t n_senderkeystates; diff --git a/src/OMEMO.pb-c.h b/src/OMEMO.pb-c.h index 7d43ca97..19932094 100644 --- a/src/OMEMO.pb-c.h +++ b/src/OMEMO.pb-c.h @@ -10,14 +10,14 @@ PROTOBUF_C__BEGIN_DECLS #if PROTOBUF_C_VERSION_NUMBER < 1000000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION +#elif 1004001 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. #endif -typedef struct _Omemo__OMEMOMessage Omemo__OMEMOMessage; -typedef struct _Omemo__OMEMOAuthenticatedMessage Omemo__OMEMOAuthenticatedMessage; -typedef struct _Omemo__OMEMOKeyExchange Omemo__OMEMOKeyExchange; +typedef struct Omemo__OMEMOMessage Omemo__OMEMOMessage; +typedef struct Omemo__OMEMOAuthenticatedMessage Omemo__OMEMOAuthenticatedMessage; +typedef struct Omemo__OMEMOKeyExchange Omemo__OMEMOKeyExchange; /* --- enums --- */ @@ -25,7 +25,7 @@ typedef struct _Omemo__OMEMOKeyExchange Omemo__OMEMOKeyExchange; /* --- messages --- */ -struct _Omemo__OMEMOMessage +struct Omemo__OMEMOMessage { ProtobufCMessage base; uint32_t n; @@ -39,7 +39,7 @@ struct _Omemo__OMEMOMessage , 0, 0, {0,NULL}, 0, {0,NULL} } -struct _Omemo__OMEMOAuthenticatedMessage +struct Omemo__OMEMOAuthenticatedMessage { ProtobufCMessage base; ProtobufCBinaryData mac; @@ -53,7 +53,7 @@ struct _Omemo__OMEMOAuthenticatedMessage , {0,NULL}, {0,NULL} } -struct _Omemo__OMEMOKeyExchange +struct Omemo__OMEMOKeyExchange { ProtobufCMessage base; uint32_t pk_id; diff --git a/src/WhisperTextProtocol.pb-c.h b/src/WhisperTextProtocol.pb-c.h index bec75cec..d2d5bd0e 100644 --- a/src/WhisperTextProtocol.pb-c.h +++ b/src/WhisperTextProtocol.pb-c.h @@ -10,17 +10,17 @@ PROTOBUF_C__BEGIN_DECLS #if PROTOBUF_C_VERSION_NUMBER < 1000000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION +#elif 1004001 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. #endif -typedef struct _Textsecure__SignalMessage Textsecure__SignalMessage; -typedef struct _Textsecure__PreKeySignalMessage Textsecure__PreKeySignalMessage; -typedef struct _Textsecure__KeyExchangeMessage Textsecure__KeyExchangeMessage; -typedef struct _Textsecure__SenderKeyMessage Textsecure__SenderKeyMessage; -typedef struct _Textsecure__SenderKeyDistributionMessage Textsecure__SenderKeyDistributionMessage; -typedef struct _Textsecure__DeviceConsistencyCodeMessage Textsecure__DeviceConsistencyCodeMessage; +typedef struct Textsecure__SignalMessage Textsecure__SignalMessage; +typedef struct Textsecure__PreKeySignalMessage Textsecure__PreKeySignalMessage; +typedef struct Textsecure__KeyExchangeMessage Textsecure__KeyExchangeMessage; +typedef struct Textsecure__SenderKeyMessage Textsecure__SenderKeyMessage; +typedef struct Textsecure__SenderKeyDistributionMessage Textsecure__SenderKeyDistributionMessage; +typedef struct Textsecure__DeviceConsistencyCodeMessage Textsecure__DeviceConsistencyCodeMessage; /* --- enums --- */ @@ -28,7 +28,7 @@ typedef struct _Textsecure__DeviceConsistencyCodeMessage Textsecure__DeviceConsi /* --- messages --- */ -struct _Textsecure__SignalMessage +struct Textsecure__SignalMessage { ProtobufCMessage base; protobuf_c_boolean has_ratchetkey; @@ -45,7 +45,7 @@ struct _Textsecure__SignalMessage , 0, {0,NULL}, 0, 0, 0, 0, 0, {0,NULL} } -struct _Textsecure__PreKeySignalMessage +struct Textsecure__PreKeySignalMessage { ProtobufCMessage base; protobuf_c_boolean has_registrationid; @@ -69,7 +69,7 @@ struct _Textsecure__PreKeySignalMessage , 0, 0, 0, 0, 0, 0, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL} } -struct _Textsecure__KeyExchangeMessage +struct Textsecure__KeyExchangeMessage { ProtobufCMessage base; protobuf_c_boolean has_id; @@ -88,7 +88,7 @@ struct _Textsecure__KeyExchangeMessage , 0, 0, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL}, 0, {0,NULL} } -struct _Textsecure__SenderKeyMessage +struct Textsecure__SenderKeyMessage { ProtobufCMessage base; protobuf_c_boolean has_id; @@ -103,7 +103,7 @@ struct _Textsecure__SenderKeyMessage , 0, 0, 0, 0, 0, {0,NULL} } -struct _Textsecure__SenderKeyDistributionMessage +struct Textsecure__SenderKeyDistributionMessage { ProtobufCMessage base; protobuf_c_boolean has_id; @@ -120,7 +120,7 @@ struct _Textsecure__SenderKeyDistributionMessage , 0, 0, 0, 0, 0, {0,NULL}, 0, {0,NULL} } -struct _Textsecure__DeviceConsistencyCodeMessage +struct Textsecure__DeviceConsistencyCodeMessage { ProtobufCMessage base; protobuf_c_boolean has_generation; diff --git a/src/curve.c b/src/curve.c index d773947e..70a44cd8 100644 --- a/src/curve.c +++ b/src/curve.c @@ -53,11 +53,55 @@ int curve_internal_fast_tests(int silent) } int curve_decode_point(ec_public_key **public_key, const uint8_t *key_data, size_t key_len, signal_context *global_context) +{ + if (key_len == DJB_KEY_LEN) { + // Key is ed25519 public key point + return curve_decode_point_ed(public_key, key_data, key_len, global_context); + } else if (key_len == DJB_KEY_LEN + 1 && key_data[0] == DJB_TYPE) { + // Key is curve25519 public key point prefixed with DJB_TYPE(5) + return curve_decode_point_mont(public_key, key_data, key_len, global_context); + } else if (key_len == DJB_KEY_LEN + 1) { + signal_log(global_context, SG_LOG_ERROR, "Invalid key type: %d", key_data[0]); + return SG_ERR_INVALID_KEY; + } else { + signal_log(global_context, SG_LOG_ERROR, "Invalid key length: %d", key_len); + return SG_ERR_INVALID_KEY; + } +} + +int curve_decode_point_ed(ec_public_key **public_key, const uint8_t *key_data, size_t key_len, signal_context *global_context) +{ + ec_public_key *key = 0; + + if (key_len != DJB_KEY_LEN) { + return SG_ERR_INVALID_KEY; + } + + key = malloc(sizeof(ec_public_key)); + if(!key) { + return SG_ERR_NOMEM; + } + + SIGNAL_INIT(key, ec_public_key_destroy); + + memcpy(key->ed_data, key_data, DJB_KEY_LEN); + fe y, u; + fe_frombytes(y, key->ed_data); + fe_edy_to_montx(u, y); + fe_tobytes(key->data, u); + key->has_ed = 1; + + *public_key = key; + + return 0; +} + +int curve_decode_point_mont(ec_public_key **public_key, const uint8_t *key_data, size_t key_len, signal_context *global_context) { ec_public_key *key = 0; if (key_len == DJB_KEY_LEN) { - // Key is ed25519 public key point + // Key is curve25519 public key point } else if (key_len == DJB_KEY_LEN + 1 && key_data[0] == DJB_TYPE) { // Key is curve25519 public key point prefixed with DJB_TYPE(5) } else if (key_len == DJB_KEY_LEN + 1) { @@ -75,17 +119,12 @@ int curve_decode_point(ec_public_key **public_key, const uint8_t *key_data, size SIGNAL_INIT(key, ec_public_key_destroy); - if (key_len == DJB_KEY_LEN) { // Ed25519 - memcpy(key->ed_data, key_data, DJB_KEY_LEN); - fe y, u; - fe_frombytes(y, key->ed_data); - fe_edy_to_montx(u, y); - fe_tobytes(key->data, u); - key->has_ed = 1; - } else { // Curve25519 with prefix + if (key_len == DJB_KEY_LEN + 1) { memcpy(key->data, key_data + 1, DJB_KEY_LEN); - key->has_ed = 0; + } else { + memcpy(key->data, key_data, DJB_KEY_LEN); } + key->has_ed = 0; *public_key = key; @@ -172,6 +211,24 @@ int ec_public_key_serialize(signal_buffer **buffer, const ec_public_key *key) return 0; } +int ec_public_key_serialize_omemo(signal_buffer **buffer, const ec_public_key *key) +{ + signal_buffer *buf = 0; + + if(!key) { + return SG_ERR_INVAL; + } + + buf = ec_public_key_get_mont(key); + if(!buf) { + return SG_ERR_NOMEM; + } + + *buffer = buf; + + return 0; +} + int ec_public_key_serialize_protobuf(ProtobufCBinaryData *buffer, const ec_public_key *key) { size_t len = 0; @@ -194,6 +251,55 @@ int ec_public_key_serialize_protobuf(ProtobufCBinaryData *buffer, const ec_publi return 0; } +int ec_public_key_serialize_protobuf_mont(ProtobufCBinaryData *buffer, const ec_public_key *key) +{ + size_t len = 0; + uint8_t *data = 0; + + assert(buffer); + assert(key); + + len = sizeof(uint8_t) * (DJB_KEY_LEN); + data = malloc(len); + if(!data) { + return SG_ERR_NOMEM; + } + + memcpy(data, key->data, DJB_KEY_LEN); + + buffer->data = data; + buffer->len = len; + return 0; +} + +int ec_public_key_serialize_protobuf_ed(ProtobufCBinaryData *buffer, const ec_public_key *key) +{ + size_t len = 0; + uint8_t *data = 0; + + assert(buffer); + assert(key); + + len = sizeof(uint8_t) * (DJB_KEY_LEN); + data = malloc(len); + if(!data) { + return SG_ERR_NOMEM; + } + + if (key->has_ed) { + memcpy(data, key->ed_data, DJB_KEY_LEN); + } else { + fe y, u; + fe_frombytes(u, key->data); + fe_montx_to_edy(y, u); + fe_tobytes(data, y); + } + + buffer->data = data; + buffer->len = len; + return 0; +} + void ec_public_key_destroy(signal_type_base *type) { ec_public_key *public_key = (ec_public_key *)type; diff --git a/src/curve.h b/src/curve.h index 9d168294..bccbbe1e 100644 --- a/src/curve.h +++ b/src/curve.h @@ -15,6 +15,8 @@ extern "C" { int curve_internal_fast_tests(int silent); int curve_decode_point(ec_public_key **public_key, const uint8_t *key_data, size_t key_len, signal_context *global_context); +int curve_decode_point_ed(ec_public_key **public_key, const uint8_t *key_data, size_t key_len, signal_context *global_context); +int curve_decode_point_mont(ec_public_key **public_key, const uint8_t *key_data, size_t key_len, signal_context *global_context); int ec_public_key_compare(const ec_public_key *key1, const ec_public_key *key2); int ec_public_key_memcmp(const ec_public_key *key1, const ec_public_key *key2); signal_buffer* ec_public_key_get_ed(const ec_public_key *key); @@ -32,6 +34,7 @@ signal_buffer* ec_public_key_get_mont(const ec_public_key *key); * @return 0 on success, negative on failure */ int ec_public_key_serialize(signal_buffer **buffer, const ec_public_key *key); +int ec_public_key_serialize_omemo(signal_buffer **buffer, const ec_public_key *key); void ec_public_key_destroy(signal_type_base *type); diff --git a/src/device_consistency.c b/src/device_consistency.c deleted file mode 100644 index a079d117..00000000 --- a/src/device_consistency.c +++ /dev/null @@ -1,681 +0,0 @@ -#include "device_consistency.h" - -#include -#include - -#include "signal_protocol_internal.h" -#include "curve.h" -#include "WhisperTextProtocol.pb-c.h" -#include "signal_utarray.h" - -#define CODE_VERSION 0 - -struct device_consistency_signature -{ - signal_type_base base; - signal_buffer *signature; - signal_buffer *vrf_output; -}; - -struct device_consistency_commitment -{ - signal_type_base base; - uint32_t generation; - signal_buffer *serialized; -}; - -struct device_consistency_message -{ - signal_type_base base; - device_consistency_signature *signature; - uint32_t generation; - signal_buffer *serialized; -}; - -struct device_consistency_signature_list -{ - UT_array *values; -}; - -static int device_consistency_message_create(device_consistency_message **message); -static void device_consistency_signature_list_sort(device_consistency_signature_list *list); - -/*------------------------------------------------------------------------*/ - -int device_consistency_signature_create(device_consistency_signature **signature, - const uint8_t *signature_data, size_t signature_len, - const uint8_t *vrf_output_data, size_t vrf_output_len) -{ - int result = 0; - device_consistency_signature *result_signature = 0; - - result_signature = malloc(sizeof(device_consistency_signature)); - if(!result_signature) { - result = SG_ERR_NOMEM; - goto complete; - } - memset(result_signature, 0, sizeof(device_consistency_signature)); - SIGNAL_INIT(result_signature, device_consistency_signature_destroy); - - result_signature->signature = signal_buffer_create(signature_data, signature_len); - if(!result_signature->signature) { - result = SG_ERR_NOMEM; - goto complete; - } - - result_signature->vrf_output = signal_buffer_create(vrf_output_data, vrf_output_len); - if(!result_signature->vrf_output) { - result = SG_ERR_NOMEM; - goto complete; - } - -complete: - if(result >= 0) { - *signature = result_signature; - } - else { - SIGNAL_UNREF(result_signature); - } - return result; -} - -signal_buffer *device_consistency_signature_get_signature(const device_consistency_signature *signature) -{ - assert(signature); - return signature->signature; -} - -signal_buffer *device_consistency_signature_get_vrf_output(const device_consistency_signature *signature) -{ - assert(signature); - return signature->vrf_output; -} - -void device_consistency_signature_destroy(signal_type_base *type) -{ - device_consistency_signature *signature = (device_consistency_signature *)type; - signal_buffer_free(signature->signature); - signal_buffer_free(signature->vrf_output); - free(signature); -} - -/*------------------------------------------------------------------------*/ - -int device_consistency_commitment_create(device_consistency_commitment **commitment, - uint32_t generation, ec_public_key_list *identity_key_list, - signal_context *global_context) -{ - static const char version[] = "DeviceConsistencyCommitment_V0"; - int result = 0; - void *digest_context = 0; - device_consistency_commitment *result_commitment = 0; - ec_public_key_list *sorted_list = 0; - uint8_t gen_data[4]; - unsigned int list_size; - unsigned int i; - - result_commitment = malloc(sizeof(device_consistency_commitment)); - if(!result_commitment) { - result = SG_ERR_NOMEM; - goto complete; - } - memset(result_commitment, 0, sizeof(device_consistency_commitment)); - SIGNAL_INIT(result_commitment, device_consistency_commitment_destroy); - - sorted_list = ec_public_key_list_copy(identity_key_list); - if(!sorted_list) { - result = SG_ERR_NOMEM; - goto complete; - } - - ec_public_key_list_sort(sorted_list); - - result = signal_sha512_digest_init(global_context, &digest_context); - if(result < 0) { - goto complete; - } - - result = signal_sha512_digest_update(global_context, digest_context, - (uint8_t *)version, sizeof(version) - 1); - if(result < 0) { - goto complete; - } - - gen_data[3] = (uint8_t)(generation); - gen_data[2] = (uint8_t)(generation >> 8); - gen_data[1] = (uint8_t)(generation >> 16); - gen_data[0] = (uint8_t)(generation >> 24); - - result = signal_sha512_digest_update(global_context, digest_context, - gen_data, sizeof(gen_data)); - if(result < 0) { - goto complete; - } - - list_size = ec_public_key_list_size(sorted_list); - for(i = 0; i < list_size; i++) { - signal_buffer *key_buffer = 0; - ec_public_key *key = ec_public_key_list_at(sorted_list, i); - - result = ec_public_key_serialize(&key_buffer, key); - if(result < 0) { - goto complete; - } - - result = signal_sha512_digest_update(global_context, digest_context, - signal_buffer_data(key_buffer), signal_buffer_len(key_buffer)); - signal_buffer_free(key_buffer); - if(result < 0) { - goto complete; - } - } - - result_commitment->generation = generation; - result = signal_sha512_digest_final(global_context, digest_context, &result_commitment->serialized); - -complete: - if(sorted_list) { - ec_public_key_list_free(sorted_list); - } - if(digest_context) { - signal_sha512_digest_cleanup(global_context, digest_context); - } - if(result >= 0) { - *commitment = result_commitment; - } - else { - SIGNAL_UNREF(result_commitment); - } - return result; -} - -uint32_t device_consistency_commitment_get_generation(const device_consistency_commitment *commitment) -{ - assert(commitment); - return commitment->generation; -} - -signal_buffer *device_consistency_commitment_get_serialized(const device_consistency_commitment *commitment) -{ - assert(commitment); - return commitment->serialized; -} - -void device_consistency_commitment_destroy(signal_type_base *type) -{ - device_consistency_commitment *commitment = (device_consistency_commitment *)type; - signal_buffer_free(commitment->serialized); - free(commitment); -} - -/*------------------------------------------------------------------------*/ - -int device_consistency_message_create(device_consistency_message **message) -{ - int result = 0; - device_consistency_message *result_message = 0; - - result_message = malloc(sizeof(device_consistency_message)); - if(!result_message) { - result = SG_ERR_NOMEM; - goto complete; - } - memset(result_message, 0, sizeof(device_consistency_message)); - SIGNAL_INIT(result_message, device_consistency_message_destroy); - -complete: - if(result >= 0) { - *message = result_message; - } - return result; -} - -int device_consistency_message_create_from_pair(device_consistency_message **message, - device_consistency_commitment *commitment, - ec_key_pair *identity_key_pair, - signal_context *global_context) -{ - int result = 0; - device_consistency_message *result_message = 0; - signal_buffer *commitment_buffer = 0; - signal_buffer *signature_buffer = 0; - signal_buffer *vrf_output_buffer = 0; - signal_buffer *serialized_signature_buffer = 0; - Textsecure__DeviceConsistencyCodeMessage message_structure = TEXTSECURE__DEVICE_CONSISTENCY_CODE_MESSAGE__INIT; - size_t len = 0; - uint8_t *data = 0; - size_t result_size = 0; - - /* Create message instance */ - result = device_consistency_message_create(&result_message); - if(result < 0) { - goto complete; - } - - /* Calculate VRF signature */ - commitment_buffer = device_consistency_commitment_get_serialized(commitment); - result = curve_calculate_vrf_signature(global_context, &signature_buffer, - ec_key_pair_get_private(identity_key_pair), - signal_buffer_data(commitment_buffer), signal_buffer_len(commitment_buffer)); - if(result < 0) { - goto complete; - } - - /* Verify VRF signature */ - result = curve_verify_vrf_signature(global_context, &vrf_output_buffer, - ec_key_pair_get_public(identity_key_pair), - signal_buffer_data(commitment_buffer), signal_buffer_len(commitment_buffer), - signal_buffer_data(signature_buffer), signal_buffer_len(signature_buffer)); - if(result < 0) { - goto complete; - } - - result_message->generation = device_consistency_commitment_get_generation(commitment); - - /* Create and assign the signature */ - result = device_consistency_signature_create(&result_message->signature, - signal_buffer_data(signature_buffer), signal_buffer_len(signature_buffer), - signal_buffer_data(vrf_output_buffer), signal_buffer_len(vrf_output_buffer)); - if(result < 0) { - goto complete; - } - - serialized_signature_buffer = device_consistency_signature_get_signature(result_message->signature); - - /* Serialize the message */ - message_structure.generation = device_consistency_commitment_get_generation(commitment); - message_structure.has_generation = 1; - message_structure.signature.data = signal_buffer_data(serialized_signature_buffer); - message_structure.signature.len = signal_buffer_len(serialized_signature_buffer); - message_structure.has_signature = 1; - - len = textsecure__device_consistency_code_message__get_packed_size(&message_structure); - result_message->serialized = signal_buffer_alloc(len); - if(!result_message->serialized) { - result = SG_ERR_NOMEM; - goto complete; - } - - data = signal_buffer_data(result_message->serialized); - - result_size = textsecure__device_consistency_code_message__pack(&message_structure, data); - if(result_size != len) { - result = SG_ERR_INVALID_PROTO_BUF; - goto complete; - } - -complete: - signal_buffer_free(signature_buffer); - signal_buffer_free(vrf_output_buffer); - if(result >= 0) { - *message = result_message; - } - else { - SIGNAL_UNREF(result_message); - } - if(result == SG_ERR_INVALID_KEY || result == SG_ERR_VRF_SIG_VERIF_FAILED) { - result = SG_ERR_UNKNOWN; - } - return result; -} - -int device_consistency_message_create_from_serialized(device_consistency_message **message, - device_consistency_commitment *commitment, - const uint8_t *serialized_data, size_t serialized_len, - ec_public_key *identity_key, - signal_context *global_context) -{ - int result = 0; - device_consistency_message *result_message = 0; - Textsecure__DeviceConsistencyCodeMessage *message_structure = 0; - signal_buffer *commitment_buffer = 0; - signal_buffer *vrf_output_buffer = 0; - - /* Create message instance */ - result = device_consistency_message_create(&result_message); - if(result < 0) { - goto complete; - } - - /* Deserialize the message */ - message_structure = textsecure__device_consistency_code_message__unpack(0, serialized_len, serialized_data); - if(!message_structure) { - result = SG_ERR_INVALID_PROTO_BUF; - goto complete; - } - - if(!message_structure->has_generation || !message_structure->has_signature) { - result = SG_ERR_INVALID_PROTO_BUF; - goto complete; - } - - /* Verify VRF signature */ - commitment_buffer = device_consistency_commitment_get_serialized(commitment); - result = curve_verify_vrf_signature(global_context, &vrf_output_buffer, - identity_key, - signal_buffer_data(commitment_buffer), signal_buffer_len(commitment_buffer), - message_structure->signature.data, message_structure->signature.len); - if(result < 0) { - goto complete; - } - - /* Assign the message fields */ - result_message->generation = message_structure->generation; - - result = device_consistency_signature_create(&result_message->signature, - message_structure->signature.data, message_structure->signature.len, - signal_buffer_data(vrf_output_buffer), signal_buffer_len(vrf_output_buffer)); - if(result < 0) { - goto complete; - } - - result_message->serialized = signal_buffer_create(serialized_data, serialized_len); - if(!result_message->serialized) { - result = SG_ERR_NOMEM; - } - -complete: - if(message_structure) { - textsecure__device_consistency_code_message__free_unpacked(message_structure, 0); - } - signal_buffer_free(vrf_output_buffer); - if(result >= 0) { - *message = result_message; - } - else { - SIGNAL_UNREF(result_message); - } - if(result == SG_ERR_INVALID_PROTO_BUF - || result == SG_ERR_INVALID_KEY - || result == SG_ERR_VRF_SIG_VERIF_FAILED) { - result = SG_ERR_INVALID_MESSAGE; - } - return result; -} - -signal_buffer *device_consistency_message_get_serialized(const device_consistency_message *message) -{ - assert(message); - return message->serialized; -} - -device_consistency_signature *device_consistency_message_get_signature(const device_consistency_message *message) -{ - assert(message); - return message->signature; -} - -uint32_t device_consistency_signature_get_generation(const device_consistency_message *message) -{ - assert(message); - return message->generation; -} - -void device_consistency_message_destroy(signal_type_base *type) -{ - device_consistency_message *message = (device_consistency_message *)type; - SIGNAL_UNREF(message->signature); - signal_buffer_free(message->serialized); - free(message); -} - -/*------------------------------------------------------------------------*/ - -int device_consistency_code_generate_for(device_consistency_commitment *commitment, - device_consistency_signature_list *signatures, - char **code_string, - signal_context *global_context) -{ - int result = 0; - char *result_string = 0; - void *digest_context = 0; - device_consistency_signature_list *sorted_list = 0; - uint8_t version_data[2]; - signal_buffer *commitment_buffer; - unsigned int list_size; - unsigned int i; - signal_buffer *hash_buffer = 0; - uint8_t *data = 0; - size_t len = 0; - char *encoded_string = 0; - - sorted_list = device_consistency_signature_list_copy(signatures); - if(!sorted_list) { - result = SG_ERR_NOMEM; - goto complete; - } - - device_consistency_signature_list_sort(sorted_list); - - result = signal_sha512_digest_init(global_context, &digest_context); - if(result < 0) { - goto complete; - } - - version_data[1] = (uint8_t)(CODE_VERSION); - version_data[0] = (uint8_t)(CODE_VERSION >> 8); - - result = signal_sha512_digest_update(global_context, digest_context, - version_data, sizeof(version_data)); - if(result < 0) { - goto complete; - } - - commitment_buffer = device_consistency_commitment_get_serialized(commitment); - result = signal_sha512_digest_update(global_context, digest_context, - signal_buffer_data(commitment_buffer), - signal_buffer_len(commitment_buffer)); - if(result < 0) { - goto complete; - } - - list_size = device_consistency_signature_list_size(sorted_list); - for(i = 0; i < list_size; i++) { - device_consistency_signature *signature = device_consistency_signature_list_at(sorted_list, i); - signal_buffer *vrf_output = device_consistency_signature_get_vrf_output(signature); - - result = signal_sha512_digest_update(global_context, digest_context, - signal_buffer_data(vrf_output), - signal_buffer_len(vrf_output)); - if(result < 0) { - goto complete; - } - } - - result = signal_sha512_digest_final(global_context, digest_context, &hash_buffer); - if(result < 0) { - goto complete; - } - - data = signal_buffer_data(hash_buffer); - len = signal_buffer_len(hash_buffer); - - if(len < 10) { - result = SG_ERR_UNKNOWN; - goto complete; - } - - encoded_string = malloc(11); - if(!encoded_string) { - result = SG_ERR_NOMEM; - goto complete; - } - - for(i = 0; i < 10; i += 5) { - uint64_t chunk = ((uint64_t)data[i] & 0xFFL) << 32 | - ((uint64_t)data[i + 1] & 0xFFL) << 24 | - ((uint64_t)data[i + 2] & 0xFFL) << 16 | - ((uint64_t)data[i + 3] & 0xFFL) << 8 | - ((uint64_t)data[i + 4] & 0xFFL); -#if _WINDOWS - sprintf_s(encoded_string + i, 6, "%05d", (int)(chunk % 100000)); -#else - snprintf(encoded_string + i, 6, "%05d", (int)(chunk % 100000)); -#endif - } - - result_string = malloc(7); - if(!result_string) { - result = SG_ERR_NOMEM; - goto complete; - } - - memcpy(result_string, encoded_string, 6); - result_string[6] = '\0'; - -complete: - if(sorted_list) { - device_consistency_signature_list_free(sorted_list); - } - if(digest_context) { - signal_sha512_digest_cleanup(global_context, digest_context); - } - signal_buffer_free(hash_buffer); - free(encoded_string); - if(result >= 0) { - *code_string = result_string; - } - return result; -} - -/*------------------------------------------------------------------------*/ - -device_consistency_signature_list *device_consistency_signature_list_alloc() -{ - int result = 0; - device_consistency_signature_list *list = malloc(sizeof(device_consistency_signature_list)); - if(!list) { - result = SG_ERR_NOMEM; - goto complete; - } - - memset(list, 0, sizeof(device_consistency_signature_list)); - - utarray_new(list->values, &ut_ptr_icd); - -complete: - if(result < 0) { - if(list) { - free(list); - } - return 0; - } - else { - return list; - } -} - -device_consistency_signature_list *device_consistency_signature_list_copy(const device_consistency_signature_list *list) -{ - int result = 0; - device_consistency_signature_list *result_list = 0; - unsigned int size; - unsigned int i; - device_consistency_signature **p; - - result_list = device_consistency_signature_list_alloc(); - if(!result_list) { - result = SG_ERR_NOMEM; - goto complete; - } - - size = utarray_len(list->values); - - utarray_reserve(result_list->values, size); - - for (i = 0; i < size; i++) { - p = (device_consistency_signature **)utarray_eltptr(list->values, i); - result = device_consistency_signature_list_push_back(result_list, *p); - if(result < 0) { - goto complete; - } - } - -complete: - if(result < 0) { - if(result_list) { - device_consistency_signature_list_free(result_list); - } - return 0; - } - else { - return result_list; - } -} - -int device_consistency_signature_list_push_back(device_consistency_signature_list *list, device_consistency_signature *value) -{ - int result = 0; - assert(list); - assert(value); - - utarray_push_back(list->values, &value); - SIGNAL_REF(value); - -complete: - return result; -} - -unsigned int device_consistency_signature_list_size(const device_consistency_signature_list *list) -{ - assert(list); - return utarray_len(list->values); -} - -device_consistency_signature *device_consistency_signature_list_at(const device_consistency_signature_list *list, unsigned int index) -{ - device_consistency_signature **value = 0; - - assert(list); - assert(index < utarray_len(list->values)); - - value = (device_consistency_signature **)utarray_eltptr(list->values, index); - - assert(*value); - - return *value; -} - -int device_consistency_signature_list_sort_comparator(const void *a, const void *b) -{ - int result; - const device_consistency_signature *sig1 = *((const device_consistency_signature **)a); - const device_consistency_signature *sig2 = *((const device_consistency_signature **)b); - signal_buffer *buf1 = device_consistency_signature_get_vrf_output(sig1); - signal_buffer *buf2 = device_consistency_signature_get_vrf_output(sig2); - size_t len1 = signal_buffer_len(buf1); - size_t len2 = signal_buffer_len(buf2); - - if(len1 == len2) { - result = memcmp(signal_buffer_data(buf1), signal_buffer_data(buf2), len1); - } - else if (len1 < len2) { - result = -1; - } else { - result = 1; - } - - return result; -} - -void device_consistency_signature_list_sort(device_consistency_signature_list *list) -{ - assert(list); - utarray_sort(list->values, device_consistency_signature_list_sort_comparator); -} - -void device_consistency_signature_list_free(device_consistency_signature_list *list) -{ - unsigned int size; - unsigned int i; - device_consistency_signature **p; - if(list) { - size = utarray_len(list->values); - for (i = 0; i < size; i++) { - p = (device_consistency_signature **)utarray_eltptr(list->values, i); - SIGNAL_UNREF(*p); - } - utarray_free(list->values); - free(list); - } -} diff --git a/src/device_consistency.h b/src/device_consistency.h deleted file mode 100644 index 379d0447..00000000 --- a/src/device_consistency.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef DEVICE_CONSISTENCY_H -#define DEVICE_CONSISTENCY_H - -#include "signal_protocol_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int device_consistency_signature_create(device_consistency_signature **signature, - const uint8_t *signature_data, size_t signature_len, - const uint8_t *vrf_output_data, size_t vrf_output_len); - -signal_buffer *device_consistency_signature_get_signature(const device_consistency_signature *signature); -signal_buffer *device_consistency_signature_get_vrf_output(const device_consistency_signature *signature); - -void device_consistency_signature_destroy(signal_type_base *type); - -int device_consistency_commitment_create(device_consistency_commitment **commitment, - uint32_t generation, ec_public_key_list *identity_key_list, - signal_context *global_context); - -uint32_t device_consistency_commitment_get_generation(const device_consistency_commitment *commitment); -signal_buffer *device_consistency_commitment_get_serialized(const device_consistency_commitment *commitment); - -void device_consistency_commitment_destroy(signal_type_base *type); - -int device_consistency_message_create_from_pair(device_consistency_message **message, - device_consistency_commitment *commitment, - ec_key_pair *identity_key_pair, - signal_context *global_context); -int device_consistency_message_create_from_serialized(device_consistency_message **message, - device_consistency_commitment *commitment, - const uint8_t *serialized_data, size_t serialized_len, - ec_public_key *identity_key, - signal_context *global_context); - -signal_buffer *device_consistency_message_get_serialized(const device_consistency_message *message); -device_consistency_signature *device_consistency_message_get_signature(const device_consistency_message *message); -uint32_t device_consistency_signature_get_generation(const device_consistency_message *message); - -void device_consistency_message_destroy(signal_type_base *type); - -int device_consistency_code_generate_for(device_consistency_commitment *commitment, - device_consistency_signature_list *signatures, - char **code_string, - signal_context *global_context); - -device_consistency_signature_list *device_consistency_signature_list_alloc(void); -device_consistency_signature_list *device_consistency_signature_list_copy(const device_consistency_signature_list *list); -int device_consistency_signature_list_push_back(device_consistency_signature_list *list, device_consistency_signature *value); -unsigned int device_consistency_signature_list_size(const device_consistency_signature_list *list); -device_consistency_signature *device_consistency_signature_list_at(const device_consistency_signature_list *list, unsigned int index); -void device_consistency_signature_list_free(device_consistency_signature_list *list); - -#ifdef __cplusplus -} -#endif - -#endif /* DEVICE_CONSISTENCY_H */ diff --git a/src/fingerprint.c b/src/fingerprint.c deleted file mode 100644 index 1058e905..00000000 --- a/src/fingerprint.c +++ /dev/null @@ -1,851 +0,0 @@ -#include "fingerprint.h" - -#include -#include - -#include "FingerprintProtocol.pb-c.h" -#include "signal_protocol_internal.h" -#include "vpool.h" - -#define FINGERPRINT_VERSION 0 -#define FINGERPRINT_LENGTH 30 - -#define MAX(a,b) (((a)>(b))?(a):(b)) - -struct fingerprint -{ - signal_type_base base; - displayable_fingerprint *displayable; - scannable_fingerprint *scannable; -}; - -struct displayable_fingerprint -{ - signal_type_base base; - char *local_fingerprint; - char *remote_fingerprint; - char *display_text; -}; - -struct scannable_fingerprint -{ - signal_type_base base; - uint32_t version; - char *local_stable_identifier; - signal_buffer *local_fingerprint; - char *remote_stable_identifier; - signal_buffer *remote_fingerprint; -}; - -struct fingerprint_generator -{ - int iterations; - int scannable_version; - signal_context *global_context; -}; - -static int fingerprint_generator_get_logical_key_bytes(signal_buffer **key_bytes, - const ec_public_key_list *unsorted_key_list); - -static int fingerprint_generator_create_for_impl(fingerprint_generator *generator, - const char *local_stable_identifier, const signal_buffer *local_identity_buffer, - const char *remote_stable_identifier, const signal_buffer *remote_identity_buffer, - fingerprint **fingerprint_val); - -static int fingerprint_generator_get_fingerprint(fingerprint_generator *generator, signal_buffer **fingerprint_buffer, - const char *stable_identifier, const signal_buffer *identity_buffer); - -static int fingerprint_generator_create_display_string(fingerprint_generator *generator, - char **display_string, signal_buffer *fingerprint_buffer); - -int fingerprint_generator_create(fingerprint_generator **generator, - int iterations, int scannable_version, - signal_context *global_context) -{ - fingerprint_generator *result_generator; - - assert(global_context); - - if(scannable_version < 0 || scannable_version > 1) { - return SG_ERR_INVAL; - } - - result_generator = malloc(sizeof(fingerprint_generator)); - if(!result_generator) { - return SG_ERR_NOMEM; - } - memset(result_generator, 0, sizeof(fingerprint_generator)); - - result_generator->iterations = iterations; - result_generator->scannable_version = scannable_version; - result_generator->global_context = global_context; - - *generator = result_generator; - return 0; -} - -int fingerprint_generator_create_for(fingerprint_generator *generator, - const char *local_stable_identifier, const ec_public_key *local_identity_key, - const char *remote_stable_identifier, const ec_public_key *remote_identity_key, - fingerprint **fingerprint_val) -{ - int result = 0; - signal_buffer *local_key_buffer = 0; - signal_buffer *remote_key_buffer = 0; - - result = ec_public_key_serialize(&local_key_buffer, local_identity_key); - if(result < 0) { - goto complete; - } - - result = ec_public_key_serialize(&remote_key_buffer, remote_identity_key); - if(result < 0) { - goto complete; - } - - result = fingerprint_generator_create_for_impl(generator, - local_stable_identifier, local_key_buffer, - remote_stable_identifier, remote_key_buffer, - fingerprint_val); - -complete: - signal_buffer_free(local_key_buffer); - signal_buffer_free(remote_key_buffer); - return result; -} - -int fingerprint_generator_create_for_list(fingerprint_generator *generator, - const char *local_stable_identifier, const ec_public_key_list *local_identity_key_list, - const char *remote_stable_identifier, const ec_public_key_list *remote_identity_key_list, - fingerprint **fingerprint_val) -{ - int result = 0; - signal_buffer *local_key_buffer = 0; - signal_buffer *remote_key_buffer = 0; - - result = fingerprint_generator_get_logical_key_bytes(&local_key_buffer, local_identity_key_list); - if(result < 0) { - goto complete; - } - - result = fingerprint_generator_get_logical_key_bytes(&remote_key_buffer, remote_identity_key_list); - if(result < 0) { - goto complete; - } - - result = fingerprint_generator_create_for_impl(generator, - local_stable_identifier, local_key_buffer, - remote_stable_identifier, remote_key_buffer, - fingerprint_val); - -complete: - signal_buffer_free(local_key_buffer); - signal_buffer_free(remote_key_buffer); - return result; -} - -int fingerprint_generator_create_for_impl(fingerprint_generator *generator, - const char *local_stable_identifier, const signal_buffer *local_identity_buffer, - const char *remote_stable_identifier, const signal_buffer *remote_identity_buffer, - fingerprint **fingerprint_val) -{ - int result = 0; - fingerprint *result_fingerprint = 0; - signal_buffer *local_fingerprint_buffer = 0; - signal_buffer *remote_fingerprint_buffer = 0; - displayable_fingerprint *displayable = 0; - char *displayable_local = 0; - char *displayable_remote = 0; - scannable_fingerprint *scannable = 0; - - result = fingerprint_generator_get_fingerprint(generator, - &local_fingerprint_buffer, local_stable_identifier, local_identity_buffer); - if(result < 0) { - goto complete; - } - - result = fingerprint_generator_get_fingerprint(generator, - &remote_fingerprint_buffer, remote_stable_identifier, remote_identity_buffer); - if(result < 0) { - goto complete; - } - - result = fingerprint_generator_create_display_string(generator, &displayable_local, - local_fingerprint_buffer); - if(result < 0) { - goto complete; - } - - result = fingerprint_generator_create_display_string(generator, &displayable_remote, - remote_fingerprint_buffer); - if(result < 0) { - goto complete; - } - - result = displayable_fingerprint_create(&displayable, displayable_local, displayable_remote); - if(result < 0) { - goto complete; - } - - if(generator->scannable_version == 0) { - result = scannable_fingerprint_create(&scannable, 0, - local_stable_identifier, local_identity_buffer, - remote_stable_identifier, remote_identity_buffer); - } - else if(generator->scannable_version == 1) { - result = scannable_fingerprint_create(&scannable, 1, - 0, local_fingerprint_buffer, - 0, remote_fingerprint_buffer); - } - else { - result = SG_ERR_INVAL; - } - if(result < 0) { - goto complete; - } - - result = fingerprint_create(&result_fingerprint, displayable, scannable); - -complete: - signal_buffer_free(local_fingerprint_buffer); - signal_buffer_free(remote_fingerprint_buffer); - if(displayable_local) { - free(displayable_local); - } - if(displayable_remote) { - free(displayable_remote); - } - SIGNAL_UNREF(displayable); - SIGNAL_UNREF(scannable); - if(result >= 0) { - *fingerprint_val = result_fingerprint; - } - return result; -} - -int fingerprint_generator_get_logical_key_bytes(signal_buffer **key_bytes, - const ec_public_key_list *unsorted_key_list) -{ - int result = 0; - ec_public_key_list *sorted_key_list = 0; - ec_public_key *key_element = 0; - unsigned int list_size = 0; - unsigned int i = 0; - struct vpool vp; - signal_buffer *buffer = 0; - - vpool_init(&vp, 1024, 0); - - sorted_key_list = ec_public_key_list_copy(unsorted_key_list); - if(!sorted_key_list) { - result = SG_ERR_NOMEM; - goto complete; - } - - ec_public_key_list_sort(sorted_key_list); - list_size = ec_public_key_list_size(sorted_key_list); - - for(i = 0; i < list_size; i++) { - key_element = ec_public_key_list_at(sorted_key_list, i); - - result = ec_public_key_serialize(&buffer, key_element); - if (result < 0) { - goto complete; - } - - if(!vpool_insert(&vp, vpool_get_length(&vp), - signal_buffer_data(buffer), signal_buffer_len(buffer))) { - result = SG_ERR_NOMEM; - goto complete; - } - - signal_buffer_free(buffer); - buffer = 0; - } - - buffer = signal_buffer_create(vpool_get_buf(&vp), vpool_get_length(&vp)); - if(!buffer) { - result = SG_ERR_NOMEM; - goto complete; - } - -complete: - ec_public_key_list_free(sorted_key_list); - vpool_final(&vp); - if(result >= 0) { - *key_bytes = buffer; - } - else { - signal_buffer_free(buffer); - } - return result; -} - -int fingerprint_generator_get_fingerprint(fingerprint_generator *generator, signal_buffer **fingerprint_buffer, - const char *stable_identifier, const signal_buffer *identity_buffer) -{ - int result = 0; - void *digest_context = 0; - signal_buffer *hash_buffer = 0; - signal_buffer *hash_out_buffer = 0; - uint8_t *data = 0; - size_t len = 0; - int i = 0; - - assert(generator); - assert(stable_identifier); - assert(identity_buffer); - - result = signal_sha512_digest_init(generator->global_context, &digest_context); - if(result < 0) { - goto complete; - } - - len = 2 + signal_buffer_len(identity_buffer) + strlen(stable_identifier); - - hash_buffer = signal_buffer_alloc(len); - if(!hash_buffer) { - result = SG_ERR_NOMEM; - goto complete; - } - - data = signal_buffer_data(hash_buffer); - - memset(data, 0, len); - - data[0] = 0; - data[1] = (uint8_t)FINGERPRINT_VERSION; - memcpy(data + 2, signal_buffer_const_data(identity_buffer), signal_buffer_len(identity_buffer)); - memcpy(data + 2 + signal_buffer_len(identity_buffer), stable_identifier, strlen(stable_identifier)); - - for(i = 0; i < generator->iterations; i++) { - data = signal_buffer_data(hash_buffer); - len = signal_buffer_len(hash_buffer); - - result = signal_sha512_digest_update(generator->global_context, - digest_context, data, len); - if(result < 0) { - goto complete; - } - - result = signal_sha512_digest_update(generator->global_context, - digest_context, - signal_buffer_const_data(identity_buffer), - signal_buffer_len(identity_buffer)); - if(result < 0) { - goto complete; - } - - result = signal_sha512_digest_final(generator->global_context, - digest_context, &hash_out_buffer); - if(result < 0) { - goto complete; - } - - signal_buffer_free(hash_buffer); - hash_buffer = hash_out_buffer; - hash_out_buffer = 0; - } - - len = signal_buffer_len(hash_buffer); - - if(len < FINGERPRINT_LENGTH) { - result = SG_ERR_UNKNOWN; - goto complete; - } - -complete: - if(digest_context) { - signal_sha512_digest_cleanup(generator->global_context, digest_context); - } - if(result >= 0) { - *fingerprint_buffer = hash_buffer; - } - else { - signal_buffer_free(hash_buffer); - } - return result; -} - -int fingerprint_generator_create_display_string(fingerprint_generator *generator, - char **display_string, signal_buffer *fingerprint_buffer) -{ - int result = 0; - char *result_string = 0; - uint8_t *data = 0; - size_t len = 0; - int i = 0; - - assert(generator); - assert(fingerprint_buffer); - - data = signal_buffer_data(fingerprint_buffer); - len = signal_buffer_len(fingerprint_buffer); - - if(len < FINGERPRINT_LENGTH) { - result = SG_ERR_UNKNOWN; - goto complete; - } - - result_string = malloc(FINGERPRINT_LENGTH+1); - if(!result_string) { - result = SG_ERR_NOMEM; - goto complete; - } - - for(i = 0; i < FINGERPRINT_LENGTH; i += 5) { - uint64_t chunk = ((uint64_t)data[i] & 0xFFL) << 32 | - ((uint64_t)data[i + 1] & 0xFFL) << 24 | - ((uint64_t)data[i + 2] & 0xFFL) << 16 | - ((uint64_t)data[i + 3] & 0xFFL) << 8 | - ((uint64_t)data[i + 4] & 0xFFL); -#if _WINDOWS - sprintf_s(result_string + i, 6, "%05d", (int)(chunk % 100000)); -#else - snprintf(result_string + i, 6, "%05d", (int)(chunk % 100000)); -#endif - } - -complete: - if(result >= 0) { - *display_string = result_string; - } - return result; -} - -void fingerprint_generator_free(fingerprint_generator *generator) -{ - if(generator) { - free(generator); - } -} - -int fingerprint_create(fingerprint **fingerprint_val, displayable_fingerprint *displayable, scannable_fingerprint *scannable) -{ - fingerprint *result = malloc(sizeof(fingerprint)); - if(!result) { - return SG_ERR_NOMEM; - } - - memset(result, 0, sizeof(fingerprint)); - SIGNAL_INIT(result, fingerprint_destroy); - if(displayable) { - result->displayable = displayable; - SIGNAL_REF(displayable); - } - if(scannable) { - result->scannable = scannable; - SIGNAL_REF(scannable); - } - - *fingerprint_val = result; - - return 0; -} - -displayable_fingerprint *fingerprint_get_displayable(const fingerprint *fingerprint_val) -{ - assert(fingerprint_val); - return fingerprint_val->displayable; -} - -scannable_fingerprint *fingerprint_get_scannable(const fingerprint *fingerprint_val) -{ - assert(fingerprint_val); - return fingerprint_val->scannable; -} - -void fingerprint_destroy(signal_type_base *type) -{ - fingerprint *fingerprint_val = (fingerprint *)type; - SIGNAL_UNREF(fingerprint_val->displayable); - SIGNAL_UNREF(fingerprint_val->scannable); - free(fingerprint_val); -} - -int displayable_fingerprint_create(displayable_fingerprint **displayable, const char *local_fingerprint, const char *remote_fingerprint) -{ - int result = 0; - size_t local_len = 0; - size_t remote_len = 0; - displayable_fingerprint *result_displayable = 0; - char *display_text = 0; - - if(!local_fingerprint || !remote_fingerprint) { - return SG_ERR_INVAL; - } - - result_displayable = malloc(sizeof(displayable_fingerprint)); - if(!result_displayable) { - return SG_ERR_NOMEM; - } - - memset(result_displayable, 0, sizeof(displayable_fingerprint)); - SIGNAL_INIT(result_displayable, displayable_fingerprint_destroy); - - result_displayable->local_fingerprint = strdup(local_fingerprint); - if(!result_displayable->local_fingerprint) { - result = SG_ERR_NOMEM; - goto complete; - } - - result_displayable->remote_fingerprint = strdup(remote_fingerprint); - if(!result_displayable->remote_fingerprint) { - result = SG_ERR_NOMEM; - goto complete; - } - - local_len = strlen(local_fingerprint); - remote_len = strlen(remote_fingerprint); - - display_text = malloc(local_len + remote_len + 1); - if(!display_text) { - result = SG_ERR_NOMEM; - goto complete; - } - - if(strcmp(local_fingerprint, remote_fingerprint) <= 0) { - memcpy(display_text, local_fingerprint, local_len); - memcpy(display_text + local_len, remote_fingerprint, remote_len + 1); - } - else { - memcpy(display_text, remote_fingerprint, remote_len); - memcpy(display_text + remote_len, local_fingerprint, local_len + 1); - } - - result_displayable->display_text = display_text; - -complete: - if(result < 0) { - SIGNAL_UNREF(result_displayable); - } - else { - *displayable = result_displayable; - } - - return result; -} - -const char *displayable_fingerprint_local(const displayable_fingerprint *displayable) -{ - assert(displayable); - return displayable->local_fingerprint; -} - -const char *displayable_fingerprint_remote(const displayable_fingerprint *displayable) -{ - assert(displayable); - return displayable->remote_fingerprint; -} - -const char *displayable_fingerprint_text(const displayable_fingerprint *displayable) -{ - assert(displayable); - return displayable->display_text; -} - -void displayable_fingerprint_destroy(signal_type_base *type) -{ - displayable_fingerprint *displayable = (displayable_fingerprint *)type; - if(displayable->local_fingerprint) { - free(displayable->local_fingerprint); - } - if(displayable->remote_fingerprint) { - free(displayable->remote_fingerprint); - } - if(displayable->display_text) { - free(displayable->display_text); - } - free(displayable); -} - -int scannable_fingerprint_create(scannable_fingerprint **scannable, - uint32_t version, - const char *local_stable_identifier, const signal_buffer *local_fingerprint, - const char *remote_stable_identifier, const signal_buffer *remote_fingerprint) -{ - int result = 0; - scannable_fingerprint *result_scannable = 0; - - if(version == 0 && (!local_stable_identifier || !remote_stable_identifier)) { - return SG_ERR_INVAL; - } - - if(!local_fingerprint || !remote_fingerprint) { - return SG_ERR_INVAL; - } - - result_scannable = malloc(sizeof(scannable_fingerprint)); - if(!result_scannable) { - return SG_ERR_NOMEM; - } - - memset(result_scannable, 0, sizeof(scannable_fingerprint)); - SIGNAL_INIT(result_scannable, scannable_fingerprint_destroy); - - result_scannable->version = version; - - if(version == 0 && local_stable_identifier) { - result_scannable->local_stable_identifier = strdup(local_stable_identifier); - if(!result_scannable->local_stable_identifier) { - result = SG_ERR_NOMEM; - goto complete; - } - } - - if(version == 0) { - result_scannable->local_fingerprint = signal_buffer_copy(local_fingerprint); - } - else { - result_scannable->local_fingerprint = signal_buffer_n_copy(local_fingerprint, 32); - } - if(!result_scannable->local_fingerprint) { - result = SG_ERR_NOMEM; - goto complete; - } - - if(version == 0 && remote_stable_identifier) { - result_scannable->remote_stable_identifier = strdup(remote_stable_identifier); - if(!result_scannable->remote_stable_identifier) { - result = SG_ERR_NOMEM; - goto complete; - } - } - - if(version == 0) { - result_scannable->remote_fingerprint = signal_buffer_copy(remote_fingerprint); - } - else { - result_scannable->remote_fingerprint = signal_buffer_n_copy(remote_fingerprint, 32); - } - if(!result_scannable->remote_fingerprint) { - result = SG_ERR_NOMEM; - goto complete; - } - -complete: - if(result < 0) { - SIGNAL_UNREF(result_scannable); - } - else { - *scannable = result_scannable; - } - - return result; -} - -int scannable_fingerprint_serialize(signal_buffer **buffer, const scannable_fingerprint *scannable) -{ - int result = 0; - size_t result_size = 0; - signal_buffer *result_buf = 0; - Textsecure__CombinedFingerprints combined_fingerprint = TEXTSECURE__COMBINED_FINGERPRINTS__INIT; - Textsecure__LogicalFingerprint local_fingerprint = TEXTSECURE__LOGICAL_FINGERPRINT__INIT; - Textsecure__LogicalFingerprint remote_fingerprint = TEXTSECURE__LOGICAL_FINGERPRINT__INIT; - size_t len = 0; - uint8_t *data = 0; - - combined_fingerprint.version = scannable->version; - combined_fingerprint.has_version = 1; - - if(scannable->local_fingerprint) { - if(scannable->version == 0 && scannable->local_stable_identifier) { - signal_protocol_str_serialize_protobuf(&local_fingerprint.identifier, scannable->local_stable_identifier); - local_fingerprint.has_identifier = 1; - } - - local_fingerprint.content.data = signal_buffer_data(scannable->local_fingerprint); - local_fingerprint.content.len = signal_buffer_len(scannable->local_fingerprint); - local_fingerprint.has_content = 1; - - combined_fingerprint.localfingerprint = &local_fingerprint; - } - - if(scannable->remote_fingerprint) { - if(scannable->version == 0 && scannable->remote_stable_identifier) { - signal_protocol_str_serialize_protobuf(&remote_fingerprint.identifier, scannable->remote_stable_identifier); - remote_fingerprint.has_identifier = 1; - } - - remote_fingerprint.content.data = signal_buffer_data(scannable->remote_fingerprint); - remote_fingerprint.content.len = signal_buffer_len(scannable->remote_fingerprint); - remote_fingerprint.has_content = 1; - - combined_fingerprint.remotefingerprint = &remote_fingerprint; - } - - len = textsecure__combined_fingerprints__get_packed_size(&combined_fingerprint); - - result_buf = signal_buffer_alloc(len); - if(!result_buf) { - result = SG_ERR_NOMEM; - goto complete; - } - - data = signal_buffer_data(result_buf); - result_size = textsecure__combined_fingerprints__pack(&combined_fingerprint, data); - if(result_size != len) { - signal_buffer_free(result_buf); - result = SG_ERR_INVALID_PROTO_BUF; - result_buf = 0; - goto complete; - } - -complete: - if(result >= 0) { - *buffer = result_buf; - } - return result; -} - -int scannable_fingerprint_deserialize(scannable_fingerprint **scannable, const uint8_t *data, size_t len, signal_context *global_context) -{ - int result = 0; - Textsecure__CombinedFingerprints *combined_fingerprint = 0; - uint32_t version = 0; - char *local_stable_identifier = 0; - signal_buffer *local_fingerprint = 0; - char *remote_stable_identifier = 0; - signal_buffer *remote_fingerprint = 0; - - combined_fingerprint = textsecure__combined_fingerprints__unpack(0, len, data); - if(!combined_fingerprint) { - result = SG_ERR_INVALID_PROTO_BUF; - goto complete; - } - - if(combined_fingerprint->has_version) { - version = combined_fingerprint->version; - } - - if(combined_fingerprint->localfingerprint) { - if(combined_fingerprint->localfingerprint->has_identifier) { - local_stable_identifier = signal_protocol_str_deserialize_protobuf(&combined_fingerprint->localfingerprint->identifier); - if(!local_stable_identifier) { - result = SG_ERR_NOMEM; - goto complete; - } - } - if(combined_fingerprint->localfingerprint->has_content) { - local_fingerprint = signal_buffer_create( - combined_fingerprint->localfingerprint->content.data, - combined_fingerprint->localfingerprint->content.len); - if(!local_fingerprint) { - result = SG_ERR_NOMEM; - goto complete; - } - } - } - - if(combined_fingerprint->remotefingerprint) { - if(combined_fingerprint->remotefingerprint->has_identifier) { - remote_stable_identifier = signal_protocol_str_deserialize_protobuf(&combined_fingerprint->remotefingerprint->identifier); - if(!remote_stable_identifier) { - result = SG_ERR_NOMEM; - goto complete; - } - } - if(combined_fingerprint->remotefingerprint->has_content) { - remote_fingerprint = signal_buffer_create( - combined_fingerprint->remotefingerprint->content.data, - combined_fingerprint->remotefingerprint->content.len); - if(!remote_fingerprint) { - result = SG_ERR_NOMEM; - goto complete; - } - } - } - - result = scannable_fingerprint_create(scannable, version, - local_stable_identifier, local_fingerprint, - remote_stable_identifier, remote_fingerprint); - -complete: - if(combined_fingerprint) { - textsecure__combined_fingerprints__free_unpacked(combined_fingerprint, 0); - } - if(local_stable_identifier) { - free(local_stable_identifier); - } - if(remote_stable_identifier) { - free(remote_stable_identifier); - } - signal_buffer_free(local_fingerprint); - signal_buffer_free(remote_fingerprint); - return result; -} - -uint32_t scannable_fingerprint_get_version(const scannable_fingerprint *scannable) -{ - assert(scannable); - return scannable->version; -} - -const char *scannable_fingerprint_get_local_stable_identifier(const scannable_fingerprint *scannable) -{ - assert(scannable); - return scannable->local_stable_identifier; -} - -signal_buffer *scannable_fingerprint_get_local_fingerprint(const scannable_fingerprint *scannable) -{ - assert(scannable); - return scannable->local_fingerprint; -} - -const char *scannable_fingerprint_get_remote_stable_identifier(const scannable_fingerprint *scannable) -{ - assert(scannable); - return scannable->remote_stable_identifier; -} - -signal_buffer *scannable_fingerprint_get_remote_fingerprint(const scannable_fingerprint *scannable) -{ - assert(scannable); - return scannable->remote_fingerprint; -} - -int scannable_fingerprint_compare(const scannable_fingerprint *scannable, const scannable_fingerprint *other_scannable) -{ - if(!other_scannable->remote_fingerprint || !other_scannable->local_fingerprint || - other_scannable->version != scannable->version) { - return SG_ERR_FP_VERSION_MISMATCH; - } - - if(scannable->version == 0) { - if(strcmp(scannable->local_stable_identifier, other_scannable->remote_stable_identifier) != 0) { - return SG_ERR_FP_IDENT_MISMATCH; - } - - if(strcmp(scannable->remote_stable_identifier, other_scannable->local_stable_identifier) != 0) { - return SG_ERR_FP_IDENT_MISMATCH; - } - } - - if(signal_buffer_compare(scannable->local_fingerprint, other_scannable->remote_fingerprint) != 0) { - return 0; - } - - if(signal_buffer_compare(scannable->remote_fingerprint, other_scannable->local_fingerprint) != 0) { - return 0; - } - - return 1; -} - -void scannable_fingerprint_destroy(signal_type_base *type) -{ - scannable_fingerprint *scannable = (scannable_fingerprint *)type; - - if(scannable->local_stable_identifier) { - free(scannable->local_stable_identifier); - } - if(scannable->remote_stable_identifier) { - free(scannable->remote_stable_identifier); - } - - signal_buffer_free(scannable->local_fingerprint); - signal_buffer_free(scannable->remote_fingerprint); - - free(scannable); -} diff --git a/src/fingerprint.h b/src/fingerprint.h deleted file mode 100644 index a09287cd..00000000 --- a/src/fingerprint.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef FINGERPRINT_H -#define FINGERPRINT_H - -#include "signal_protocol_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Construct a fingerprint generator for 60 digit numerics. - * - * @param generator set to a freshly allocated generator instance - * @param iterations The number of internal iterations to perform in the process of - * generating a fingerprint. This needs to be constant, and synchronized - * across all clients. - * - * The higher the iteration count, the higher the security level: - * - 1024 ~ 109.7 bits - * - 1400 > 110 bits - * - 5200 > 112 bits - * @param scannable_version The format version for the scannable fingerprint (0 or 1) - * @param global_context the global library context - * @return 0 on success, or negative on failure - */ -int fingerprint_generator_create(fingerprint_generator **generator, - int iterations, int scannable_version, - signal_context *global_context); - -/** - * Generate a scannable and displayble fingerprint. - * - * @param local_stable_identifier The client's "stable" identifier. - * @param local_identity_key The client's identity key. - * @param remote_stable_identifier The remote party's "stable" identifier. - * @param remote_identity_key The remote party's identity key. - * @param fingerprint_val Set to a freshly allocated unique fingerprint for this conversation - * @return 0 on success, or negative on failure - */ -int fingerprint_generator_create_for(fingerprint_generator *generator, - const char *local_stable_identifier, const ec_public_key *local_identity_key, - const char *remote_stable_identifier, const ec_public_key *remote_identity_key, - fingerprint **fingerprint_val); - -/** - * Generate a scannable and displayble fingerprint for a list of keys - * - * @param local_stable_identifier The client's "stable" identifier. - * @param local_identity_key_list The client's identity key list. - * @param remote_stable_identifier The remote party's "stable" identifier. - * @param remote_identity_key_list The remote party's identity key list. - * @param fingerprint_val Set to a freshly allocated unique fingerprint for this conversation - * @return 0 on success, or negative on failure - */ -int fingerprint_generator_create_for_list(fingerprint_generator *generator, - const char *local_stable_identifier, const ec_public_key_list *local_identity_key_list, - const char *remote_stable_identifier, const ec_public_key_list *remote_identity_key_list, - fingerprint **fingerprint_val); - -void fingerprint_generator_free(fingerprint_generator *generator); - -int fingerprint_create(fingerprint **fingerprint_val, displayable_fingerprint *displayable, scannable_fingerprint *scannable); -displayable_fingerprint *fingerprint_get_displayable(const fingerprint *fingerprint_val); -scannable_fingerprint *fingerprint_get_scannable(const fingerprint *fingerprint_val); -void fingerprint_destroy(signal_type_base *type); - -int displayable_fingerprint_create(displayable_fingerprint **displayable, const char *local_fingerprint, const char *remote_fingerprint); -const char *displayable_fingerprint_local(const displayable_fingerprint *displayable); -const char *displayable_fingerprint_remote(const displayable_fingerprint *displayable); -const char *displayable_fingerprint_text(const displayable_fingerprint *displayable); -void displayable_fingerprint_destroy(signal_type_base *type); - -int scannable_fingerprint_create(scannable_fingerprint **scannable, - uint32_t version, - const char *local_stable_identifier, const signal_buffer *local_fingerprint, - const char *remote_stable_identifier, const signal_buffer *remote_fingerprint); - -int scannable_fingerprint_serialize(signal_buffer **buffer, const scannable_fingerprint *scannable); -int scannable_fingerprint_deserialize(scannable_fingerprint **scannable, const uint8_t *data, size_t len, signal_context *global_context); -uint32_t scannable_fingerprint_get_version(const scannable_fingerprint *scannable); -const char *scannable_fingerprint_get_local_stable_identifier(const scannable_fingerprint *scannable); -signal_buffer *scannable_fingerprint_get_local_fingerprint(const scannable_fingerprint *scannable); -const char *scannable_fingerprint_get_remote_stable_identifier(const scannable_fingerprint *scannable); -signal_buffer *scannable_fingerprint_get_remote_fingerprint(const scannable_fingerprint *scannable); - -/** - * Compare a scanned QR code with what we expect. - * @param scannable The local scannable data - * @param other_scannable The data from the scanned code - * @retval 1 if the scannable codes match - * @retval 0 if the scannable codes do not match - * @retval SG_ERR_FP_VERSION_MISMATCH if the scanned fingerprint is the wrong version - * @retval SG_ERR_FP_IDENT_MISMATCH if the scanned fingerprint is for the wrong stable identifier - */ -int scannable_fingerprint_compare(const scannable_fingerprint *scannable, const scannable_fingerprint *other_scannable); - -void scannable_fingerprint_destroy(signal_type_base *type); - -#ifdef __cplusplus -} -#endif - -#endif /* FINGERPRINT_H */ diff --git a/src/group_cipher.c b/src/group_cipher.c deleted file mode 100644 index 05ea320d..00000000 --- a/src/group_cipher.c +++ /dev/null @@ -1,333 +0,0 @@ -#include "group_cipher.h" - -#include -#include -#include "protocol.h" -#include "sender_key.h" -#include "sender_key_record.h" -#include "sender_key_state.h" -#include "signal_protocol_internal.h" - -struct group_cipher -{ - signal_protocol_store_context *store; - const signal_protocol_sender_key_name *sender_key_id; - signal_context *global_context; - int (*decrypt_callback)(group_cipher *cipher, signal_buffer *plaintext, void *decrypt_context); - int inside_callback; - void *user_data; -}; - -static int group_cipher_get_sender_key(group_cipher *cipher, sender_message_key **sender_key, sender_key_state *state, uint32_t iteration); -static int group_cipher_decrypt_callback(group_cipher *cipher, signal_buffer *plaintext, void *decrypt_context); - -int group_cipher_create(group_cipher **cipher, - signal_protocol_store_context *store, const signal_protocol_sender_key_name *sender_key_id, - signal_context *global_context) -{ - group_cipher *result_cipher; - - assert(store); - assert(global_context); - - result_cipher = malloc(sizeof(group_cipher)); - if(!result_cipher) { - return SG_ERR_NOMEM; - } - memset(result_cipher, 0, sizeof(group_cipher)); - - result_cipher->store = store; - result_cipher->sender_key_id = sender_key_id; - result_cipher->global_context = global_context; - - *cipher = result_cipher; - return 0; -} - -void group_cipher_set_user_data(group_cipher *cipher, void *user_data) -{ - assert(cipher); - cipher->user_data = user_data; -} - -void *group_cipher_get_user_data(group_cipher *cipher) -{ - assert(cipher); - return cipher->user_data; -} - -void group_cipher_set_decryption_callback(group_cipher *cipher, - int (*callback)(group_cipher *cipher, signal_buffer *plaintext, void *decrypt_context)) -{ - assert(cipher); - cipher->decrypt_callback = callback; -} - -int group_cipher_encrypt(group_cipher *cipher, - const uint8_t *padded_plaintext, size_t padded_plaintext_len, - ciphertext_message **encrypted_message) -{ - int result = 0; - sender_key_message *result_message = 0; - sender_key_record *record = 0; - sender_key_state *state = 0; - ec_private_key *signing_key_private = 0; - sender_message_key *sender_key = 0; - sender_chain_key *next_chain_key = 0; - signal_buffer *sender_cipher_key = 0; - signal_buffer *sender_cipher_iv = 0; - signal_buffer *ciphertext = 0; - - assert(cipher); - signal_lock(cipher->global_context); - - if(cipher->inside_callback == 1) { - result = SG_ERR_INVAL; - goto complete; - } - - result = signal_protocol_sender_key_load_key(cipher->store, &record, cipher->sender_key_id); - if(result < 0) { - goto complete; - } - - result = sender_key_record_get_sender_key_state(record, &state); - if(result < 0) { - goto complete; - } - - signing_key_private = sender_key_state_get_signing_key_private(state); - if(!signing_key_private) { - result = SG_ERR_INVALID_KEY; - goto complete; - } - - result = sender_chain_key_create_message_key(sender_key_state_get_chain_key(state), &sender_key); - if(result < 0) { - goto complete; - } - - sender_cipher_key = sender_message_key_get_cipher_key(sender_key); - sender_cipher_iv = sender_message_key_get_iv(sender_key); - - result = signal_encrypt(cipher->global_context, &ciphertext, SG_CIPHER_AES_CBC_PKCS5, - signal_buffer_data(sender_cipher_key), signal_buffer_len(sender_cipher_key), - signal_buffer_data(sender_cipher_iv), signal_buffer_len(sender_cipher_iv), - padded_plaintext, padded_plaintext_len); - if(result < 0) { - goto complete; - } - - result = sender_key_message_create(&result_message, - sender_key_state_get_key_id(state), - sender_message_key_get_iteration(sender_key), - signal_buffer_data(ciphertext), signal_buffer_len(ciphertext), - signing_key_private, - cipher->global_context); - if(result < 0) { - goto complete; - } - - result = sender_chain_key_create_next(sender_key_state_get_chain_key(state), &next_chain_key); - if(result < 0) { - goto complete; - } - - sender_key_state_set_chain_key(state, next_chain_key); - - result = signal_protocol_sender_key_store_key(cipher->store, cipher->sender_key_id, record); - -complete: - if(result >= 0) { - *encrypted_message = (ciphertext_message *)result_message; - } - else { - if(result == SG_ERR_INVALID_KEY_ID) { - result = SG_ERR_NO_SESSION; - } - SIGNAL_UNREF(result_message); - } - signal_buffer_free(ciphertext); - SIGNAL_UNREF(next_chain_key); - SIGNAL_UNREF(sender_key); - SIGNAL_UNREF(record); - signal_unlock(cipher->global_context); - return result; -} - -int group_cipher_decrypt(group_cipher *cipher, - sender_key_message *ciphertext, void *decrypt_context, - signal_buffer **plaintext) -{ - int result = 0; - signal_buffer *result_buf = 0; - sender_key_record *record = 0; - sender_key_state *state = 0; - sender_message_key *sender_key = 0; - signal_buffer *sender_cipher_key = 0; - signal_buffer *sender_cipher_iv = 0; - signal_buffer *ciphertext_body = 0; - - assert(cipher); - signal_lock(cipher->global_context); - - if(cipher->inside_callback == 1) { - result = SG_ERR_INVAL; - goto complete; - } - - result = signal_protocol_sender_key_load_key(cipher->store, &record, cipher->sender_key_id); - if(result < 0) { - goto complete; - } - - if(sender_key_record_is_empty(record)) { - result = SG_ERR_NO_SESSION; - signal_log(cipher->global_context, SG_LOG_WARNING, "No sender key for: %s::%s::%d", - cipher->sender_key_id->group_id, - cipher->sender_key_id->sender.name, - cipher->sender_key_id->sender.device_id); - goto complete; - } - - result = sender_key_record_get_sender_key_state_by_id(record, &state, sender_key_message_get_key_id(ciphertext)); - if(result < 0) { - goto complete; - } - - result = sender_key_message_verify_signature(ciphertext, sender_key_state_get_signing_key_public(state)); - if(result < 0) { - goto complete; - } - - result = group_cipher_get_sender_key(cipher, &sender_key, state, sender_key_message_get_iteration(ciphertext)); - if(result < 0) { - goto complete; - } - - sender_cipher_key = sender_message_key_get_cipher_key(sender_key); - sender_cipher_iv = sender_message_key_get_iv(sender_key); - ciphertext_body = sender_key_message_get_ciphertext(ciphertext); - - result = signal_decrypt(cipher->global_context, &result_buf, SG_CIPHER_AES_CBC_PKCS5, - signal_buffer_data(sender_cipher_key), signal_buffer_len(sender_cipher_key), - signal_buffer_data(sender_cipher_iv), signal_buffer_len(sender_cipher_iv), - signal_buffer_data(ciphertext_body), signal_buffer_len(ciphertext_body)); - if(result < 0) { - goto complete; - } - - result = group_cipher_decrypt_callback(cipher, result_buf, decrypt_context); - if(result < 0) { - goto complete; - } - - result = signal_protocol_sender_key_store_key(cipher->store, cipher->sender_key_id, record); - -complete: - SIGNAL_UNREF(sender_key); - SIGNAL_UNREF(record); - if(result >= 0) { - *plaintext = result_buf; - } - else { - if(result == SG_ERR_INVALID_KEY || result == SG_ERR_INVALID_KEY_ID) { - result = SG_ERR_INVALID_MESSAGE; - } - signal_buffer_free(result_buf); - } - signal_unlock(cipher->global_context); - return result; -} - -int group_cipher_get_sender_key(group_cipher *cipher, sender_message_key **sender_key, sender_key_state *state, uint32_t iteration) -{ - int result = 0; - sender_message_key *result_key = 0; - sender_chain_key *chain_key = 0; - sender_chain_key *next_chain_key = 0; - sender_message_key *message_key = 0; - - chain_key = sender_key_state_get_chain_key(state); - SIGNAL_REF(chain_key); - - if(sender_chain_key_get_iteration(chain_key) > iteration) { - if(sender_key_state_has_sender_message_key(state, iteration)) { - result_key = sender_key_state_remove_sender_message_key(state, iteration); - if(!result_key) { - result = SG_ERR_UNKNOWN; - } - goto complete; - } - else { - result = SG_ERR_DUPLICATE_MESSAGE; - signal_log(cipher->global_context, SG_LOG_WARNING, - "Received message with old counter: %d, %d", - sender_chain_key_get_iteration(chain_key), iteration); - goto complete; - } - } - - if(iteration - sender_chain_key_get_iteration(chain_key) > 2000) { - result = SG_ERR_INVALID_MESSAGE; - signal_log(cipher->global_context, SG_LOG_WARNING, "Over 2000 messages into the future!"); - goto complete; - } - - while(sender_chain_key_get_iteration(chain_key) < iteration) { - result = sender_chain_key_create_message_key(chain_key, &message_key); - if(result < 0) { - goto complete; - } - - result = sender_key_state_add_sender_message_key(state, message_key); - if(result < 0) { - goto complete; - } - SIGNAL_UNREF(message_key); - - result = sender_chain_key_create_next(chain_key, &next_chain_key); - if(result < 0) { - goto complete; - } - - SIGNAL_UNREF(chain_key); - chain_key = next_chain_key; - next_chain_key = 0; - } - - result = sender_chain_key_create_next(chain_key, &next_chain_key); - if(result < 0) { - goto complete; - } - - sender_key_state_set_chain_key(state, next_chain_key); - result = sender_chain_key_create_message_key(chain_key, &result_key); - -complete: - SIGNAL_UNREF(message_key); - SIGNAL_UNREF(chain_key); - SIGNAL_UNREF(next_chain_key); - if(result >= 0) { - *sender_key = result_key; - } - return result; -} - -static int group_cipher_decrypt_callback(group_cipher *cipher, signal_buffer *plaintext, void *decrypt_context) -{ - int result = 0; - if(cipher->decrypt_callback) { - cipher->inside_callback = 1; - result = cipher->decrypt_callback(cipher, plaintext, decrypt_context); - cipher->inside_callback = 0; - } - return result; -} - -void group_cipher_free(group_cipher *cipher) -{ - if(cipher) { - free(cipher); - } -} diff --git a/src/group_cipher.h b/src/group_cipher.h deleted file mode 100644 index 50b194c0..00000000 --- a/src/group_cipher.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef GROUP_CIPHER_H -#define GROUP_CIPHER_H - -#include -#include -#include "signal_protocol_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * The main entry point for Signal Protocol group encrypt/decrypt operations. - * - * Once a session has been established with group_session_builder and a - * sender_key_distribution_message has been distributed to each member of - * the group, this class can be used for all subsequent encrypt/decrypt - * operations within that session (i.e. until group membership changes). - */ - -/** - * Construct a group cipher for encrypt/decrypt operations. - * - * The store and global contexts must remain valid for the lifetime of the - * group cipher. - * - * When finished, free the returned instance by calling group_cipher_free(). - * - * @param cipher set to a freshly allocated group cipher instance - * @param store the signal_protocol_store_context to store all state information in - * @param sender_key_id the sender that messages will be encrypted to or decrypted from - * @param global_context the global library context - * @return 0 on success, or negative on failure - */ -int group_cipher_create(group_cipher **cipher, - signal_protocol_store_context *store, const signal_protocol_sender_key_name *sender_key_id, - signal_context *global_context); - -/** - * Set the optional user data pointer for the group cipher. - * - * This is to give callback functions a way of accessing app specific - * context information for this cipher. - */ -void group_cipher_set_user_data(group_cipher *cipher, void *user_data); - -/** - * Get the optional user data pointer for the group cipher. - * - * This is to give callback functions a way of accessing app specific - * context information for this cipher. - */ -void *group_cipher_get_user_data(group_cipher *cipher); - -/** - * Set the callback function that is called during the decrypt process. - * - * The callback function is called from within group_cipher_decrypt() after - * decryption is complete but before the updated session state has been - * committed to the session store. If the callback function returns a - * negative value, then the decrypt function will immediately fail with - * an error. - * - * This a callback allows some implementations to store the committed plaintext - * to their local message store first, in case they are concerned with a crash - * or write error happening between the time the session state is updated but - * before they're able to successfully store the plaintext to disk. - * - * @param callback the callback function to set - */ -void group_cipher_set_decryption_callback(group_cipher *cipher, - int (*callback)(group_cipher *cipher, signal_buffer *plaintext, void *decrypt_context)); - -/** - * Encrypt a message. - * - * @param padded_plaintext The plaintext message bytes, optionally padded to a constant multiple. - * @param padded_plaintext_len The length of the data pointed to by padded_message - * @param encrypted_message Set to a ciphertext message encrypted to the group+sender+device tuple. - * - * @retval SG_SUCCESS Success - * @retval SG_ERR_NO_SESSION if there is no established session for this contact. - * @retval SG_ERR_INVALID_KEY if there is no valid private key for this session. - */ -int group_cipher_encrypt(group_cipher *cipher, - const uint8_t *padded_plaintext, size_t padded_plaintext_len, - ciphertext_message **encrypted_message); - -/** - * Decrypt a message. - * - * @param ciphertext The sender_key_message to decrypt. - * @param decrypt_context Optional context pointer associated with the - * ciphertext, which is passed to the decryption callback function - * @param plaintext Set to a newly allocated buffer containing the plaintext. - * - * @retval SG_SUCCESS Success - * @retval SG_ERR_INVALID_MESSAGE if the input is not valid ciphertext. - * @retval SG_ERR_DUPLICATE_MESSAGE if the input is a message that has already been received. - * @retval SG_ERR_LEGACY_MESSAGE if the input is a message formatted by a protocol version that - * is no longer supported. - * @retval SG_ERR_NO_SESSION if there is no established session for this contact. - */ -int group_cipher_decrypt(group_cipher *cipher, - sender_key_message *ciphertext, void *decrypt_context, - signal_buffer **plaintext); - -void group_cipher_free(group_cipher *cipher); - -#ifdef __cplusplus -} -#endif - -#endif /* GROUP_CIPHER_H */ diff --git a/src/group_session_builder.c b/src/group_session_builder.c deleted file mode 100644 index 13db334c..00000000 --- a/src/group_session_builder.c +++ /dev/null @@ -1,149 +0,0 @@ -#include "group_session_builder.h" - -#include -#include -#include "sender_key_record.h" -#include "sender_key_state.h" -#include "sender_key.h" -#include "protocol.h" -#include "key_helper.h" -#include "signal_protocol_internal.h" - -struct group_session_builder -{ - signal_protocol_store_context *store; - signal_context *global_context; -}; - -int group_session_builder_create(group_session_builder **builder, - signal_protocol_store_context *store, signal_context *global_context) -{ - group_session_builder *result = 0; - - assert(store); - assert(global_context); - - result = malloc(sizeof(group_session_builder)); - if(!result) { - return SG_ERR_NOMEM; - } - memset(result, 0, sizeof(group_session_builder)); - - result->store = store; - result->global_context = global_context; - - *builder = result; - return 0; -} - -int group_session_builder_process_session(group_session_builder *builder, - const signal_protocol_sender_key_name *sender_key_name, - sender_key_distribution_message *distribution_message) -{ - int result = 0; - sender_key_record *record = 0; - - assert(builder); - assert(builder->store); - signal_lock(builder->global_context); - - result = signal_protocol_sender_key_load_key(builder->store, &record, sender_key_name); - if(result < 0) { - goto complete; - } - - result = sender_key_record_add_sender_key_state(record, - sender_key_distribution_message_get_id(distribution_message), - sender_key_distribution_message_get_iteration(distribution_message), - sender_key_distribution_message_get_chain_key(distribution_message), - sender_key_distribution_message_get_signature_key(distribution_message)); - if(result < 0) { - goto complete; - } - - result = signal_protocol_sender_key_store_key(builder->store, sender_key_name, record); - -complete: - SIGNAL_UNREF(record); - signal_unlock(builder->global_context); - return result; -} - -int group_session_builder_create_session(group_session_builder *builder, - sender_key_distribution_message **distribution_message, - const signal_protocol_sender_key_name *sender_key_name) -{ - int result = 0; - sender_key_record *record = 0; - sender_key_state *state = 0; - uint32_t sender_key_id = 0; - signal_buffer *sender_key = 0; - ec_key_pair *sender_signing_key = 0; - sender_chain_key *chain_key = 0; - signal_buffer *seed = 0; - - assert(builder); - assert(builder->store); - signal_lock(builder->global_context); - - result = signal_protocol_sender_key_load_key(builder->store, &record, sender_key_name); - if(result < 0) { - goto complete; - } - - if(sender_key_record_is_empty(record)) { - result = signal_protocol_key_helper_generate_sender_key_id(&sender_key_id, builder->global_context); - if(result < 0) { - goto complete; - } - - result = signal_protocol_key_helper_generate_sender_key(&sender_key, builder->global_context); - if(result < 0) { - goto complete; - } - - result = signal_protocol_key_helper_generate_sender_signing_key(&sender_signing_key, builder->global_context); - if(result < 0) { - goto complete; - } - - result = sender_key_record_set_sender_key_state(record, sender_key_id, 0, sender_key, sender_signing_key); - if(result < 0) { - goto complete; - } - - result = signal_protocol_sender_key_store_key(builder->store, sender_key_name, record); - if(result < 0) { - goto complete; - } - } - - result = sender_key_record_get_sender_key_state(record, &state); - if(result < 0) { - goto complete; - } - - chain_key = sender_key_state_get_chain_key(state); - seed = sender_chain_key_get_seed(chain_key); - - result = sender_key_distribution_message_create(distribution_message, - sender_key_state_get_key_id(state), - sender_chain_key_get_iteration(chain_key), - signal_buffer_data(seed), signal_buffer_len(seed), - sender_key_state_get_signing_key_public(state), - builder->global_context); - -complete: - signal_buffer_free(sender_key); - SIGNAL_UNREF(sender_signing_key); - SIGNAL_UNREF(record); - signal_unlock(builder->global_context); - return result; -} - -void group_session_builder_free(group_session_builder *builder) -{ - if(builder) { - free(builder); - } -} diff --git a/src/group_session_builder.h b/src/group_session_builder.h deleted file mode 100644 index 1d87d53a..00000000 --- a/src/group_session_builder.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef GROUP_SESSION_BUILDER_H -#define GROUP_SESSION_BUILDER_H - -#include "signal_protocol_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Group session builder is responsible for setting up group sender key encrypted sessions. - * - * Once a session has been established, group_cipher can be used to - * encrypt/decrypt messages in that session. - *

- * The built sessions are unidirectional: they can be used either for sending - * or for receiving, but not both. - * - * Sessions are constructed per (groupId + senderId + deviceId) tuple. Remote logical users - * are identified by their senderId, and each logical recipientId can have multiple physical - * devices. - */ - -/** - * Constructs a group session builder. - * - * The store and global contexts must remain valid for the lifetime of the - * session builder. - * - * When finished, free the returned instance by calling group_session_builder_free(). - * - * @param builder set to a freshly allocated group session builder instance - * @param store the signal_protocol_store_context to store all state information in - * @param global_context the global library context - * @return 0 on success, or negative on failure - */ -int group_session_builder_create(group_session_builder **builder, - signal_protocol_store_context *store, signal_context *global_context); - -/** - * Construct a group session for receiving messages from senderKeyName. - * - * @param sender_key_name the (groupId, senderId, deviceId) tuple associated - * with the sender_key_distribution_message - * @param distribution_message a received sender_key_distribution_message - * @return 0 on success, or negative on failure - */ -int group_session_builder_process_session(group_session_builder *builder, - const signal_protocol_sender_key_name *sender_key_name, - sender_key_distribution_message *distribution_message); - -/** - * Construct a group session for sending messages. - * - * @param distribution_message a distribution message to be allocated and populated - * @param sender_key_name the (groupId, senderId, deviceId) tuple. In this - * case, the sender should be the caller - * @return 0 on success, or negative on failure - */ -int group_session_builder_create_session(group_session_builder *builder, - sender_key_distribution_message **distribution_message, - const signal_protocol_sender_key_name *sender_key_name); - -void group_session_builder_free(group_session_builder *builder); - -#ifdef __cplusplus -} -#endif - -#endif /* GROUP_SESSION_BUILDER_H */ diff --git a/src/key_helper.c b/src/key_helper.c index e2de8d48..5c82cc0a 100644 --- a/src/key_helper.c +++ b/src/key_helper.c @@ -211,7 +211,9 @@ int signal_protocol_key_helper_generate_signed_pre_key(session_signed_pre_key ** session_signed_pre_key *result_signed_pre_key = 0; ec_key_pair *ec_pair = 0; signal_buffer *public_buf = 0; + signal_buffer *public_omemo_buf = 0; signal_buffer *signature_buf = 0; + signal_buffer *signature_omemo_buf = 0; ec_public_key *public_key = 0; ec_private_key *private_key = 0; @@ -227,6 +229,10 @@ int signal_protocol_key_helper_generate_signed_pre_key(session_signed_pre_key ** if(result < 0) { goto complete; } + result = ec_public_key_serialize_omemo(&public_omemo_buf, public_key); + if(result < 0) { + goto complete; + } private_key = ratchet_identity_key_pair_get_private(identity_key_pair); @@ -238,17 +244,81 @@ int signal_protocol_key_helper_generate_signed_pre_key(session_signed_pre_key ** if(result < 0) { goto complete; } + result = curve_calculate_signature(global_context, + &signature_omemo_buf, + private_key, + signal_buffer_data(public_omemo_buf), + signal_buffer_len(public_omemo_buf)); + if(result < 0) { + goto complete; + } result = session_signed_pre_key_create(&result_signed_pre_key, signed_pre_key_id, timestamp, ec_pair, signal_buffer_data(signature_buf), - signal_buffer_len(signature_buf)); + signal_buffer_len(signature_buf), + signal_buffer_data(signature_omemo_buf), + signal_buffer_len(signature_omemo_buf)); complete: SIGNAL_UNREF(ec_pair); signal_buffer_free(public_buf); + signal_buffer_free(public_omemo_buf); signal_buffer_free(signature_buf); + signal_buffer_free(signature_omemo_buf); + if(result >= 0) { + *signed_pre_key = result_signed_pre_key; + } + return result; +} + +int signal_protocol_key_helper_upgrade_signed_pre_key(session_signed_pre_key **signed_pre_key, + const ratchet_identity_key_pair *identity_key_pair, + signal_context *global_context) +{ + int result = 0; + session_signed_pre_key *result_signed_pre_key = 0; + signal_buffer *public_omemo_buf = 0; + signal_buffer *signature_omemo_buf = 0; + ec_public_key *public_key = 0; + ec_private_key *private_key = 0; + + assert(global_context); + if (session_signed_pre_key_get_signature_omemo_len(*signed_pre_key) > 0) { + return result; + } + + public_key = ec_key_pair_get_public(session_signed_pre_key_get_key_pair(*signed_pre_key)); + result = ec_public_key_serialize_omemo(&public_omemo_buf, public_key); + if(result < 0) { + goto complete; + } + + private_key = ratchet_identity_key_pair_get_private(identity_key_pair); + + result = curve_calculate_signature(global_context, + &signature_omemo_buf, + private_key, + signal_buffer_data(public_omemo_buf), + signal_buffer_len(public_omemo_buf)); + if(result < 0) { + goto complete; + } + + result = session_signed_pre_key_create(&result_signed_pre_key, + session_signed_pre_key_get_id(*signed_pre_key), + session_signed_pre_key_get_timestamp(*signed_pre_key), + session_signed_pre_key_get_key_pair(*signed_pre_key), + session_signed_pre_key_get_signature(*signed_pre_key), + session_signed_pre_key_get_signature_len(*signed_pre_key), + signal_buffer_data(signature_omemo_buf), + signal_buffer_len(signature_omemo_buf)); + +complete: + signal_buffer_free(public_omemo_buf); + signal_buffer_free(signature_omemo_buf); if(result >= 0) { + SIGNAL_UNREF(*signed_pre_key); *signed_pre_key = result_signed_pre_key; } return result; diff --git a/src/key_helper.h b/src/key_helper.h index f0e5e560..4f8d2ad8 100644 --- a/src/key_helper.h +++ b/src/key_helper.h @@ -99,6 +99,10 @@ int signal_protocol_key_helper_generate_signed_pre_key(session_signed_pre_key ** uint64_t timestamp, signal_context *global_context); +int signal_protocol_key_helper_upgrade_signed_pre_key(session_signed_pre_key **signed_pre_key, + const ratchet_identity_key_pair *identity_key_pair, + signal_context *global_context); + /* * Generate a sender signing key pair * diff --git a/src/protocol.c b/src/protocol.c index e6296e50..7c1c8eca 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -72,6 +72,7 @@ static int signal_message_get_mac(signal_buffer **buffer, ec_public_key *receiver_identity_key, const uint8_t *mac_key, size_t mac_key_len, const uint8_t *serialized, size_t serialized_len, + uint8_t sender_is_alice, signal_context *global_context); static int pre_key_signal_message_serialize(signal_buffer **buffer, const pre_key_signal_message *message); @@ -101,6 +102,7 @@ int signal_message_create(signal_message **message, uint8_t message_version, ec_public_key *sender_ratchet_key, uint32_t counter, uint32_t previous_counter, const uint8_t *ciphertext, size_t ciphertext_len, ec_public_key *sender_identity_key, ec_public_key *receiver_identity_key, + uint8_t sender_is_alice, signal_context *global_context) { int result = 0; @@ -143,6 +145,7 @@ int signal_message_create(signal_message **message, uint8_t message_version, mac_key, mac_key_len, signal_buffer_data(message_buf), signal_buffer_len(message_buf), + sender_is_alice, global_context); if(result < 0) { goto complete; @@ -249,7 +252,7 @@ static int signal_message_serialize_omemo(signal_buffer **buffer, const signal_m Omemo__OMEMOMessage message_structure = OMEMO__OMEMOMESSAGE__INIT; size_t len = 0; - result = ec_public_key_serialize_protobuf(&message_structure.dh_pub, message->sender_ratchet_key); + result = ec_public_key_serialize_protobuf_mont(&message_structure.dh_pub, message->sender_ratchet_key); if(result < 0) { goto complete; } @@ -469,7 +472,7 @@ int signal_message_deserialize_omemo(signal_message **message, const uint8_t *da result_message->base_message.message_type = CIPHERTEXT_SIGNAL_TYPE; result_message->base_message.global_context = global_context; - result = curve_decode_point(&result_message->sender_ratchet_key, message_structure->dh_pub.data, message_structure->dh_pub.len, global_context); + result = curve_decode_point_mont(&result_message->sender_ratchet_key, message_structure->dh_pub.data, message_structure->dh_pub.len, global_context); if(result < 0) { goto complete; } @@ -580,6 +583,7 @@ int signal_message_verify_mac(signal_message *message, ec_public_key *sender_identity_key, ec_public_key *receiver_identity_key, const uint8_t *mac_key, size_t mac_key_len, + uint8_t sender_is_alice, signal_context *global_context) { int result = 0; @@ -617,6 +621,7 @@ int signal_message_verify_mac(signal_message *message, sender_identity_key, receiver_identity_key, mac_key, mac_key_len, serialized_message_data, serialized_message_len, + sender_is_alice, message->base_message.global_context); if(result < 0) { goto complete; @@ -651,12 +656,13 @@ static int signal_message_get_mac(signal_buffer **buffer, ec_public_key *receiver_identity_key, const uint8_t *mac_key, size_t mac_key_len, const uint8_t *serialized, size_t serialized_len, + uint8_t sender_is_alice, signal_context *global_context) { int result = 0; void *hmac_context; - signal_buffer *sender_key_buffer = 0; - signal_buffer *receiver_key_buffer = 0; + signal_buffer *first_key_buffer = 0; + signal_buffer *second_key_buffer = 0; signal_buffer *full_mac_buffer = 0; signal_buffer *result_buf = 0; uint8_t *result_data = 0; @@ -671,26 +677,42 @@ static int signal_message_get_mac(signal_buffer **buffer, } if(message_version >= 3) { - result = ec_public_key_serialize(&sender_key_buffer, sender_identity_key); - if(result < 0) { + if (message_version >= 4) { + if (sender_is_alice) { + first_key_buffer = ec_public_key_get_ed(sender_identity_key); + } else { + first_key_buffer = ec_public_key_get_ed(receiver_identity_key); + } + } else { + result = ec_public_key_serialize(&first_key_buffer, sender_identity_key); + } + if(first_key_buffer == 0 || result < 0) { goto complete; } result = signal_hmac_sha256_update(global_context, hmac_context, - signal_buffer_data(sender_key_buffer), - signal_buffer_len(sender_key_buffer)); + signal_buffer_data(first_key_buffer), + signal_buffer_len(first_key_buffer)); if(result < 0) { goto complete; } - result = ec_public_key_serialize(&receiver_key_buffer, receiver_identity_key); - if(result < 0) { + if (message_version >= 4) { + if (sender_is_alice) { + second_key_buffer = ec_public_key_get_ed(receiver_identity_key); + } else { + second_key_buffer = ec_public_key_get_ed(sender_identity_key); + } + } else { + result = ec_public_key_serialize(&second_key_buffer, receiver_identity_key); + } + if(second_key_buffer == 0 || result < 0) { goto complete; } result = signal_hmac_sha256_update(global_context, hmac_context, - signal_buffer_data(receiver_key_buffer), - signal_buffer_len(receiver_key_buffer)); + signal_buffer_data(second_key_buffer), + signal_buffer_len(second_key_buffer)); if(result < 0) { goto complete; } @@ -720,8 +742,8 @@ static int signal_message_get_mac(signal_buffer **buffer, complete: signal_hmac_sha256_cleanup(global_context, hmac_context); - signal_buffer_free(sender_key_buffer); - signal_buffer_free(receiver_key_buffer); + signal_buffer_free(first_key_buffer); + signal_buffer_free(second_key_buffer); signal_buffer_free(full_mac_buffer); if(result >= 0) { *buffer = result_buf; @@ -894,12 +916,12 @@ static int pre_key_signal_message_serialize_omemo(signal_buffer **buffer, const message_structure.pk_id = message->pre_key_id; message_structure.spk_id = message->signed_pre_key_id; - result = ec_public_key_serialize_protobuf(&message_structure.ek, message->base_key); + result = ec_public_key_serialize_protobuf_mont(&message_structure.ek, message->base_key); if(result < 0) { goto complete; } - result = ec_public_key_serialize_protobuf(&message_structure.ik, message->identity_key); + result = ec_public_key_serialize_protobuf_ed(&message_structure.ik, message->identity_key); if(result < 0) { goto complete; } @@ -1016,7 +1038,7 @@ int pre_key_signal_message_deserialize(pre_key_signal_message **message, } if(message_structure->has_basekey) { - result = curve_decode_point(&result_message->base_key, + result = curve_decode_point_mont(&result_message->base_key, message_structure->basekey.data, message_structure->basekey.len, global_context); if(result < 0) { goto complete; @@ -1107,7 +1129,7 @@ int pre_key_signal_message_deserialize_omemo(pre_key_signal_message **message, result_message->signed_pre_key_id = message_structure->spk_id; - result = curve_decode_point(&result_message->base_key, message_structure->ek.data, message_structure->ek.len, global_context); + result = curve_decode_point_mont(&result_message->base_key, message_structure->ek.data, message_structure->ek.len, global_context); if(result < 0) { goto complete; } diff --git a/src/protocol.h b/src/protocol.h index f4f243be..6f6ea3a0 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -33,6 +33,7 @@ int signal_message_create(signal_message **message, uint8_t message_version, ec_public_key *sender_ratchet_key, uint32_t counter, uint32_t previous_counter, const uint8_t *ciphertext, size_t ciphertext_len, ec_public_key *sender_identity_key, ec_public_key *receiver_identity_key, + uint8_t sender_is_alice, signal_context *global_context); int signal_message_deserialize(signal_message **message, const uint8_t *data, size_t len, @@ -59,6 +60,7 @@ int signal_message_verify_mac(signal_message *message, ec_public_key *sender_identity_key, ec_public_key *receiver_identity_key, const uint8_t *mac_key, size_t mac_key_len, + uint8_t sender_is_alice, signal_context *global_context); int signal_message_is_legacy(const uint8_t *data, size_t len); diff --git a/src/ratchet.c b/src/ratchet.c index f925c76b..f1d64086 100644 --- a/src/ratchet.c +++ b/src/ratchet.c @@ -1112,6 +1112,7 @@ int ratcheting_session_alice_initialize( session_state_set_local_identity_key(state, parameters->our_identity_key->public_key); session_state_set_sender_chain(state, sending_ratchet_key, sending_chain_key); session_state_set_root_key(state, sending_chain_root); + session_state_set_local_is_alice(state, 1); complete: vpool_final(&vp); @@ -1239,6 +1240,7 @@ int ratcheting_session_bob_initialize( session_state_set_local_identity_key(state, parameters->our_identity_key->public_key); session_state_set_sender_chain(state, parameters->our_ratchet_key, derived_chain); session_state_set_root_key(state, derived_root); + session_state_set_local_is_alice(state, 0); } vpool_final(&vp); diff --git a/src/session_builder.c b/src/session_builder.c index f84b76c7..1065f84c 100644 --- a/src/session_builder.c +++ b/src/session_builder.c @@ -241,7 +241,11 @@ int session_builder_process_pre_key_bundle(session_builder *builder, session_pre signal_buffer *signature = session_pre_key_bundle_get_signed_pre_key_signature(bundle); signal_buffer *serialized_signed_pre_key = 0; - result = ec_public_key_serialize(&serialized_signed_pre_key, signed_pre_key); + if (session_builder_get_version(builder) < 4) { + result = ec_public_key_serialize(&serialized_signed_pre_key, signed_pre_key); + } else { + result = ec_public_key_serialize_omemo(&serialized_signed_pre_key, signed_pre_key); + } if(result < 0) { goto complete; } diff --git a/src/session_cipher.c b/src/session_cipher.c index f6ef2b58..a1f0150d 100644 --- a/src/session_cipher.c +++ b/src/session_cipher.c @@ -197,6 +197,7 @@ int session_cipher_encrypt(session_cipher *cipher, chain_key_index, previous_counter, ciphertext_data, ciphertext_len, local_identity_key, remote_identity_key, + session_state_get_local_is_alice(state), cipher->global_context); if(result < 0) { goto complete; @@ -525,6 +526,7 @@ static int session_cipher_decrypt_from_state_and_signal_message(session_cipher * result = signal_message_verify_mac(ciphertext, remote_identity_key, local_identity_key, message_keys.mac_key, sizeof(message_keys.mac_key), + !session_state_get_local_is_alice(state), cipher->global_context); if(result != 1) { if(result == 0) { diff --git a/src/session_pre_key.c b/src/session_pre_key.c index 416ed6a1..93c3054c 100644 --- a/src/session_pre_key.c +++ b/src/session_pre_key.c @@ -20,7 +20,8 @@ struct session_signed_pre_key { ec_key_pair *key_pair; uint64_t timestamp; size_t signature_len; - uint8_t signature[]; + size_t signature_omemo_len; + uint8_t signatures[]; }; struct session_pre_key_bundle { @@ -214,19 +215,21 @@ void session_pre_key_destroy(signal_type_base *type) int session_signed_pre_key_create(session_signed_pre_key **pre_key, uint32_t id, uint64_t timestamp, ec_key_pair *key_pair, - const uint8_t *signature, size_t signature_len) + const uint8_t *signature, size_t signature_len, + const uint8_t *signature_omemo, size_t signature_omemo_len) { session_signed_pre_key *result = 0; assert(key_pair); assert(signature); assert(signature_len > 0); + assert(signature_omemo_len == 0 || signature_omemo); - if(signature_len > (SIZE_MAX - sizeof(session_signed_pre_key)) / sizeof(uint8_t)) { + if(signature_len + signature_omemo_len > (SIZE_MAX - sizeof(session_signed_pre_key)) / sizeof(uint8_t)) { return SG_ERR_NOMEM; } - result = malloc(sizeof(session_signed_pre_key) + (sizeof(uint8_t) * signature_len)); + result = malloc(sizeof(session_signed_pre_key) + (sizeof(uint8_t) * signature_len) + (sizeof(uint8_t) * signature_omemo_len)); if(!result) { return SG_ERR_NOMEM; } @@ -240,8 +243,12 @@ int session_signed_pre_key_create(session_signed_pre_key **pre_key, result->key_pair = key_pair; result->signature_len = signature_len; + result->signature_omemo_len = signature_omemo_len; - memcpy(result->signature, signature, signature_len); + memcpy(result->signatures, signature, signature_len); + if (signature_omemo_len > 0) { + memcpy(result->signatures + signature_len, signature_omemo, signature_omemo_len); + } *pre_key = result; return 0; @@ -255,6 +262,7 @@ int session_signed_pre_key_serialize(signal_buffer **buffer, const session_signe signal_buffer *public_buf = 0; signal_buffer *private_buf = 0; signal_buffer *signature_buf = 0; + signal_buffer *signature_omemo_buf = 0; signal_buffer *result_buf = 0; ec_public_key *public_key = 0; ec_private_key *private_key = 0; @@ -273,12 +281,18 @@ int session_signed_pre_key_serialize(signal_buffer **buffer, const session_signe goto complete; } - signature_buf = signal_buffer_create(pre_key->signature, pre_key->signature_len); + signature_buf = signal_buffer_create(pre_key->signatures, pre_key->signature_len); if(!signature_buf) { result = SG_ERR_NOMEM; goto complete; } + signature_omemo_buf = signal_buffer_create(pre_key->signatures+pre_key->signature_len, pre_key->signature_omemo_len); + if(!signature_omemo_buf) { + result = SG_ERR_NOMEM; + goto complete; + } + record.has_id = 1; record.id = pre_key->id; @@ -297,6 +311,10 @@ int session_signed_pre_key_serialize(signal_buffer **buffer, const session_signe record.signature.data = signal_buffer_data(signature_buf); record.signature.len = signal_buffer_len(signature_buf); + record.has_signature_omemo = 1; + record.signature_omemo.data = signal_buffer_data(signature_omemo_buf); + record.signature_omemo.len = signal_buffer_len(signature_omemo_buf); + len = textsecure__signed_pre_key_record_structure__get_packed_size(&record); result_buf = signal_buffer_alloc(len); @@ -324,6 +342,9 @@ int session_signed_pre_key_serialize(signal_buffer **buffer, const session_signe if(signature_buf) { signal_buffer_free(signature_buf); } + if(signature_omemo_buf) { + signal_buffer_free(signature_omemo_buf); + } if(result >= 0) { *buffer = result_buf; } @@ -367,9 +388,17 @@ int session_signed_pre_key_deserialize(session_signed_pre_key **pre_key, const u goto complete; } - result = session_signed_pre_key_create(&result_pre_key, - record->id, record->timestamp, key_pair, - record->signature.data, record->signature.len); + if (record->has_signature_omemo) { + result = session_signed_pre_key_create(&result_pre_key, + record->id, record->timestamp, key_pair, + record->signature.data, record->signature.len, + record->signature_omemo.data, record->signature_omemo.len); + } else { + result = session_signed_pre_key_create(&result_pre_key, + record->id, record->timestamp, key_pair, + record->signature.data, record->signature.len, + NULL, 0); + } if(result < 0) { goto complete; } @@ -410,7 +439,7 @@ ec_key_pair *session_signed_pre_key_get_key_pair(const session_signed_pre_key *p const uint8_t *session_signed_pre_key_get_signature(const session_signed_pre_key *pre_key) { - return pre_key->signature; + return pre_key->signatures; } size_t session_signed_pre_key_get_signature_len(const session_signed_pre_key *pre_key) @@ -418,6 +447,16 @@ size_t session_signed_pre_key_get_signature_len(const session_signed_pre_key *pr return pre_key->signature_len; } +const uint8_t *session_signed_pre_key_get_signature_omemo(const session_signed_pre_key *pre_key) +{ + return pre_key->signatures + pre_key->signature_len; +} + +size_t session_signed_pre_key_get_signature_omemo_len(const session_signed_pre_key *pre_key) +{ + return pre_key->signature_omemo_len; +} + void session_signed_pre_key_destroy(signal_type_base *type) { session_signed_pre_key *pre_key = (session_signed_pre_key *)type; diff --git a/src/session_pre_key.h b/src/session_pre_key.h index ff8a9a8d..29114e4d 100644 --- a/src/session_pre_key.h +++ b/src/session_pre_key.h @@ -26,7 +26,8 @@ void session_pre_key_destroy(signal_type_base *type); int session_signed_pre_key_create(session_signed_pre_key **pre_key, uint32_t id, uint64_t timestamp, ec_key_pair *key_pair, - const uint8_t *signature, size_t signature_len); + const uint8_t *signature, size_t signature_len, + const uint8_t *signature_omemo, size_t signature_omemo_len); int session_signed_pre_key_serialize(signal_buffer **buffer, const session_signed_pre_key *pre_key); int session_signed_pre_key_deserialize(session_signed_pre_key **pre_key, const uint8_t *data, size_t len, signal_context *global_context); @@ -35,6 +36,8 @@ uint64_t session_signed_pre_key_get_timestamp(const session_signed_pre_key *pre_ ec_key_pair *session_signed_pre_key_get_key_pair(const session_signed_pre_key *pre_key); const uint8_t *session_signed_pre_key_get_signature(const session_signed_pre_key *pre_key); size_t session_signed_pre_key_get_signature_len(const session_signed_pre_key *pre_key); +const uint8_t *session_signed_pre_key_get_signature_omemo(const session_signed_pre_key *pre_key); +size_t session_signed_pre_key_get_signature_omemo_len(const session_signed_pre_key *pre_key); void session_signed_pre_key_destroy(signal_type_base *type); diff --git a/src/session_state.c b/src/session_state.c index 2df6a925..1370b0b5 100644 --- a/src/session_state.c +++ b/src/session_state.c @@ -78,6 +78,8 @@ struct session_state int needs_refresh; ec_public_key *alice_base_key; + uint8_t local_is_alice; + signal_context *global_context; }; @@ -241,8 +243,13 @@ int session_state_serialize_prepare(session_state *state, Textsecure__SessionStr session_structure->sessionversion = state->session_version; if(state->local_identity_public) { - result = ec_public_key_serialize_protobuf( - &session_structure->localidentitypublic, state->local_identity_public); + if (state->session_version < 4) { + result = ec_public_key_serialize_protobuf( + &session_structure->localidentitypublic, state->local_identity_public); + } else { + result = ec_public_key_serialize_protobuf_ed( + &session_structure->localidentitypublic, state->local_identity_public); + } if(result < 0) { goto complete; } @@ -250,8 +257,13 @@ int session_state_serialize_prepare(session_state *state, Textsecure__SessionStr } if(state->remote_identity_public) { - result = ec_public_key_serialize_protobuf( - &session_structure->remoteidentitypublic, state->remote_identity_public); + if (state->session_version < 4) { + result = ec_public_key_serialize_protobuf( + &session_structure->remoteidentitypublic, state->remote_identity_public); + } else { + result = ec_public_key_serialize_protobuf_ed( + &session_structure->remoteidentitypublic, state->remote_identity_public); + } if(result < 0) { goto complete; } @@ -368,6 +380,9 @@ int session_state_serialize_prepare(session_state *state, Textsecure__SessionStr session_structure->has_alicebasekey = 1; } + session_structure->has_localisalice = 1; + session_structure->localisalice = state->local_is_alice; + complete: return result; } @@ -903,6 +918,12 @@ int session_state_deserialize_protobuf(session_state **state, Textsecure__Sessio } } + if (session_structure->has_localisalice) { + result_state->local_is_alice = session_structure->localisalice; + } else { + result_state->local_is_alice = 1; // We are alice by default + } + complete: if(result >= 0) { *state = result_state; @@ -1778,6 +1799,18 @@ ec_public_key *session_state_get_alice_base_key(const session_state *state) return state->alice_base_key; } +void session_state_set_local_is_alice(session_state *state, uint8_t local_is_alice) +{ + assert(state); + state->local_is_alice = local_is_alice; +} + +uint8_t session_state_get_local_is_alice(const session_state *state) +{ + assert(state); + return state->local_is_alice; +} + static void session_state_free_sender_chain(session_state *state) { if(state->sender_chain.sender_ratchet_key_pair) { diff --git a/src/session_state.h b/src/session_state.h index d47692de..b091ef45 100644 --- a/src/session_state.h +++ b/src/session_state.h @@ -83,6 +83,9 @@ const struct ratchet_kdf_infos *session_state_get_kdf_infos(const session_state void session_state_set_alice_base_key(session_state *state, ec_public_key *key); ec_public_key *session_state_get_alice_base_key(const session_state *state); +void session_state_set_local_is_alice(session_state *state, uint8_t local_is_alice); +uint8_t session_state_get_local_is_alice(const session_state *state); + void session_state_destroy(signal_type_base *type); #ifdef __cplusplus diff --git a/src/signal_protocol_internal.h b/src/signal_protocol_internal.h index 3a30a0f0..81e33ee6 100644 --- a/src/signal_protocol_internal.h +++ b/src/signal_protocol_internal.h @@ -68,6 +68,8 @@ int signal_constant_memcmp(const void *s1, const void *s2, size_t n); */ int ec_public_key_serialize_protobuf(ProtobufCBinaryData *buffer, const ec_public_key *key); +int ec_public_key_serialize_protobuf_ed(ProtobufCBinaryData *buffer, const ec_public_key *key); +int ec_public_key_serialize_protobuf_mont(ProtobufCBinaryData *buffer, const ec_public_key *key); int ec_private_key_serialize_protobuf(ProtobufCBinaryData *buffer, const ec_private_key *key); int ratchet_chain_key_get_key_protobuf(const ratchet_chain_key *chain_key, ProtobufCBinaryData *buffer); diff --git a/src/signal_protocol_types.h b/src/signal_protocol_types.h index b45fa4c7..2759e03d 100644 --- a/src/signal_protocol_types.h +++ b/src/signal_protocol_types.h @@ -118,22 +118,6 @@ typedef struct sender_key_record sender_key_record; typedef struct group_session_builder group_session_builder; typedef struct group_cipher group_cipher; -/* - * Fingerprint types - */ -typedef struct fingerprint fingerprint; -typedef struct displayable_fingerprint displayable_fingerprint; -typedef struct scannable_fingerprint scannable_fingerprint; -typedef struct fingerprint_generator fingerprint_generator; - -/* - * Device consistency types - */ -typedef struct device_consistency_signature device_consistency_signature; -typedef struct device_consistency_commitment device_consistency_commitment; -typedef struct device_consistency_message device_consistency_message; -typedef struct device_consistency_signature_list device_consistency_signature_list; - #ifdef __cplusplus } #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e72643dd..69bd20f3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -95,16 +95,4 @@ add_test(test_simultaneous_initiate ${TEST_PATH}/test_simultaneous_initiate) add_executable(test_sender_key_record test_sender_key_record.c ${common_SRCS}) target_link_libraries(test_sender_key_record ${LIBS}) -add_test(test_sender_key_record ${TEST_PATH}/test_sender_key_record) - -add_executable(test_group_cipher test_group_cipher.c ${common_SRCS}) -target_link_libraries(test_group_cipher ${LIBS}) -add_test(test_group_cipher ${TEST_PATH}/test_group_cipher) - -add_executable(test_fingerprint test_fingerprint.c ${common_SRCS}) -target_link_libraries(test_fingerprint ${LIBS}) -add_test(test_fingerprint ${TEST_PATH}/test_fingerprint) - -add_executable(test_device_consistency test_device_consistency.c ${common_SRCS}) -target_link_libraries(test_device_consistency ${LIBS}) -add_test(test_device_consistency ${TEST_PATH}/test_device_consistency) +add_test(test_sender_key_record ${TEST_PATH}/test_sender_key_record) \ No newline at end of file diff --git a/tests/test_device_consistency.c b/tests/test_device_consistency.c deleted file mode 100644 index 19b5c539..00000000 --- a/tests/test_device_consistency.c +++ /dev/null @@ -1,251 +0,0 @@ -#include - -#include "../src/signal_protocol.h" -#include "device_consistency.h" -#include "curve.h" -#include "test_common.h" - -signal_context *global_context; - -static char *generate_code(device_consistency_commitment *commitment, - device_consistency_message *msg1, - device_consistency_message *msg2, - device_consistency_message *msg3); - -void test_setup() -{ - int result; - result = signal_context_create(&global_context, 0); - ck_assert_int_eq(result, 0); - signal_context_set_log_function(global_context, test_log); - setup_test_crypto_provider(global_context); -} - -void test_teardown() -{ - signal_context_destroy(global_context); -} - -START_TEST(test_device_consistency) -{ - int result = 0; - int i; - - /* Create three device key pairs */ - ec_key_pair *device_one = 0; - result = curve_generate_key_pair(global_context, &device_one); - ck_assert_int_eq(result, 0); - - ec_key_pair *device_two = 0; - result = curve_generate_key_pair(global_context, &device_two); - ck_assert_int_eq(result, 0); - - ec_key_pair *device_three = 0; - result = curve_generate_key_pair(global_context, &device_three); - ck_assert_int_eq(result, 0); - - ec_public_key *key_array[] = { - ec_key_pair_get_public(device_one), - ec_key_pair_get_public(device_two), - ec_key_pair_get_public(device_three) - }; - - /* Create device one commitment */ - ec_public_key_list *key_list = ec_public_key_list_alloc(); - ck_assert_ptr_ne(key_list, 0); - shuffle_ec_public_keys(key_array, 3); - for(i = 0; i < 3; i++) { - ec_public_key_list_push_back(key_list, key_array[i]); - } - - device_consistency_commitment *device_one_commitment = 0; - result = device_consistency_commitment_create(&device_one_commitment, 1, key_list, global_context); - ck_assert_int_eq(result, 0); - ec_public_key_list_free(key_list); - - /* Create device two commitment */ - key_list = ec_public_key_list_alloc(); - ck_assert_ptr_ne(key_list, 0); - shuffle_ec_public_keys(key_array, 3); - for(i = 0; i < 3; i++) { - ec_public_key_list_push_back(key_list, key_array[i]); - } - - device_consistency_commitment *device_two_commitment = 0; - result = device_consistency_commitment_create(&device_two_commitment, 1, key_list, global_context); - ck_assert_int_eq(result, 0); - ec_public_key_list_free(key_list); - - /* Create device three commitment */ - key_list = ec_public_key_list_alloc(); - ck_assert_ptr_ne(key_list, 0); - shuffle_ec_public_keys(key_array, 3); - for(i = 0; i < 3; i++) { - ec_public_key_list_push_back(key_list, key_array[i]); - } - - device_consistency_commitment *device_three_commitment = 0; - result = device_consistency_commitment_create(&device_three_commitment, 1, key_list, global_context); - ck_assert_int_eq(result, 0); - ec_public_key_list_free(key_list); - - /* Check that all three commitments are equal */ - ck_assert_int_eq(signal_buffer_compare( - device_consistency_commitment_get_serialized(device_one_commitment), - device_consistency_commitment_get_serialized(device_two_commitment)), 0); - ck_assert_int_eq(signal_buffer_compare( - device_consistency_commitment_get_serialized(device_two_commitment), - device_consistency_commitment_get_serialized(device_three_commitment)), 0); - - /* Create device consistency messages */ - device_consistency_message *device_one_message = 0; - result = device_consistency_message_create_from_pair(&device_one_message, - device_one_commitment, device_one, global_context); - ck_assert_int_eq(result, 0); - - device_consistency_message *device_two_message = 0; - result = device_consistency_message_create_from_pair(&device_two_message, - device_one_commitment, device_two, global_context); - ck_assert_int_eq(result, 0); - - device_consistency_message *device_three_message = 0; - result = device_consistency_message_create_from_pair(&device_three_message, - device_one_commitment, device_three, global_context); - ck_assert_int_eq(result, 0); - - /* Create received device consistency messages */ - signal_buffer *device_one_message_serialized = - device_consistency_message_get_serialized(device_one_message); - device_consistency_message *received_device_one_message = 0; - result = device_consistency_message_create_from_serialized(&received_device_one_message, - device_one_commitment, - signal_buffer_data(device_one_message_serialized), - signal_buffer_len(device_one_message_serialized), - ec_key_pair_get_public(device_one), global_context); - ck_assert_int_eq(result, 0); - - signal_buffer *device_two_message_serialized = - device_consistency_message_get_serialized(device_two_message); - device_consistency_message *received_device_two_message = 0; - result = device_consistency_message_create_from_serialized(&received_device_two_message, - device_one_commitment, - signal_buffer_data(device_two_message_serialized), - signal_buffer_len(device_two_message_serialized), - ec_key_pair_get_public(device_two), global_context); - ck_assert_int_eq(result, 0); - - signal_buffer *device_three_message_serialized = - device_consistency_message_get_serialized(device_three_message); - device_consistency_message *received_device_three_message = 0; - result = device_consistency_message_create_from_serialized(&received_device_three_message, - device_one_commitment, - signal_buffer_data(device_three_message_serialized), - signal_buffer_len(device_three_message_serialized), - ec_key_pair_get_public(device_three), global_context); - ck_assert_int_eq(result, 0); - - /* Check that all sent-and-received pairs have the same VRF output */ - ck_assert_int_eq(signal_buffer_compare( - device_consistency_signature_get_vrf_output( - device_consistency_message_get_signature(device_one_message)), - device_consistency_signature_get_vrf_output( - device_consistency_message_get_signature(received_device_one_message))), - 0); - ck_assert_int_eq(signal_buffer_compare( - device_consistency_signature_get_vrf_output( - device_consistency_message_get_signature(device_two_message)), - device_consistency_signature_get_vrf_output( - device_consistency_message_get_signature(received_device_two_message))), - 0); - ck_assert_int_eq(signal_buffer_compare( - device_consistency_signature_get_vrf_output( - device_consistency_message_get_signature(device_three_message)), - device_consistency_signature_get_vrf_output( - device_consistency_message_get_signature(received_device_three_message))), - 0); - - /* Generate consistency codes */ - char *code_one = generate_code(device_one_commitment, - device_one_message, received_device_two_message, received_device_three_message); - char *code_two = generate_code(device_two_commitment, - device_two_message, received_device_three_message, received_device_one_message); - char *code_three = generate_code(device_three_commitment, - device_three_message, received_device_two_message, received_device_one_message); - - /* Check that all the consistency codes match */ - ck_assert_str_eq(code_one, code_two); - ck_assert_str_eq(code_two, code_three); - - /* Cleanup */ - SIGNAL_UNREF(device_one); - SIGNAL_UNREF(device_two); - SIGNAL_UNREF(device_three); - SIGNAL_UNREF(device_one_commitment); - SIGNAL_UNREF(device_two_commitment); - SIGNAL_UNREF(device_three_commitment); - SIGNAL_UNREF(device_one_message); - SIGNAL_UNREF(device_two_message); - SIGNAL_UNREF(device_three_message); - SIGNAL_UNREF(received_device_one_message); - SIGNAL_UNREF(received_device_two_message); - SIGNAL_UNREF(received_device_three_message); - free(code_one); - free(code_two); - free(code_three); -} -END_TEST - -char *generate_code(device_consistency_commitment *commitment, - device_consistency_message *msg1, - device_consistency_message *msg2, - device_consistency_message *msg3) -{ - int result = 0; - char *code_string = 0; - - /* Build the list of signatures */ - device_consistency_signature_list *signatures = device_consistency_signature_list_alloc(); - ck_assert_ptr_ne(signatures, 0); - - device_consistency_signature_list_push_back(signatures, - device_consistency_message_get_signature(msg1)); - device_consistency_signature_list_push_back(signatures, - device_consistency_message_get_signature(msg2)); - device_consistency_signature_list_push_back(signatures, - device_consistency_message_get_signature(msg3)); - - result = device_consistency_code_generate_for(commitment, signatures, &code_string, global_context); - ck_assert_int_eq(result, 0); - ck_assert_ptr_ne(code_string, 0); - - device_consistency_signature_list_free(signatures); - - return code_string; -} - -Suite *device_consistency_suite(void) -{ - Suite *suite = suite_create("device_consistency"); - - TCase *tcase = tcase_create("case"); - tcase_add_checked_fixture(tcase, test_setup, test_teardown); - tcase_add_test(tcase, test_device_consistency); - suite_add_tcase(suite, tcase); - - return suite; -} - -int main(void) -{ - int number_failed; - Suite *suite; - SRunner *runner; - - suite = device_consistency_suite(); - runner = srunner_create(suite); - - srunner_run_all(runner, CK_VERBOSE); - number_failed = srunner_ntests_failed(runner); - srunner_free(runner); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/tests/test_fingerprint.c b/tests/test_fingerprint.c deleted file mode 100644 index d92bc173..00000000 --- a/tests/test_fingerprint.c +++ /dev/null @@ -1,586 +0,0 @@ -#include - -#include "../src/signal_protocol.h" -#include "curve.h" -#include "fingerprint.h" -#include "test_common.h" - -signal_context *global_context; - -static uint8_t ALICE_IDENTITY[] = { - 0x05, 0x06, 0x86, 0x3b, 0xc6, 0x6d, 0x02, 0xb4, - 0x0d, 0x27, 0xb8, 0xd4, 0x9c, 0xa7, 0xc0, 0x9e, - 0x92, 0x39, 0x23, 0x6f, 0x9d, 0x7d, 0x25, 0xd6, - 0xfc, 0xca, 0x5c, 0xe1, 0x3c, 0x70, 0x64, 0xd8, - 0x68}; - -static uint8_t BOB_IDENTITY[] = { - 0x05, 0xf7, 0x81, 0xb6, 0xfb, 0x32, 0xfe, 0xd9, - 0xba, 0x1c, 0xf2, 0xde, 0x97, 0x8d, 0x4d, 0x5d, - 0xa2, 0x8d, 0xc3, 0x40, 0x46, 0xae, 0x81, 0x44, - 0x02, 0xb5, 0xc0, 0xdb, 0xd9, 0x6f, 0xda, 0x90, - 0x7b}; - -static const char *DISPLAYABLE_FINGERPRINT = - "300354477692869396892869876765458257569162576843440918079131"; - -static uint8_t ALICE_SCANNABLE_FINGERPRINT_V0[] = { - 0x08, 0x00, 0x12, 0x31, 0x0a, 0x21, 0x05, 0x06, - 0x86, 0x3b, 0xc6, 0x6d, 0x02, 0xb4, 0x0d, 0x27, - 0xb8, 0xd4, 0x9c, 0xa7, 0xc0, 0x9e, 0x92, 0x39, - 0x23, 0x6f, 0x9d, 0x7d, 0x25, 0xd6, 0xfc, 0xca, - 0x5c, 0xe1, 0x3c, 0x70, 0x64, 0xd8, 0x68, 0x12, - 0x0c, 0x2b, 0x31, 0x34, 0x31, 0x35, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x1a, 0x31, 0x0a, - 0x21, 0x05, 0xf7, 0x81, 0xb6, 0xfb, 0x32, 0xfe, - 0xd9, 0xba, 0x1c, 0xf2, 0xde, 0x97, 0x8d, 0x4d, - 0x5d, 0xa2, 0x8d, 0xc3, 0x40, 0x46, 0xae, 0x81, - 0x44, 0x02, 0xb5, 0xc0, 0xdb, 0xd9, 0x6f, 0xda, - 0x90, 0x7b, 0x12, 0x0c, 0x2b, 0x31, 0x34, 0x31, - 0x35, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33}; - -static uint8_t BOB_SCANNABLE_FINGERPRINT_V0[] = { - 0x08, 0x00, 0x12, 0x31, 0x0a, 0x21, 0x05, 0xf7, - 0x81, 0xb6, 0xfb, 0x32, 0xfe, 0xd9, 0xba, 0x1c, - 0xf2, 0xde, 0x97, 0x8d, 0x4d, 0x5d, 0xa2, 0x8d, - 0xc3, 0x40, 0x46, 0xae, 0x81, 0x44, 0x02, 0xb5, - 0xc0, 0xdb, 0xd9, 0x6f, 0xda, 0x90, 0x7b, 0x12, - 0x0c, 0x2b, 0x31, 0x34, 0x31, 0x35, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x1a, 0x31, 0x0a, - 0x21, 0x05, 0x06, 0x86, 0x3b, 0xc6, 0x6d, 0x02, - 0xb4, 0x0d, 0x27, 0xb8, 0xd4, 0x9c, 0xa7, 0xc0, - 0x9e, 0x92, 0x39, 0x23, 0x6f, 0x9d, 0x7d, 0x25, - 0xd6, 0xfc, 0xca, 0x5c, 0xe1, 0x3c, 0x70, 0x64, - 0xd8, 0x68, 0x12, 0x0c, 0x2b, 0x31, 0x34, 0x31, - 0x35, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}; - -static uint8_t ALICE_SCANNABLE_FINGERPRINT_V1[] = { - 0x08, 0x01, 0x12, 0x22, 0x0a, 0x20, 0x1e, 0x30, - 0x1a, 0x03, 0x53, 0xdc, 0xe3, 0xdb, 0xe7, 0x68, - 0x4c, 0xb8, 0x33, 0x6e, 0x85, 0x13, 0x6c, 0xdc, - 0x0e, 0xe9, 0x62, 0x19, 0x49, 0x4a, 0xda, 0x30, - 0x5d, 0x62, 0xa7, 0xbd, 0x61, 0xdf, 0x1a, 0x22, - 0x0a, 0x20, 0xd6, 0x2c, 0xbf, 0x73, 0xa1, 0x15, - 0x92, 0x01, 0x5b, 0x6b, 0x9f, 0x16, 0x82, 0xac, - 0x30, 0x6f, 0xea, 0x3a, 0xaf, 0x38, 0x85, 0xb8, - 0x4d, 0x12, 0xbc, 0xa6, 0x31, 0xe9, 0xd4, 0xfb, - 0x3a, 0x4d}; - -static uint8_t BOB_SCANNABLE_FINGERPRINT_V1[] = { - 0x08, 0x01, 0x12, 0x22, 0x0a, 0x20, 0xd6, 0x2c, - 0xbf, 0x73, 0xa1, 0x15, 0x92, 0x01, 0x5b, 0x6b, - 0x9f, 0x16, 0x82, 0xac, 0x30, 0x6f, 0xea, 0x3a, - 0xaf, 0x38, 0x85, 0xb8, 0x4d, 0x12, 0xbc, 0xa6, - 0x31, 0xe9, 0xd4, 0xfb, 0x3a, 0x4d, 0x1a, 0x22, - 0x0a, 0x20, 0x1e, 0x30, 0x1a, 0x03, 0x53, 0xdc, - 0xe3, 0xdb, 0xe7, 0x68, 0x4c, 0xb8, 0x33, 0x6e, - 0x85, 0x13, 0x6c, 0xdc, 0x0e, 0xe9, 0x62, 0x19, - 0x49, 0x4a, 0xda, 0x30, 0x5d, 0x62, 0xa7, 0xbd, - 0x61, 0xdf}; - -void test_setup() -{ - int result; - result = signal_context_create(&global_context, 0); - ck_assert_int_eq(result, 0); - signal_context_set_log_function(global_context, test_log); - setup_test_crypto_provider(global_context); -} - -void test_teardown() -{ - signal_context_destroy(global_context); -} - -static void test_scannable_fingerprint_serialize_impl(int version) -{ - int result = 0; - ec_public_key *alice_identity_key = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key = create_test_ec_public_key(global_context); - signal_buffer *alice_identity_buffer = 0; - signal_buffer *bob_identity_buffer = 0; - scannable_fingerprint *alice_scannable = 0; - scannable_fingerprint *bob_scannable = 0; - signal_buffer *buffer = 0; - scannable_fingerprint *bob_deserialized = 0; - - result = ec_public_key_serialize(&alice_identity_buffer, alice_identity_key); - ck_assert_int_eq(result, 0); - - result = ec_public_key_serialize(&bob_identity_buffer, bob_identity_key); - ck_assert_int_eq(result, 0); - - result = scannable_fingerprint_create(&alice_scannable, version, - "+14152222222", alice_identity_buffer, - "+14153333333", bob_identity_buffer); - ck_assert_int_eq(result, 0); - - result = scannable_fingerprint_create(&bob_scannable, version, - "+14153333333", bob_identity_buffer, - "+14152222222", alice_identity_buffer); - ck_assert_int_eq(result, 0); - - ck_assert_int_eq(scannable_fingerprint_compare(alice_scannable, bob_scannable), 1); - - result = scannable_fingerprint_serialize(&buffer, bob_scannable); - ck_assert_int_eq(result, 0); - - result = scannable_fingerprint_deserialize(&bob_deserialized, - signal_buffer_data(buffer), - signal_buffer_len(buffer), - global_context); - ck_assert_int_eq(result, 0); - - ck_assert_int_eq(scannable_fingerprint_compare(alice_scannable, bob_deserialized), 1); - - /* Cleanup */ - SIGNAL_UNREF(alice_identity_key); - SIGNAL_UNREF(bob_identity_key); - SIGNAL_UNREF(alice_scannable); - SIGNAL_UNREF(bob_scannable); - SIGNAL_UNREF(bob_deserialized); - signal_buffer_free(alice_identity_buffer); - signal_buffer_free(bob_identity_buffer); - signal_buffer_free(buffer); -} - -START_TEST(test_scannable_fingerprint_serialize_v0) -{ - test_scannable_fingerprint_serialize_impl(0); -} -END_TEST - -START_TEST(test_scannable_fingerprint_serialize_v1) -{ - test_scannable_fingerprint_serialize_impl(1); -} -END_TEST - -static void test_vectors_impl(int version) -{ - int result = 0; - ec_public_key *alice_identity_key = 0; - ec_public_key *bob_identity_key = 0; - fingerprint_generator *generator = 0; - fingerprint *alice_fingerprint = 0; - fingerprint *bob_fingerprint = 0; - signal_buffer *alice_buffer = 0; - signal_buffer *bob_buffer = 0; - - result = curve_decode_point(&alice_identity_key, ALICE_IDENTITY, sizeof(ALICE_IDENTITY), global_context); - ck_assert_int_eq(result, 0); - - result = curve_decode_point(&bob_identity_key, BOB_IDENTITY, sizeof(BOB_IDENTITY), global_context); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create(&generator, 5200, version, global_context); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator, - "+14152222222", alice_identity_key, - "+14153333333", bob_identity_key, - &alice_fingerprint); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator, - "+14153333333", bob_identity_key, - "+14152222222", alice_identity_key, - &bob_fingerprint); - ck_assert_int_eq(result, 0); - - displayable_fingerprint *alice_displayable = fingerprint_get_displayable(alice_fingerprint); - ck_assert_str_eq( - displayable_fingerprint_text(alice_displayable), - DISPLAYABLE_FINGERPRINT); - - displayable_fingerprint *bob_displayable = fingerprint_get_displayable(bob_fingerprint); - ck_assert_str_eq( - displayable_fingerprint_text(bob_displayable), - DISPLAYABLE_FINGERPRINT); - - scannable_fingerprint *alice_scannable = fingerprint_get_scannable(alice_fingerprint); - scannable_fingerprint_serialize(&alice_buffer, alice_scannable); - ck_assert_int_eq(result, 0); - - scannable_fingerprint *bob_scannable = fingerprint_get_scannable(bob_fingerprint); - scannable_fingerprint_serialize(&bob_buffer, bob_scannable); - ck_assert_int_eq(result, 0); - - if(version == 0) { - ck_assert_int_eq(signal_buffer_len(alice_buffer), sizeof(ALICE_SCANNABLE_FINGERPRINT_V0)); - ck_assert_int_eq(memcmp(signal_buffer_data(alice_buffer), - ALICE_SCANNABLE_FINGERPRINT_V0, sizeof(ALICE_SCANNABLE_FINGERPRINT_V0)), 0); - - ck_assert_int_eq(signal_buffer_len(bob_buffer), sizeof(BOB_SCANNABLE_FINGERPRINT_V0)); - ck_assert_int_eq(memcmp(signal_buffer_data(bob_buffer), - BOB_SCANNABLE_FINGERPRINT_V0, sizeof(BOB_SCANNABLE_FINGERPRINT_V0)), 0); - } - else if(version == 1) { - ck_assert_int_eq(signal_buffer_len(alice_buffer), sizeof(ALICE_SCANNABLE_FINGERPRINT_V1)); - ck_assert_int_eq(memcmp(signal_buffer_data(alice_buffer), - ALICE_SCANNABLE_FINGERPRINT_V1, sizeof(ALICE_SCANNABLE_FINGERPRINT_V1)), 0); - - ck_assert_int_eq(signal_buffer_len(bob_buffer), sizeof(BOB_SCANNABLE_FINGERPRINT_V1)); - ck_assert_int_eq(memcmp(signal_buffer_data(bob_buffer), - BOB_SCANNABLE_FINGERPRINT_V1, sizeof(BOB_SCANNABLE_FINGERPRINT_V1)), 0); - } - - /* Cleanup */ - signal_buffer_free(alice_buffer); - signal_buffer_free(bob_buffer); - fingerprint_generator_free(generator); - SIGNAL_UNREF(alice_identity_key); - SIGNAL_UNREF(bob_identity_key); - SIGNAL_UNREF(alice_fingerprint); - SIGNAL_UNREF(bob_fingerprint); -} - -START_TEST(test_vectors_v0) -{ - test_vectors_impl(0); -} -END_TEST - -START_TEST(test_vectors_v1) -{ - test_vectors_impl(1); -} -END_TEST - -static void test_matching_fingerprints_impl(int version) -{ - int result = 0; - ec_public_key *alice_identity_key = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key = create_test_ec_public_key(global_context); - fingerprint_generator *generator = 0; - fingerprint *alice_fingerprint = 0; - fingerprint *bob_fingerprint = 0; - - result = fingerprint_generator_create(&generator, 1024, version, global_context); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator, - "+14152222222", alice_identity_key, - "+14153333333", bob_identity_key, - &alice_fingerprint); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator, - "+14153333333", bob_identity_key, - "+14152222222", alice_identity_key, - &bob_fingerprint); - ck_assert_int_eq(result, 0); - - displayable_fingerprint *alice_displayable = fingerprint_get_displayable(alice_fingerprint); - displayable_fingerprint *bob_displayable = fingerprint_get_displayable(bob_fingerprint); - - ck_assert_str_eq( - displayable_fingerprint_text(alice_displayable), - displayable_fingerprint_text(bob_displayable)); - - scannable_fingerprint *alice_scannable = fingerprint_get_scannable(alice_fingerprint); - scannable_fingerprint *bob_scannable = fingerprint_get_scannable(bob_fingerprint); - - ck_assert_int_eq(scannable_fingerprint_compare(alice_scannable, bob_scannable), 1); - ck_assert_int_eq(scannable_fingerprint_compare(bob_scannable, alice_scannable), 1); - - ck_assert_int_eq(strlen(displayable_fingerprint_text(alice_displayable)), 60); - - /* Cleanup */ - fingerprint_generator_free(generator); - SIGNAL_UNREF(alice_identity_key); - SIGNAL_UNREF(bob_identity_key); - SIGNAL_UNREF(alice_fingerprint); - SIGNAL_UNREF(bob_fingerprint); -} - -START_TEST(test_matching_fingerprints_v0) -{ - test_matching_fingerprints_impl(0); -} -END_TEST - -START_TEST(test_matching_fingerprints_v1) -{ - test_matching_fingerprints_impl(1); -} -END_TEST - -START_TEST(test_matching_list_fingerprints) -{ - int result = 0; - ec_public_key *alice_identity_key1 = create_test_ec_public_key(global_context); - ec_public_key *alice_identity_key2 = create_test_ec_public_key(global_context); - ec_public_key *alice_identity_key3 = create_test_ec_public_key(global_context); - ec_public_key *alice_identity_key4 = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key1 = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key2 = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key3 = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key4 = create_test_ec_public_key(global_context); - fingerprint_generator *generator = 0; - fingerprint *alice_fingerprint = 0; - fingerprint *bob_fingerprint = 0; - - ec_public_key_list *alice_key_list = ec_public_key_list_alloc(); - ck_assert_ptr_ne(alice_key_list, 0); - result = ec_public_key_list_push_back(alice_key_list, alice_identity_key1); - ck_assert_int_eq(result, 0); - result = ec_public_key_list_push_back(alice_key_list, alice_identity_key2); - ck_assert_int_eq(result, 0); - result = ec_public_key_list_push_back(alice_key_list, alice_identity_key3); - ck_assert_int_eq(result, 0); - result = ec_public_key_list_push_back(alice_key_list, alice_identity_key4); - ck_assert_int_eq(result, 0); - - ec_public_key_list *bob_key_list = ec_public_key_list_alloc(); - ck_assert_ptr_ne(bob_key_list, 0); - result = ec_public_key_list_push_back(bob_key_list, bob_identity_key1); - ck_assert_int_eq(result, 0); - result = ec_public_key_list_push_back(bob_key_list, bob_identity_key2); - ck_assert_int_eq(result, 0); - result = ec_public_key_list_push_back(bob_key_list, bob_identity_key3); - ck_assert_int_eq(result, 0); - result = ec_public_key_list_push_back(bob_key_list, bob_identity_key4); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create(&generator, 1024, 1, global_context); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for_list(generator, - "+14152222222", alice_key_list, - "+14153333333", bob_key_list, - &alice_fingerprint); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for_list(generator, - "+14153333333", bob_key_list, - "+14152222222", alice_key_list, - &bob_fingerprint); - ck_assert_int_eq(result, 0); - - displayable_fingerprint *alice_displayable = fingerprint_get_displayable(alice_fingerprint); - displayable_fingerprint *bob_displayable = fingerprint_get_displayable(bob_fingerprint); - - ck_assert_str_eq( - displayable_fingerprint_text(alice_displayable), - displayable_fingerprint_text(bob_displayable)); - - scannable_fingerprint *alice_scannable = fingerprint_get_scannable(alice_fingerprint); - scannable_fingerprint *bob_scannable = fingerprint_get_scannable(bob_fingerprint); - - ck_assert_int_eq(scannable_fingerprint_compare(alice_scannable, bob_scannable), 1); - ck_assert_int_eq(scannable_fingerprint_compare(bob_scannable, alice_scannable), 1); - - ck_assert_int_eq(strlen(displayable_fingerprint_text(alice_displayable)), 60); - - /* Cleanup */ - fingerprint_generator_free(generator); - SIGNAL_UNREF(alice_identity_key1); - SIGNAL_UNREF(alice_identity_key2); - SIGNAL_UNREF(alice_identity_key3); - SIGNAL_UNREF(alice_identity_key4); - SIGNAL_UNREF(bob_identity_key1); - SIGNAL_UNREF(bob_identity_key2); - SIGNAL_UNREF(bob_identity_key3); - SIGNAL_UNREF(bob_identity_key4); - ec_public_key_list_free(alice_key_list); - ec_public_key_list_free(bob_key_list); - SIGNAL_UNREF(alice_fingerprint); - SIGNAL_UNREF(bob_fingerprint); -} -END_TEST - -static void test_mismatching_fingerprints_impl(int version) -{ - int result = 0; - ec_public_key *alice_identity_key = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key = create_test_ec_public_key(global_context); - ec_public_key *mitm_identity_key = create_test_ec_public_key(global_context); - fingerprint_generator *generator = 0; - fingerprint *alice_fingerprint = 0; - fingerprint *bob_fingerprint = 0; - - result = fingerprint_generator_create(&generator, 1024, version, global_context); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator, - "+14152222222", alice_identity_key, - "+14153333333", mitm_identity_key, - &alice_fingerprint); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator, - "+14153333333", bob_identity_key, - "+14152222222", alice_identity_key, - &bob_fingerprint); - ck_assert_int_eq(result, 0); - - displayable_fingerprint *alice_displayable = fingerprint_get_displayable(alice_fingerprint); - displayable_fingerprint *bob_displayable = fingerprint_get_displayable(bob_fingerprint); - - ck_assert_str_ne( - displayable_fingerprint_text(alice_displayable), - displayable_fingerprint_text(bob_displayable)); - - scannable_fingerprint *alice_scannable = fingerprint_get_scannable(alice_fingerprint); - scannable_fingerprint *bob_scannable = fingerprint_get_scannable(bob_fingerprint); - - ck_assert_int_ne(scannable_fingerprint_compare(alice_scannable, bob_scannable), 1); - ck_assert_int_ne(scannable_fingerprint_compare(bob_scannable, alice_scannable), 1); - - /* Cleanup */ - fingerprint_generator_free(generator); - SIGNAL_UNREF(alice_identity_key); - SIGNAL_UNREF(bob_identity_key); - SIGNAL_UNREF(mitm_identity_key); - SIGNAL_UNREF(alice_fingerprint); - SIGNAL_UNREF(bob_fingerprint); -} - -START_TEST(test_mismatching_fingerprints_v0) -{ - test_mismatching_fingerprints_impl(0); -} -END_TEST - -START_TEST(test_mismatching_fingerprints_v1) -{ - test_mismatching_fingerprints_impl(1); -} -END_TEST - -START_TEST(test_mismatching_identifiers) -{ - int result = 0; - ec_public_key *alice_identity_key = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key = create_test_ec_public_key(global_context); - fingerprint_generator *generator = 0; - fingerprint *alice_fingerprint = 0; - fingerprint *bob_fingerprint = 0; - - result = fingerprint_generator_create(&generator, 1024, 0, global_context); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator, - "+14152222222", alice_identity_key, - "+1415333333", bob_identity_key, - &alice_fingerprint); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator, - "+14153333333", bob_identity_key, - "+14152222222", alice_identity_key, - &bob_fingerprint); - ck_assert_int_eq(result, 0); - - displayable_fingerprint *alice_displayable = fingerprint_get_displayable(alice_fingerprint); - displayable_fingerprint *bob_displayable = fingerprint_get_displayable(bob_fingerprint); - - ck_assert_str_ne( - displayable_fingerprint_text(alice_displayable), - displayable_fingerprint_text(bob_displayable)); - - scannable_fingerprint *alice_scannable = fingerprint_get_scannable(alice_fingerprint); - scannable_fingerprint *bob_scannable = fingerprint_get_scannable(bob_fingerprint); - - ck_assert_int_eq(scannable_fingerprint_compare(alice_scannable, bob_scannable), SG_ERR_FP_IDENT_MISMATCH); - ck_assert_int_eq(scannable_fingerprint_compare(bob_scannable, alice_scannable), SG_ERR_FP_IDENT_MISMATCH); - - /* Cleanup */ - fingerprint_generator_free(generator); - SIGNAL_UNREF(alice_identity_key); - SIGNAL_UNREF(bob_identity_key); - SIGNAL_UNREF(alice_fingerprint); - SIGNAL_UNREF(bob_fingerprint); -} -END_TEST - -START_TEST(test_mismatching_versions) -{ - int result = 0; - ec_public_key *alice_identity_key = create_test_ec_public_key(global_context); - ec_public_key *bob_identity_key = create_test_ec_public_key(global_context); - ec_public_key *mitm_identity_key = create_test_ec_public_key(global_context); - fingerprint_generator *generator_v0 = 0; - fingerprint_generator *generator_v1 = 0; - fingerprint *alice_fingerprint = 0; - fingerprint *bob_fingerprint = 0; - - result = fingerprint_generator_create(&generator_v0, 1024, 0, global_context); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator_v0, - "+14152222222", alice_identity_key, - "+14153333333", mitm_identity_key, - &alice_fingerprint); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create(&generator_v1, 1024, 1, global_context); - ck_assert_int_eq(result, 0); - - result = fingerprint_generator_create_for(generator_v1, - "+14153333333", bob_identity_key, - "+14152222222", alice_identity_key, - &bob_fingerprint); - ck_assert_int_eq(result, 0); - - displayable_fingerprint *alice_displayable = fingerprint_get_displayable(alice_fingerprint); - displayable_fingerprint *bob_displayable = fingerprint_get_displayable(bob_fingerprint); - - ck_assert_str_ne( - displayable_fingerprint_text(alice_displayable), - displayable_fingerprint_text(bob_displayable)); - - scannable_fingerprint *alice_scannable = fingerprint_get_scannable(alice_fingerprint); - scannable_fingerprint *bob_scannable = fingerprint_get_scannable(bob_fingerprint); - - ck_assert_int_eq(scannable_fingerprint_compare(alice_scannable, bob_scannable), SG_ERR_FP_VERSION_MISMATCH); - ck_assert_int_eq(scannable_fingerprint_compare(bob_scannable, alice_scannable), SG_ERR_FP_VERSION_MISMATCH); - - /* Cleanup */ - fingerprint_generator_free(generator_v0); - fingerprint_generator_free(generator_v1); - SIGNAL_UNREF(alice_identity_key); - SIGNAL_UNREF(bob_identity_key); - SIGNAL_UNREF(mitm_identity_key); - SIGNAL_UNREF(alice_fingerprint); - SIGNAL_UNREF(bob_fingerprint); -} -END_TEST - -Suite *fingerprint_suite(void) -{ - Suite *suite = suite_create("fingerprint"); - - TCase *tcase = tcase_create("case"); - tcase_add_checked_fixture(tcase, test_setup, test_teardown); - tcase_add_test(tcase, test_scannable_fingerprint_serialize_v0); - tcase_add_test(tcase, test_scannable_fingerprint_serialize_v1); - tcase_add_test(tcase, test_vectors_v0); - tcase_add_test(tcase, test_vectors_v1); - tcase_add_test(tcase, test_matching_fingerprints_v0); - tcase_add_test(tcase, test_matching_fingerprints_v1); - tcase_add_test(tcase, test_matching_list_fingerprints); - tcase_add_test(tcase, test_mismatching_fingerprints_v0); - tcase_add_test(tcase, test_mismatching_fingerprints_v1); - tcase_add_test(tcase, test_mismatching_identifiers); - tcase_add_test(tcase, test_mismatching_versions); - suite_add_tcase(suite, tcase); - - return suite; -} - -int main(void) -{ - int number_failed; - Suite *suite; - SRunner *runner; - - suite = fingerprint_suite(); - runner = srunner_create(suite); - - srunner_run_all(runner, CK_VERBOSE); - number_failed = srunner_ntests_failed(runner); - srunner_free(runner); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/tests/test_group_cipher.c b/tests/test_group_cipher.c deleted file mode 100644 index 9c75fa88..00000000 --- a/tests/test_group_cipher.c +++ /dev/null @@ -1,829 +0,0 @@ -#include -#include -#include -#include - -#include "../src/signal_protocol.h" -#include "protocol.h" -#include "group_cipher.h" -#include "group_session_builder.h" -#include "test_common.h" -#include "test_utarray.h" - -signal_context *global_context; -pthread_mutex_t global_mutex; -pthread_mutexattr_t global_mutex_attr; - -static signal_protocol_sender_key_name GROUP_SENDER = { - "nihilist history reading group", 30, - {"+14150001111", 12, 1} -}; - -void test_lock(void *user_data) -{ - pthread_mutex_lock(&global_mutex); -} - -void test_unlock(void *user_data) -{ - pthread_mutex_unlock(&global_mutex); -} - -void test_setup() -{ - int result; - - pthread_mutexattr_init(&global_mutex_attr); - pthread_mutexattr_settype(&global_mutex_attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&global_mutex, &global_mutex_attr); - - result = signal_context_create(&global_context, 0); - ck_assert_int_eq(result, 0); - signal_context_set_log_function(global_context, test_log); - - setup_test_crypto_provider(global_context); - - result = signal_context_set_locking_functions(global_context, test_lock, test_unlock); - ck_assert_int_eq(result, 0); -} - -void test_teardown() -{ - signal_context_destroy(global_context); -} - -START_TEST(test_no_session) -{ - int result = 0; - - /* Create the test data stores */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - signal_protocol_store_context *bob_store = 0; - setup_test_store_context(&bob_store, global_context); - - /* Create the session builder */ - group_session_builder *alice_session_builder = 0; - result = group_session_builder_create(&alice_session_builder, alice_store, global_context); - ck_assert_int_eq(result, 0); - - /* Create the group ciphers */ - group_cipher *alice_group_cipher = 0; - result = group_cipher_create(&alice_group_cipher, alice_store, &GROUP_SENDER, global_context); - - group_cipher *bob_group_cipher = 0; - result = group_cipher_create(&bob_group_cipher, bob_store, &GROUP_SENDER, global_context); - - /* Create the sender key distribution messages */ - sender_key_distribution_message *sent_alice_distribution_message = 0; - result = group_session_builder_create_session(alice_session_builder, &sent_alice_distribution_message, &GROUP_SENDER); - ck_assert_int_eq(result, 0); - - sender_key_distribution_message *received_alice_distribution_message = 0; - signal_buffer *serialized_distribution_message = - ciphertext_message_get_serialized((ciphertext_message *)sent_alice_distribution_message); - result = sender_key_distribution_message_deserialize(&received_alice_distribution_message, - signal_buffer_data(serialized_distribution_message), - signal_buffer_len(serialized_distribution_message), - global_context); - ck_assert_int_eq(result, 0); - - /* Intentionally omitting Bob's processing of received_alice_distribution_message */ - - /* Encrypt a test message from Alice */ - static const char alice_plaintext[] = "smert ze smert"; - size_t alice_plaintext_len = sizeof(alice_plaintext) - 1; - ciphertext_message *ciphertext_from_alice = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)alice_plaintext, alice_plaintext_len, - &ciphertext_from_alice); - ck_assert_int_eq(result, 0); - - /* Attempt to have Bob decrypt the message */ - signal_buffer *plaintext_from_alice = 0; - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)ciphertext_from_alice, 0, &plaintext_from_alice); - ck_assert_int_eq(result, SG_ERR_NO_SESSION);; - - /* Cleanup */ - signal_buffer_free(plaintext_from_alice); - SIGNAL_UNREF(ciphertext_from_alice); - SIGNAL_UNREF(received_alice_distribution_message); - SIGNAL_UNREF(sent_alice_distribution_message); - group_cipher_free(bob_group_cipher); - group_cipher_free(alice_group_cipher); - group_session_builder_free(alice_session_builder); - signal_protocol_store_context_destroy(bob_store); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -START_TEST(test_basic_encrypt_decrypt) -{ - int result = 0; - - /* Create the test data stores */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - signal_protocol_store_context *bob_store = 0; - setup_test_store_context(&bob_store, global_context); - - /* Create the session builders */ - group_session_builder *alice_session_builder = 0; - result = group_session_builder_create(&alice_session_builder, alice_store, global_context); - ck_assert_int_eq(result, 0); - - group_session_builder *bob_session_builder = 0; - result = group_session_builder_create(&bob_session_builder, bob_store, global_context); - ck_assert_int_eq(result, 0); - - /* Create the group ciphers */ - group_cipher *alice_group_cipher = 0; - result = group_cipher_create(&alice_group_cipher, alice_store, &GROUP_SENDER, global_context); - - group_cipher *bob_group_cipher = 0; - result = group_cipher_create(&bob_group_cipher, bob_store, &GROUP_SENDER, global_context); - - /* Create the sender key distribution messages */ - sender_key_distribution_message *sent_alice_distribution_message = 0; - result = group_session_builder_create_session(alice_session_builder, &sent_alice_distribution_message, &GROUP_SENDER); - ck_assert_int_eq(result, 0); - - sender_key_distribution_message *received_alice_distribution_message = 0; - signal_buffer *serialized_distribution_message = - ciphertext_message_get_serialized((ciphertext_message *)sent_alice_distribution_message); - result = sender_key_distribution_message_deserialize(&received_alice_distribution_message, - signal_buffer_data(serialized_distribution_message), - signal_buffer_len(serialized_distribution_message), - global_context); - ck_assert_int_eq(result, 0); - - /* Processing Alice's distribution message */ - result = group_session_builder_process_session(bob_session_builder, &GROUP_SENDER, received_alice_distribution_message); - ck_assert_int_eq(result, 0); - - /* Encrypt a test message from Alice */ - static const char alice_plaintext[] = "smert ze smert"; - size_t alice_plaintext_len = sizeof(alice_plaintext) - 1; - ciphertext_message *ciphertext_from_alice = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)alice_plaintext, alice_plaintext_len, - &ciphertext_from_alice); - ck_assert_int_eq(result, 0); - - /* Have Bob decrypt the message */ - signal_buffer *plaintext_from_alice = 0; - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)ciphertext_from_alice, 0, &plaintext_from_alice); - ck_assert_int_eq(result, 0); - - uint8_t *plaintext_data = signal_buffer_data(plaintext_from_alice); - size_t plaintext_len = signal_buffer_len(plaintext_from_alice); - - ck_assert_int_eq(alice_plaintext_len, plaintext_len); - ck_assert_int_eq(memcmp(alice_plaintext, plaintext_data, plaintext_len), 0); - - /* Cleanup */ - signal_buffer_free(plaintext_from_alice); - SIGNAL_UNREF(ciphertext_from_alice); - SIGNAL_UNREF(received_alice_distribution_message); - SIGNAL_UNREF(sent_alice_distribution_message); - group_cipher_free(bob_group_cipher); - group_cipher_free(alice_group_cipher); - group_session_builder_free(bob_session_builder); - group_session_builder_free(alice_session_builder); - signal_protocol_store_context_destroy(bob_store); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -START_TEST(test_basic_ratchet) -{ - int result = 0; - - /* Create the test data stores */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - signal_protocol_store_context *bob_store = 0; - setup_test_store_context(&bob_store, global_context); - - /* Create the session builders */ - group_session_builder *alice_session_builder = 0; - result = group_session_builder_create(&alice_session_builder, alice_store, global_context); - ck_assert_int_eq(result, 0); - - group_session_builder *bob_session_builder = 0; - result = group_session_builder_create(&bob_session_builder, bob_store, global_context); - ck_assert_int_eq(result, 0); - - signal_protocol_sender_key_name *alice_name = &GROUP_SENDER; - - /* Create the group ciphers */ - group_cipher *alice_group_cipher = 0; - result = group_cipher_create(&alice_group_cipher, alice_store, alice_name, global_context); - - group_cipher *bob_group_cipher = 0; - result = group_cipher_create(&bob_group_cipher, bob_store, alice_name, global_context); - - /* Create the sender key distribution messages */ - sender_key_distribution_message *sent_alice_distribution_message = 0; - result = group_session_builder_create_session(alice_session_builder, &sent_alice_distribution_message, alice_name); - ck_assert_int_eq(result, 0); - - sender_key_distribution_message *received_alice_distribution_message = 0; - signal_buffer *serialized_distribution_message = - ciphertext_message_get_serialized((ciphertext_message *)sent_alice_distribution_message); - result = sender_key_distribution_message_deserialize(&received_alice_distribution_message, - signal_buffer_data(serialized_distribution_message), - signal_buffer_len(serialized_distribution_message), - global_context); - ck_assert_int_eq(result, 0); - - /* Processing Alice's distribution message */ - result = group_session_builder_process_session(bob_session_builder, alice_name, received_alice_distribution_message); - ck_assert_int_eq(result, 0); - - /* Prepare some text to encrypt */ - static const char alice_plaintext[] = "smert ze smert"; - size_t alice_plaintext_len = sizeof(alice_plaintext) - 1; - static const char alice_plaintext_2[] = "smert ze smert2"; - size_t alice_plaintext_2_len = sizeof(alice_plaintext_2) - 1; - static const char alice_plaintext_3[] = "smert ze smert3"; - size_t alice_plaintext_3_len = sizeof(alice_plaintext_3) - 1; - - /* Encrypt a series of messages from Alice */ - ciphertext_message *ciphertext_from_alice = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)alice_plaintext, alice_plaintext_len, - &ciphertext_from_alice); - ck_assert_int_eq(result, 0); - - ciphertext_message *ciphertext_from_alice_2 = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)alice_plaintext_2, alice_plaintext_2_len, - &ciphertext_from_alice_2); - ck_assert_int_eq(result, 0); - - ciphertext_message *ciphertext_from_alice_3 = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)alice_plaintext_3, alice_plaintext_3_len, - &ciphertext_from_alice_3); - ck_assert_int_eq(result, 0); - - /* Have Bob decrypt the message */ - signal_buffer *plaintext_from_alice = 0; - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)ciphertext_from_alice, 0, &plaintext_from_alice); - ck_assert_int_eq(result, 0); - - /* Have Bob attempt to decrypt the same message again */ - signal_buffer *plaintext_from_alice_repeat = 0; - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)ciphertext_from_alice, 0, &plaintext_from_alice_repeat); - ck_assert_int_eq(result, SG_ERR_DUPLICATE_MESSAGE); /* Should have ratcheted forward */ - ck_assert_ptr_eq(plaintext_from_alice_repeat, 0); - - /* Have Bob decrypt the remaining messages */ - signal_buffer *plaintext_from_alice_2 = 0; - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)ciphertext_from_alice_2, 0, &plaintext_from_alice_2); - ck_assert_int_eq(result, 0); - - signal_buffer *plaintext_from_alice_3 = 0; - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)ciphertext_from_alice_3, 0, &plaintext_from_alice_3); - ck_assert_int_eq(result, 0); - - /* Verify that the plaintext matches */ - uint8_t *plaintext_data = signal_buffer_data(plaintext_from_alice); - size_t plaintext_len = signal_buffer_len(plaintext_from_alice); - ck_assert_int_eq(alice_plaintext_len, plaintext_len); - ck_assert_int_eq(memcmp(alice_plaintext, plaintext_data, plaintext_len), 0); - - plaintext_data = signal_buffer_data(plaintext_from_alice_2); - plaintext_len = signal_buffer_len(plaintext_from_alice_2); - ck_assert_int_eq(alice_plaintext_2_len, plaintext_len); - ck_assert_int_eq(memcmp(alice_plaintext_2, plaintext_data, plaintext_len), 0); - - plaintext_data = signal_buffer_data(plaintext_from_alice_3); - plaintext_len = signal_buffer_len(plaintext_from_alice_3); - ck_assert_int_eq(alice_plaintext_3_len, plaintext_len); - ck_assert_int_eq(memcmp(alice_plaintext_3, plaintext_data, plaintext_len), 0); - - /* Cleanup */ - signal_buffer_free(plaintext_from_alice_3); - signal_buffer_free(plaintext_from_alice_2); - signal_buffer_free(plaintext_from_alice); - SIGNAL_UNREF(ciphertext_from_alice_3); - SIGNAL_UNREF(ciphertext_from_alice_2); - SIGNAL_UNREF(ciphertext_from_alice); - SIGNAL_UNREF(received_alice_distribution_message); - SIGNAL_UNREF(sent_alice_distribution_message); - group_cipher_free(bob_group_cipher); - group_cipher_free(alice_group_cipher); - group_session_builder_free(bob_session_builder); - group_session_builder_free(alice_session_builder); - signal_protocol_store_context_destroy(bob_store); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -START_TEST(test_late_join) -{ - int result = 0; - - /* Create the test data stores */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - signal_protocol_store_context *bob_store = 0; - setup_test_store_context(&bob_store, global_context); - - /* Create Alice's session builder */ - group_session_builder *alice_session_builder = 0; - result = group_session_builder_create(&alice_session_builder, alice_store, global_context); - ck_assert_int_eq(result, 0); - - signal_protocol_sender_key_name *alice_name = &GROUP_SENDER; - - /* Create Alice's group cipher */ - group_cipher *alice_group_cipher = 0; - result = group_cipher_create(&alice_group_cipher, alice_store, alice_name, global_context); - - /* Create Alice's sender key distribution message */ - sender_key_distribution_message *alice_distribution_message = 0; - result = group_session_builder_create_session(alice_session_builder, &alice_distribution_message, alice_name); - ck_assert_int_eq(result, 0); - /* Pretend this was sent to some people other than Bob */ - - /* Encrypt a batch of messages that Bob never receives */ - int i = 0; - for(i = 0; i < 100; i++) { - static const char alice_plaintext[] = "up the punks up the punks up the punks"; - size_t alice_plaintext_len = sizeof(alice_plaintext) - 1; - - ciphertext_message *ciphertext_from_alice = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)alice_plaintext, alice_plaintext_len, - &ciphertext_from_alice); - ck_assert_int_eq(result, 0); - SIGNAL_UNREF(ciphertext_from_alice); - } - - /* Now Bob Joins */ - group_session_builder *bob_session_builder = 0; - result = group_session_builder_create(&bob_session_builder, bob_store, global_context); - ck_assert_int_eq(result, 0); - - group_cipher *bob_group_cipher = 0; - result = group_cipher_create(&bob_group_cipher, bob_store, alice_name, global_context); - - /* Create Alice's sender key distribution message for Bob */ - sender_key_distribution_message *distribution_message_to_bob = 0; - result = group_session_builder_create_session(alice_session_builder, &distribution_message_to_bob, alice_name); - ck_assert_int_eq(result, 0); - - sender_key_distribution_message *received_distribution_message_to_bob = 0; - signal_buffer *serialized_distribution_message = - ciphertext_message_get_serialized((ciphertext_message *)distribution_message_to_bob); - result = sender_key_distribution_message_deserialize(&received_distribution_message_to_bob, - signal_buffer_data(serialized_distribution_message), - signal_buffer_len(serialized_distribution_message), - global_context); - ck_assert_int_eq(result, 0); - - /* Have Bob process Alice's distribution message */ - result = group_session_builder_process_session(bob_session_builder, alice_name, received_distribution_message_to_bob); - ck_assert_int_eq(result, 0); - - /* Alice sends a message welcoming Bob */ - static const char welcome_plaintext[] = "welcome to the group"; - size_t welcome_plaintext_len = sizeof(welcome_plaintext) - 1; - - ciphertext_message *ciphertext = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)welcome_plaintext, welcome_plaintext_len, - &ciphertext); - ck_assert_int_eq(result, 0); - - /* Bob decrypts the message */ - signal_buffer *plaintext_from_alice = 0; - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message*)ciphertext, 0, &plaintext_from_alice); - ck_assert_int_eq(result, 0); - - /* Verify that the plaintext matches */ - uint8_t *plaintext_data = signal_buffer_data(plaintext_from_alice); - size_t plaintext_len = signal_buffer_len(plaintext_from_alice); - ck_assert_int_eq(welcome_plaintext_len, plaintext_len); - ck_assert_int_eq(memcmp(welcome_plaintext, plaintext_data, plaintext_len), 0); - - /* Cleanup */ - signal_buffer_free(plaintext_from_alice); - SIGNAL_UNREF(ciphertext); - SIGNAL_UNREF(received_distribution_message_to_bob); - SIGNAL_UNREF(distribution_message_to_bob); - group_cipher_free(bob_group_cipher); - group_session_builder_free(bob_session_builder); - SIGNAL_UNREF(alice_distribution_message); - group_cipher_free(alice_group_cipher); - group_session_builder_free(alice_session_builder); - signal_protocol_store_context_destroy(bob_store); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -START_TEST(test_out_of_order) -{ - int result = 0; - - /* Create the test data stores */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - signal_protocol_store_context *bob_store = 0; - setup_test_store_context(&bob_store, global_context); - - /* Create the session builders */ - group_session_builder *alice_session_builder = 0; - result = group_session_builder_create(&alice_session_builder, alice_store, global_context); - ck_assert_int_eq(result, 0); - - group_session_builder *bob_session_builder = 0; - result = group_session_builder_create(&bob_session_builder, bob_store, global_context); - ck_assert_int_eq(result, 0); - - signal_protocol_sender_key_name *alice_name = &GROUP_SENDER; - - /* Create the group ciphers */ - group_cipher *alice_group_cipher = 0; - result = group_cipher_create(&alice_group_cipher, alice_store, alice_name, global_context); - - group_cipher *bob_group_cipher = 0; - result = group_cipher_create(&bob_group_cipher, bob_store, alice_name, global_context); - - /* Create Alice's sender key distribution message */ - sender_key_distribution_message *alice_distribution_message = 0; - result = group_session_builder_create_session( - alice_session_builder, &alice_distribution_message, alice_name); - ck_assert_int_eq(result, 0); - - /* Have Bob process the distribution message */ - result = group_session_builder_process_session(bob_session_builder, alice_name, alice_distribution_message); - ck_assert_int_eq(result, 0); - - /* Populate a batch of 100 messages */ - UT_array *ciphertexts; - utarray_new(ciphertexts, &ut_ptr_icd); - utarray_reserve(ciphertexts, 100); - - static const char plaintext[] = "up the punks"; - size_t plaintext_len = sizeof(plaintext) - 1; - int i = 0; - for(i = 0; i < 100; i++) { - ciphertext_message *ciphertext = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)plaintext, plaintext_len, - &ciphertext); - ck_assert_int_eq(result, 0); - - signal_buffer *serialized = ciphertext_message_get_serialized(ciphertext); - signal_buffer *serialized_copy = signal_buffer_copy(serialized); - utarray_push_back(ciphertexts, &serialized_copy); - SIGNAL_UNREF(ciphertext); - } - - /* Try decrypting those messages in random order */ - while(utarray_len(ciphertexts) > 0) { - /* Get the next element */ - int index = rand() % utarray_len(ciphertexts); - signal_buffer *element = *((signal_buffer **)utarray_eltptr(ciphertexts, index)); - utarray_erase(ciphertexts, index, 1); - - /* Deserialize the message */ - sender_key_message *ciphertext = 0; - result = sender_key_message_deserialize(&ciphertext, - signal_buffer_data(element), signal_buffer_len(element), - global_context); - ck_assert_int_eq(result, 0); - - /* Decrypt the message */ - signal_buffer *plaintext_buffer = 0; - result = group_cipher_decrypt(bob_group_cipher, ciphertext, 0, &plaintext_buffer); - ck_assert_int_eq(result, 0); - - /* Verify that the plaintext matches */ - uint8_t *decrypted_plaintext_data = signal_buffer_data(plaintext_buffer); - size_t decrypted_plaintext_len = signal_buffer_len(plaintext_buffer); - ck_assert_int_eq(plaintext_len, decrypted_plaintext_len); - ck_assert_int_eq(memcmp(plaintext, decrypted_plaintext_data, decrypted_plaintext_len), 0); - - signal_buffer_free(element); - signal_buffer_free(plaintext_buffer); - SIGNAL_UNREF(ciphertext); - } - - /* Cleanup */ - utarray_free(ciphertexts); - SIGNAL_UNREF(alice_distribution_message); - group_cipher_free(bob_group_cipher); - group_cipher_free(alice_group_cipher); - group_session_builder_free(bob_session_builder); - group_session_builder_free(alice_session_builder); - signal_protocol_store_context_destroy(bob_store); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -START_TEST(test_encrypt_no_session) -{ - int result = 0; - static const signal_protocol_sender_key_name alice_sender_name = { - "coolio groupio", 14, - {"+10002223333", 12, 1} - }; - - /* Create the test data store for Alice */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - /* Create Alice's group cipher */ - group_cipher *alice_group_cipher = 0; - result = group_cipher_create(&alice_group_cipher, alice_store, &alice_sender_name, global_context); - ck_assert_int_eq(result, 0); - - /* Try to encrypt without a session */ - static const char plaintext[] = "up the punks"; - size_t plaintext_len = sizeof(plaintext) - 1; - - ciphertext_message *ciphertext = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)plaintext, plaintext_len, - &ciphertext); - ck_assert_int_eq(result, SG_ERR_NO_SESSION); - ck_assert_ptr_eq(ciphertext, 0); - - /* Cleanup */ - group_cipher_free(alice_group_cipher); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -START_TEST(test_too_far_in_future) -{ - int result = 0; - - /* Create the test data stores */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - signal_protocol_store_context *bob_store = 0; - setup_test_store_context(&bob_store, global_context); - - /* Create the session builders */ - group_session_builder *alice_session_builder = 0; - result = group_session_builder_create(&alice_session_builder, alice_store, global_context); - ck_assert_int_eq(result, 0); - - group_session_builder *bob_session_builder = 0; - result = group_session_builder_create(&bob_session_builder, bob_store, global_context); - ck_assert_int_eq(result, 0); - - signal_protocol_sender_key_name *alice_name = &GROUP_SENDER; - - /* Create the group ciphers */ - group_cipher *alice_group_cipher = 0; - result = group_cipher_create(&alice_group_cipher, alice_store, alice_name, global_context); - - group_cipher *bob_group_cipher = 0; - result = group_cipher_create(&bob_group_cipher, bob_store, alice_name, global_context); - - /* Create Alice's sender key distribution message */ - sender_key_distribution_message *alice_distribution_message = 0; - result = group_session_builder_create_session( - alice_session_builder, &alice_distribution_message, alice_name); - ck_assert_int_eq(result, 0); - - /* Have Bob process the distribution message */ - result = group_session_builder_process_session(bob_session_builder, alice_name, alice_distribution_message); - ck_assert_int_eq(result, 0); - - /* Have Alice encrypt a batch of 2001 messages */ - static const char plaintext[] = "up the punks"; - size_t plaintext_len = sizeof(plaintext) - 1; - int i = 0; - for(i = 0; i < 2001; i++) { - ciphertext_message *ciphertext = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)plaintext, plaintext_len, - &ciphertext); - ck_assert_int_eq(result, 0); - SIGNAL_UNREF(ciphertext); - } - - /* Have Alice encrypt a message too far in the future */ - static const char too_far_plaintext[] = "notta gonna worka"; - size_t too_far_plaintext_len = sizeof(too_far_plaintext) - 1; - - ciphertext_message *too_far_ciphertext = 0; - result = group_cipher_encrypt(alice_group_cipher, - (const uint8_t *)too_far_plaintext, too_far_plaintext_len, - &too_far_ciphertext); - ck_assert_int_eq(result, 0); - - /* Have Bob try, and fail, to decrypt the message */ - signal_buffer *plaintext_from_alice = 0; - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message*)too_far_ciphertext, 0, &plaintext_from_alice); - ck_assert_int_eq(result, SG_ERR_INVALID_MESSAGE); - - /* Cleanup */ - SIGNAL_UNREF(too_far_ciphertext); - SIGNAL_UNREF(alice_distribution_message); - group_cipher_free(bob_group_cipher); - group_cipher_free(alice_group_cipher); - group_session_builder_free(bob_session_builder); - group_session_builder_free(alice_session_builder); - signal_protocol_store_context_destroy(bob_store); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -START_TEST(test_message_key_limit) -{ - int result = 0; - int i; - - /* Create the test data stores */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - signal_protocol_store_context *bob_store = 0; - setup_test_store_context(&bob_store, global_context); - - /* Create the session builders */ - group_session_builder *alice_session_builder = 0; - result = group_session_builder_create(&alice_session_builder, alice_store, global_context); - ck_assert_int_eq(result, 0); - - group_session_builder *bob_session_builder = 0; - result = group_session_builder_create(&bob_session_builder, bob_store, global_context); - ck_assert_int_eq(result, 0); - - signal_protocol_sender_key_name *alice_name = &GROUP_SENDER; - - /* Create the group ciphers */ - group_cipher *alice_group_cipher = 0; - result = group_cipher_create(&alice_group_cipher, alice_store, alice_name, global_context); - - group_cipher *bob_group_cipher = 0; - result = group_cipher_create(&bob_group_cipher, bob_store, alice_name, global_context); - - /* Create the sender key distribution messages */ - sender_key_distribution_message *alice_distribution_message = 0; - result = group_session_builder_create_session(alice_session_builder, &alice_distribution_message, alice_name); - ck_assert_int_eq(result, 0); - - /* Processing Alice's distribution message */ - result = group_session_builder_process_session(bob_session_builder, alice_name, alice_distribution_message); - ck_assert_int_eq(result, 0); - - ciphertext_message *inflight[2010]; - memset(inflight, 0, sizeof(inflight)); - - for(i = 0; i <2010; i++) { - static const char plaintext[] = "up the punks"; - size_t plaintext_len = sizeof(plaintext) - 1; - ciphertext_message *message = 0; - result = group_cipher_encrypt(alice_group_cipher, (uint8_t *)plaintext, plaintext_len, &message); - ck_assert_int_eq(result, 0); - inflight[i] = message; - } - - signal_buffer *buffer = 0; - - /* Try decrypting in-flight message 1000 */ - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)inflight[1000], 0, &buffer); - ck_assert_int_eq(result, 0); - ck_assert_ptr_ne(buffer, 0); - signal_buffer_free(buffer); buffer = 0; - - /* Try decrypting in-flight message 2009 */ - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)inflight[2009], 0, &buffer); - ck_assert_int_eq(result, 0); - ck_assert_ptr_ne(buffer, 0); - signal_buffer_free(buffer); buffer = 0; - - /* Try decrypting in-flight message 0, which should fail */ - result = group_cipher_decrypt(bob_group_cipher, (sender_key_message *)inflight[0], 0, &buffer); - ck_assert_int_eq(result, SG_ERR_DUPLICATE_MESSAGE); - signal_buffer_free(buffer); buffer = 0; - - /* Cleanup */ - for(i = 0; i < 2010; i++) { - if(inflight[i]) { - SIGNAL_UNREF(inflight[i]); - } - } - SIGNAL_UNREF(alice_distribution_message); - group_cipher_free(bob_group_cipher); - group_cipher_free(alice_group_cipher); - group_session_builder_free(bob_session_builder); - group_session_builder_free(alice_session_builder); - signal_protocol_store_context_destroy(bob_store); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -START_TEST(test_invalid_signature_key) -{ - int result = 0; - - /* Create the test data stores */ - signal_protocol_store_context *alice_store = 0; - setup_test_store_context(&alice_store, global_context); - - signal_protocol_store_context *bob_store = 0; - setup_test_store_context(&bob_store, global_context); - - /* Create the session builders */ - group_session_builder *alice_session_builder = 0; - result = group_session_builder_create(&alice_session_builder, alice_store, global_context); - ck_assert_int_eq(result, 0); - - group_session_builder *bob_session_builder = 0; - result = group_session_builder_create(&bob_session_builder, bob_store, global_context); - ck_assert_int_eq(result, 0); - - /* Create the group cipher for Bob */ - group_cipher *bob_group_cipher = 0; - result = group_cipher_create(&bob_group_cipher, bob_store, &GROUP_SENDER, global_context); - - /* Create a sender key distribution message from Alice to Bob */ - sender_key_distribution_message *sent_alice_distribution_message = 0; - result = group_session_builder_create_session(alice_session_builder, &sent_alice_distribution_message, &GROUP_SENDER); - ck_assert_int_eq(result, 0); - - sender_key_distribution_message *received_alice_distribution_message = 0; - signal_buffer *serialized_distribution_message = - ciphertext_message_get_serialized((ciphertext_message *)sent_alice_distribution_message); - result = sender_key_distribution_message_deserialize(&received_alice_distribution_message, - signal_buffer_data(serialized_distribution_message), - signal_buffer_len(serialized_distribution_message), - global_context); - ck_assert_int_eq(result, 0); - - /* Processing Alice's distribution message */ - result = group_session_builder_process_session(bob_session_builder, &GROUP_SENDER, received_alice_distribution_message); - ck_assert_int_eq(result, 0); - - /* Encrypt a test message from Bob */ - static const char bob_plaintext[] = "smert ze smert"; - size_t bob_plaintext_len = sizeof(bob_plaintext) - 1; - ciphertext_message *ciphertext_from_bob = 0; - result = group_cipher_encrypt(bob_group_cipher, - (const uint8_t *)bob_plaintext, bob_plaintext_len, - &ciphertext_from_bob); - ck_assert_int_eq(result, SG_ERR_INVALID_KEY); - - /* Cleanup */ - SIGNAL_UNREF(ciphertext_from_bob); - SIGNAL_UNREF(received_alice_distribution_message); - SIGNAL_UNREF(sent_alice_distribution_message); - group_cipher_free(bob_group_cipher); - group_session_builder_free(bob_session_builder); - group_session_builder_free(alice_session_builder); - signal_protocol_store_context_destroy(bob_store); - signal_protocol_store_context_destroy(alice_store); -} -END_TEST - -Suite *group_cipher_suite(void) -{ - Suite *suite = suite_create("group_cipher"); - - TCase *tcase = tcase_create("case"); - tcase_add_checked_fixture(tcase, test_setup, test_teardown); - tcase_add_test(tcase, test_no_session); - tcase_add_test(tcase, test_basic_encrypt_decrypt); - tcase_add_test(tcase, test_basic_ratchet); - tcase_add_test(tcase, test_late_join); - tcase_add_test(tcase, test_out_of_order); - tcase_add_test(tcase, test_encrypt_no_session); - tcase_add_test(tcase, test_too_far_in_future); - tcase_add_test(tcase, test_message_key_limit); - tcase_add_test(tcase, test_invalid_signature_key); - suite_add_tcase(suite, tcase); - - return suite; -} - -int main(void) -{ - int number_failed; - Suite *suite; - SRunner *runner; - - suite = group_cipher_suite(); - runner = srunner_create(suite); - - srunner_run_all(runner, CK_VERBOSE); - number_failed = srunner_ntests_failed(runner); - srunner_free(runner); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/tests/test_key_helper.c b/tests/test_key_helper.c index 02600251..2b0594b4 100644 --- a/tests/test_key_helper.c +++ b/tests/test_key_helper.c @@ -223,7 +223,15 @@ START_TEST(test_generate_signed_pre_key) 0x6c, 0x5e, 0x1f, 0xa6, 0xaa, 0x42, 0x53, 0x8d, 0xb9, 0xe2, 0x6b, 0xbb, 0xb0, 0xb3, 0x6c, 0x99, 0x74, 0x04, 0x29, 0xe8, 0x81, 0x3f, 0x8f, 0x48, - 0x01, 0x00, 0x00 + 0x01, 0x00, 0x00, 0x32, 0x40, 0xa9, 0x48, 0x21, + 0x7a, 0xf1, 0xa3, 0x60, 0xb9, 0x85, 0x44, 0x91, + 0x73, 0x2a, 0x29, 0x52, 0xb3, 0x3e, 0xb3, 0xe7, + 0x54, 0x8d, 0xd2, 0x06, 0xe1, 0x99, 0xec, 0xff, + 0xc2, 0x6b, 0x00, 0x95, 0x56, 0x30, 0xcd, 0x48, + 0xc0, 0xf0, 0x23, 0xef, 0x43, 0xa9, 0x1e, 0x97, + 0x80, 0x61, 0x63, 0x96, 0x60, 0x58, 0x6e, 0xa9, + 0x6f, 0x6d, 0x95, 0xb1, 0x12, 0x36, 0x47, 0x7d, + 0x16, 0xf5, 0x98, 0x79, 0x0f }; int result = 0; diff --git a/tests/test_protocol.c b/tests/test_protocol.c index b78b1ceb..b0335e90 100644 --- a/tests/test_protocol.c +++ b/tests/test_protocol.c @@ -65,6 +65,7 @@ START_TEST(test_serialize_signal_message) 1, /* previous counter */ (uint8_t *)ciphertext, sizeof(ciphertext) - 1, sender_identity_key, receiver_identity_key, + 1, global_context); ck_assert_int_eq(result, 0); @@ -82,7 +83,7 @@ START_TEST(test_serialize_signal_message) /* Exercise the MAC verification code */ result = signal_message_verify_mac(result_message, sender_identity_key, receiver_identity_key, - mac_key, sizeof(mac_key), global_context); + mac_key, sizeof(mac_key), 1, global_context); ck_assert_int_eq(result, 1); /* Cleanup */ @@ -115,6 +116,7 @@ START_TEST(test_serialize_signal_message_omemo) 1, /* previous counter */ (uint8_t *)ciphertext, sizeof(ciphertext) - 1, sender_identity_key, receiver_identity_key, + 1, global_context); ck_assert_int_eq(result, 0); @@ -132,7 +134,7 @@ START_TEST(test_serialize_signal_message_omemo) /* Exercise the MAC verification code */ result = signal_message_verify_mac(result_message, sender_identity_key, receiver_identity_key, - mac_key, sizeof(mac_key), global_context); + mac_key, sizeof(mac_key), 1, global_context); ck_assert_int_eq(result, 1); /* Cleanup */ @@ -168,6 +170,7 @@ START_TEST(test_serialize_pre_key_signal_message) 1, /* previous counter */ (uint8_t *)ciphertext, sizeof(ciphertext) - 1, sender_identity_key, receiver_identity_key, + 1, global_context); ck_assert_int_eq(result, 0); @@ -261,6 +264,7 @@ START_TEST(test_serialize_pre_key_signal_message_omemo) 1, /* previous counter */ (uint8_t *)ciphertext, sizeof(ciphertext) - 1, sender_identity_key, receiver_identity_key, + 1, global_context); ck_assert_int_eq(result, 0); diff --git a/tests/test_session_builder.c b/tests/test_session_builder.c index 0453582a..84abd0d2 100644 --- a/tests/test_session_builder.c +++ b/tests/test_session_builder.c @@ -162,6 +162,11 @@ START_TEST(test_basic_pre_key_v3) ec_key_pair_get_public(bob_signed_pre_key_pair)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_public_serialized_omemo = 0; + result = ec_public_key_serialize_omemo(&bob_signed_pre_key_public_serialized_omemo, + ec_key_pair_get_public(bob_signed_pre_key_pair)); + ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature = 0; result = curve_calculate_signature(global_context, &bob_signed_pre_key_signature, @@ -170,6 +175,14 @@ START_TEST(test_basic_pre_key_v3) signal_buffer_len(bob_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature_omemo = 0; + result = curve_calculate_signature(global_context, + &bob_signed_pre_key_signature_omemo, + ratchet_identity_key_pair_get_private(bob_identity_key_pair), + signal_buffer_data(bob_signed_pre_key_public_serialized_omemo), + signal_buffer_len(bob_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + session_pre_key_bundle *bob_pre_key = 0; result = session_pre_key_bundle_create(&bob_pre_key, bob_local_registration_id, @@ -243,7 +256,9 @@ START_TEST(test_basic_pre_key_v3) 22, time(0), bob_signed_pre_key_pair, signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature)); + signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(bob_store, bob_signed_pre_key_record); @@ -390,7 +405,9 @@ START_TEST(test_basic_pre_key_v3) 23, time(0), bob_signed_pre_key_pair, signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature)); + signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(bob_store, bob_signed_pre_key_record); @@ -527,6 +544,11 @@ START_TEST(test_basic_pre_key_omemo) ec_key_pair_get_public(bob_signed_pre_key_pair)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_public_serialized_omemo = 0; + result = ec_public_key_serialize_omemo(&bob_signed_pre_key_public_serialized_omemo, + ec_key_pair_get_public(bob_signed_pre_key_pair)); + ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature = 0; result = curve_calculate_signature(global_context, &bob_signed_pre_key_signature, @@ -535,6 +557,14 @@ START_TEST(test_basic_pre_key_omemo) signal_buffer_len(bob_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature_omemo = 0; + result = curve_calculate_signature(global_context, + &bob_signed_pre_key_signature_omemo, + ratchet_identity_key_pair_get_private(bob_identity_key_pair), + signal_buffer_data(bob_signed_pre_key_public_serialized_omemo), + signal_buffer_len(bob_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + session_pre_key_bundle *bob_pre_key = 0; result = session_pre_key_bundle_create(&bob_pre_key, bob_local_registration_id, @@ -543,8 +573,8 @@ START_TEST(test_basic_pre_key_omemo) ec_key_pair_get_public(bob_pre_key_pair), 22, /* signed pre key ID */ ec_key_pair_get_public(bob_signed_pre_key_pair), - signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo), ratchet_identity_key_pair_get_public(bob_identity_key_pair)); ck_assert_int_eq(result, 0); @@ -611,7 +641,9 @@ START_TEST(test_basic_pre_key_omemo) 22, time(0), bob_signed_pre_key_pair, signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature)); + signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(bob_store, bob_signed_pre_key_record); @@ -701,6 +733,7 @@ START_TEST(test_basic_pre_key_omemo) SIGNAL_UNREF(bob_signed_pre_key_pair); bob_signed_pre_key_pair = 0; SIGNAL_UNREF(bob_identity_key_pair); bob_identity_key_pair = 0; signal_buffer_free(bob_signed_pre_key_signature); bob_signed_pre_key_signature = 0; + signal_buffer_free(bob_signed_pre_key_signature_omemo); bob_signed_pre_key_signature_omemo = 0; SIGNAL_UNREF(bob_pre_key_record); bob_pre_key_record = 0; SIGNAL_UNREF(bob_signed_pre_key_record); bob_signed_pre_key_record = 0; @@ -727,6 +760,10 @@ START_TEST(test_basic_pre_key_omemo) ec_key_pair_get_public(bob_signed_pre_key_pair)); ck_assert_int_eq(result, 0); + result = ec_public_key_serialize_omemo(&bob_signed_pre_key_public_serialized_omemo, + ec_key_pair_get_public(bob_signed_pre_key_pair)); + ck_assert_int_eq(result, 0); + result = curve_calculate_signature(global_context, &bob_signed_pre_key_signature, ratchet_identity_key_pair_get_private(bob_identity_key_pair), @@ -734,6 +771,13 @@ START_TEST(test_basic_pre_key_omemo) signal_buffer_len(bob_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + result = curve_calculate_signature(global_context, + &bob_signed_pre_key_signature_omemo, + ratchet_identity_key_pair_get_private(bob_identity_key_pair), + signal_buffer_data(bob_signed_pre_key_public_serialized_omemo), + signal_buffer_len(bob_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + result = session_pre_key_bundle_create(&bob_pre_key, bob_local_registration_id, 1, /* device ID */ @@ -741,8 +785,8 @@ START_TEST(test_basic_pre_key_omemo) ec_key_pair_get_public(bob_pre_key_pair), 23, /* signed pre key ID */ ec_key_pair_get_public(bob_signed_pre_key_pair), - signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo), ratchet_identity_key_pair_get_public(bob_identity_key_pair)); ck_assert_int_eq(result, 0); @@ -761,7 +805,9 @@ START_TEST(test_basic_pre_key_omemo) 23, time(0), bob_signed_pre_key_pair, signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature)); + signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(bob_store, bob_signed_pre_key_record); @@ -1026,6 +1072,11 @@ START_TEST(test_repeat_bundle_message_v2) ec_key_pair_get_public(bob_signed_pre_key_pair)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_public_serialized_omemo = 0; + result = ec_public_key_serialize_omemo(&bob_signed_pre_key_public_serialized_omemo, + ec_key_pair_get_public(bob_signed_pre_key_pair)); + ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature = 0; result = curve_calculate_signature(global_context, &bob_signed_pre_key_signature, @@ -1034,6 +1085,14 @@ START_TEST(test_repeat_bundle_message_v2) signal_buffer_len(bob_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature_omemo = 0; + result = curve_calculate_signature(global_context, + &bob_signed_pre_key_signature_omemo, + ratchet_identity_key_pair_get_private(bob_identity_key_pair), + signal_buffer_data(bob_signed_pre_key_public_serialized_omemo), + signal_buffer_len(bob_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + session_pre_key_bundle *bob_pre_key = 0; result = session_pre_key_bundle_create(&bob_pre_key, bob_local_registration_id, @@ -1059,7 +1118,9 @@ START_TEST(test_repeat_bundle_message_v2) 22, time(0), bob_signed_pre_key_pair, signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature)); + signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(bob_store, bob_signed_pre_key_record); @@ -1123,6 +1184,11 @@ START_TEST(test_repeat_bundle_message_v3) ec_key_pair_get_public(bob_signed_pre_key_pair)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_public_serialized_omemo = 0; + result = ec_public_key_serialize_omemo(&bob_signed_pre_key_public_serialized_omemo, + ec_key_pair_get_public(bob_signed_pre_key_pair)); + ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature = 0; result = curve_calculate_signature(global_context, &bob_signed_pre_key_signature, @@ -1131,6 +1197,14 @@ START_TEST(test_repeat_bundle_message_v3) signal_buffer_len(bob_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature_omemo = 0; + result = curve_calculate_signature(global_context, + &bob_signed_pre_key_signature_omemo, + ratchet_identity_key_pair_get_private(bob_identity_key_pair), + signal_buffer_data(bob_signed_pre_key_public_serialized_omemo), + signal_buffer_len(bob_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + session_pre_key_bundle *bob_pre_key = 0; result = session_pre_key_bundle_create(&bob_pre_key, bob_local_registration_id, @@ -1159,7 +1233,9 @@ START_TEST(test_repeat_bundle_message_v3) 22, time(0), bob_signed_pre_key_pair, signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature)); + signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(bob_store, bob_signed_pre_key_record); @@ -1328,6 +1404,11 @@ START_TEST(test_bad_message_bundle) ec_key_pair_get_public(bob_signed_pre_key_pair)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_public_serialized_omemo = 0; + result = ec_public_key_serialize_omemo(&bob_signed_pre_key_public_serialized_omemo, + ec_key_pair_get_public(bob_signed_pre_key_pair)); + ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature = 0; result = curve_calculate_signature(global_context, &bob_signed_pre_key_signature, @@ -1336,6 +1417,14 @@ START_TEST(test_bad_message_bundle) signal_buffer_len(bob_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature_omemo = 0; + result = curve_calculate_signature(global_context, + &bob_signed_pre_key_signature_omemo, + ratchet_identity_key_pair_get_private(bob_identity_key_pair), + signal_buffer_data(bob_signed_pre_key_public_serialized_omemo), + signal_buffer_len(bob_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + session_pre_key_bundle *bob_pre_key = 0; result = session_pre_key_bundle_create(&bob_pre_key, bob_local_registration_id, @@ -1364,7 +1453,9 @@ START_TEST(test_bad_message_bundle) 22, time(0), bob_signed_pre_key_pair, signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature)); + signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(bob_store, bob_signed_pre_key_record); @@ -1492,6 +1583,11 @@ START_TEST(test_optional_one_time_pre_key) ec_key_pair_get_public(bob_signed_pre_key_pair)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_public_serialized_omemo = 0; + result = ec_public_key_serialize_omemo(&bob_signed_pre_key_public_serialized_omemo, + ec_key_pair_get_public(bob_signed_pre_key_pair)); + ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature = 0; result = curve_calculate_signature(global_context, &bob_signed_pre_key_signature, @@ -1500,6 +1596,14 @@ START_TEST(test_optional_one_time_pre_key) signal_buffer_len(bob_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_signature_omemo = 0; + result = curve_calculate_signature(global_context, + &bob_signed_pre_key_signature_omemo, + ratchet_identity_key_pair_get_private(bob_identity_key_pair), + signal_buffer_data(bob_signed_pre_key_public_serialized_omemo), + signal_buffer_len(bob_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + session_pre_key_bundle *bob_pre_key = 0; result = session_pre_key_bundle_create(&bob_pre_key, bob_local_registration_id, @@ -1568,7 +1672,9 @@ START_TEST(test_optional_one_time_pre_key) 22, time(0), bob_signed_pre_key_pair, signal_buffer_data(bob_signed_pre_key_signature), - signal_buffer_len(bob_signed_pre_key_signature)); + signal_buffer_len(bob_signed_pre_key_signature), + signal_buffer_data(bob_signed_pre_key_signature_omemo), + signal_buffer_len(bob_signed_pre_key_signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(bob_store, bob_signed_pre_key_record); diff --git a/tests/test_simultaneous_initiate.c b/tests/test_simultaneous_initiate.c index ec8ce9f4..18668416 100644 --- a/tests/test_simultaneous_initiate.c +++ b/tests/test_simultaneous_initiate.c @@ -1557,6 +1557,10 @@ session_pre_key_bundle *create_alice_pre_key_bundle(signal_protocol_store_contex result = ec_public_key_serialize(&alice_signed_pre_key_public_serialized, alice_signed_pre_key_public); ck_assert_int_eq(result, 0); + signal_buffer *alice_signed_pre_key_public_serialized_omemo = 0; + result = ec_public_key_serialize_omemo(&alice_signed_pre_key_public_serialized_omemo, alice_signed_pre_key_public); + ck_assert_int_eq(result, 0); + signal_buffer *signature = 0; result = curve_calculate_signature(global_context, &signature, ratchet_identity_key_pair_get_private(alice_identity_key_pair), @@ -1564,6 +1568,13 @@ session_pre_key_bundle *create_alice_pre_key_bundle(signal_protocol_store_contex signal_buffer_len(alice_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + signal_buffer *signature_omemo = 0; + result = curve_calculate_signature(global_context, &signature_omemo, + ratchet_identity_key_pair_get_private(alice_identity_key_pair), + signal_buffer_data(alice_signed_pre_key_public_serialized_omemo), + signal_buffer_len(alice_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + session_pre_key_bundle *alice_pre_key_bundle = 0; result = session_pre_key_bundle_create(&alice_pre_key_bundle, 1, 1, @@ -1577,7 +1588,8 @@ session_pre_key_bundle *create_alice_pre_key_bundle(signal_protocol_store_contex session_signed_pre_key *signed_pre_key_record = 0; result = session_signed_pre_key_create(&signed_pre_key_record, alice_signed_pre_key_id, time(0), alice_signed_pre_key, - signal_buffer_data(signature), signal_buffer_len(signature)); + signal_buffer_data(signature), signal_buffer_len(signature), + signal_buffer_data(signature_omemo), signal_buffer_len(signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(store, signed_pre_key_record); @@ -1595,7 +1607,9 @@ session_pre_key_bundle *create_alice_pre_key_bundle(signal_protocol_store_contex SIGNAL_UNREF(alice_identity_key_pair); SIGNAL_UNREF(alice_unsigned_pre_key); signal_buffer_free(alice_signed_pre_key_public_serialized); + signal_buffer_free(alice_signed_pre_key_public_serialized_omemo); signal_buffer_free(signature); + signal_buffer_free(signature_omemo); return alice_pre_key_bundle; } @@ -1620,6 +1634,10 @@ session_pre_key_bundle *create_bob_pre_key_bundle(signal_protocol_store_context result = ec_public_key_serialize(&bob_signed_pre_key_public_serialized, bob_signed_pre_key_public); ck_assert_int_eq(result, 0); + signal_buffer *bob_signed_pre_key_public_serialized_omemo = 0; + result = ec_public_key_serialize_omemo(&bob_signed_pre_key_public_serialized_omemo, bob_signed_pre_key_public); + ck_assert_int_eq(result, 0); + signal_buffer *signature = 0; result = curve_calculate_signature(global_context, &signature, ratchet_identity_key_pair_get_private(bob_identity_key_pair), @@ -1627,6 +1645,13 @@ session_pre_key_bundle *create_bob_pre_key_bundle(signal_protocol_store_context signal_buffer_len(bob_signed_pre_key_public_serialized)); ck_assert_int_eq(result, 0); + signal_buffer *signature_omemo = 0; + result = curve_calculate_signature(global_context, &signature_omemo, + ratchet_identity_key_pair_get_private(bob_identity_key_pair), + signal_buffer_data(bob_signed_pre_key_public_serialized_omemo), + signal_buffer_len(bob_signed_pre_key_public_serialized_omemo)); + ck_assert_int_eq(result, 0); + session_pre_key_bundle *bob_pre_key_bundle = 0; result = session_pre_key_bundle_create(&bob_pre_key_bundle, 1, 1, @@ -1640,7 +1665,8 @@ session_pre_key_bundle *create_bob_pre_key_bundle(signal_protocol_store_context session_signed_pre_key *signed_pre_key_record = 0; result = session_signed_pre_key_create(&signed_pre_key_record, bob_signed_pre_key_id, time(0), bob_signed_pre_key, - signal_buffer_data(signature), signal_buffer_len(signature)); + signal_buffer_data(signature), signal_buffer_len(signature), + signal_buffer_data(signature_omemo), signal_buffer_len(signature_omemo)); ck_assert_int_eq(result, 0); result = signal_protocol_signed_pre_key_store_key(store, signed_pre_key_record); @@ -1658,7 +1684,9 @@ session_pre_key_bundle *create_bob_pre_key_bundle(signal_protocol_store_context SIGNAL_UNREF(bob_identity_key_pair); SIGNAL_UNREF(bob_unsigned_pre_key); signal_buffer_free(bob_signed_pre_key_public_serialized); + signal_buffer_free(bob_signed_pre_key_public_serialized_omemo); signal_buffer_free(signature); + signal_buffer_free(signature_omemo); return bob_pre_key_bundle; }