1 #include "group_session_builder.h"
2
3 #include <assert.h>
4 #include <string.h>
5 #include "sender_key_record.h"
6 #include "sender_key_state.h"
7 #include "sender_key.h"
8 #include "protocol.h"
9 #include "key_helper.h"
10 #include "signal_protocol_internal.h"
11
12 struct group_session_builder
13 {
14 signal_protocol_store_context *store;
15 signal_context *global_context;
16 };
17
group_session_builder_create(group_session_builder ** builder,signal_protocol_store_context * store,signal_context * global_context)18 int group_session_builder_create(group_session_builder **builder,
19 signal_protocol_store_context *store, signal_context *global_context)
20 {
21 group_session_builder *result = 0;
22
23 assert(store);
24 assert(global_context);
25
26 result = malloc(sizeof(group_session_builder));
27 if(!result) {
28 return SG_ERR_NOMEM;
29 }
30 memset(result, 0, sizeof(group_session_builder));
31
32 result->store = store;
33 result->global_context = global_context;
34
35 *builder = result;
36 return 0;
37 }
38
group_session_builder_process_session(group_session_builder * builder,const signal_protocol_sender_key_name * sender_key_name,sender_key_distribution_message * distribution_message)39 int group_session_builder_process_session(group_session_builder *builder,
40 const signal_protocol_sender_key_name *sender_key_name,
41 sender_key_distribution_message *distribution_message)
42 {
43 int result = 0;
44 sender_key_record *record = 0;
45
46 assert(builder);
47 assert(builder->store);
48 signal_lock(builder->global_context);
49
50 result = signal_protocol_sender_key_load_key(builder->store, &record, sender_key_name);
51 if(result < 0) {
52 goto complete;
53 }
54
55 result = sender_key_record_add_sender_key_state(record,
56 sender_key_distribution_message_get_id(distribution_message),
57 sender_key_distribution_message_get_iteration(distribution_message),
58 sender_key_distribution_message_get_chain_key(distribution_message),
59 sender_key_distribution_message_get_signature_key(distribution_message));
60 if(result < 0) {
61 goto complete;
62 }
63
64 result = signal_protocol_sender_key_store_key(builder->store, sender_key_name, record);
65
66 complete:
67 SIGNAL_UNREF(record);
68 signal_unlock(builder->global_context);
69 return result;
70 }
71
group_session_builder_create_session(group_session_builder * builder,sender_key_distribution_message ** distribution_message,const signal_protocol_sender_key_name * sender_key_name)72 int group_session_builder_create_session(group_session_builder *builder,
73 sender_key_distribution_message **distribution_message,
74 const signal_protocol_sender_key_name *sender_key_name)
75 {
76 int result = 0;
77 sender_key_record *record = 0;
78 sender_key_state *state = 0;
79 uint32_t sender_key_id = 0;
80 signal_buffer *sender_key = 0;
81 ec_key_pair *sender_signing_key = 0;
82 sender_chain_key *chain_key = 0;
83 signal_buffer *seed = 0;
84
85 assert(builder);
86 assert(builder->store);
87 signal_lock(builder->global_context);
88
89 result = signal_protocol_sender_key_load_key(builder->store, &record, sender_key_name);
90 if(result < 0) {
91 goto complete;
92 }
93
94 if(sender_key_record_is_empty(record)) {
95 result = signal_protocol_key_helper_generate_sender_key_id(&sender_key_id, builder->global_context);
96 if(result < 0) {
97 goto complete;
98 }
99
100 result = signal_protocol_key_helper_generate_sender_key(&sender_key, builder->global_context);
101 if(result < 0) {
102 goto complete;
103 }
104
105 result = signal_protocol_key_helper_generate_sender_signing_key(&sender_signing_key, builder->global_context);
106 if(result < 0) {
107 goto complete;
108 }
109
110 result = sender_key_record_set_sender_key_state(record, sender_key_id, 0, sender_key, sender_signing_key);
111 if(result < 0) {
112 goto complete;
113 }
114
115 result = signal_protocol_sender_key_store_key(builder->store, sender_key_name, record);
116 if(result < 0) {
117 goto complete;
118 }
119 }
120
121 result = sender_key_record_get_sender_key_state(record, &state);
122 if(result < 0) {
123 goto complete;
124 }
125
126 chain_key = sender_key_state_get_chain_key(state);
127 seed = sender_chain_key_get_seed(chain_key);
128
129 result = sender_key_distribution_message_create(distribution_message,
130 sender_key_state_get_key_id(state),
131 sender_chain_key_get_iteration(chain_key),
132 signal_buffer_data(seed), signal_buffer_len(seed),
133 sender_key_state_get_signing_key_public(state),
134 builder->global_context);
135
136 complete:
137 signal_buffer_free(sender_key);
138 SIGNAL_UNREF(sender_signing_key);
139 SIGNAL_UNREF(record);
140 signal_unlock(builder->global_context);
141 return result;
142 }
143
group_session_builder_free(group_session_builder * builder)144 void group_session_builder_free(group_session_builder *builder)
145 {
146 if(builder) {
147 free(builder);
148 }
149 }
150