- FD5121B49FCBCB70293B002298FC82272EF291E959FE63D17B5B22BA02B1ABB2B1D12A6D0D9541CAEBE43A300FE08CC329FBCACE81B8341A00296F66EB182A84
+ 04B433F10C5557D2F696FEBE95CA6E9497354129DDFCC95C1E366AF2744B214DB5F7A9E63B401754F1E345ADB0EF658A95A60FB54BC761BA628962AA2E40CCAC
smg_comms/src/messages.adb
(1 . 6)(1 . 7)
75 -- Message reader & writers for SMG Communication Protocol
76 -- S.MG, 2018
77
78 with Raw_Types; use Raw_Types;
79 with Interfaces; use Interfaces;
80 with Serpent;
81 with System; use System;
(14 . 10)(15 . 11)
83
84 procedure Write_SKeys_SMsg( Keyset : in Serpent_Keyset;
85 Counter : in Interfaces.Unsigned_16;
86 Pad : in Raw_Types.Octets_8;
87 Msg : out Raw_Types.Serpent_Msg) is
88 begin
89 -- call internal write on Octets with correct type id
90 Write_SKeys( Keyset, Counter, SKeys_S_Type, Msg );
91 Write_SKeys( Keyset, Counter, SKeys_S_Type, Pad, Msg );
92 end Write_SKeys_SMsg;
93
94
(37 . 10)(39 . 11)
96 -- writes given key mgm structure into a Serpent message
97 procedure Write_KMgm_SMsg( KMgm : in Keys_Mgm;
98 Counter : in Interfaces.Unsigned_16;
99 Pad : in Raw_Types.Octets_8;
100 Msg : out Raw_Types.Serpent_Msg) is
101 begin
102 -- call internal write of key mgm with correct type ID
103 Write_KMgm( KMgm, Counter, Key_Mgm_S_Type, Msg );
104 Write_KMgm( KMgm, Counter, Key_Mgm_S_Type, Pad, Msg );
105 end Write_KMgm_SMsg;
106
107 -- reads a key mgm structure from the given Serpent message
(58 . 6)(61 . 7)
109
110 ------ File Transfer ------
111 procedure Write_File_Transfer( Chunk : in File_Chunk;
112 Pad : in Raw_Types.Octets_8;
113 Msg : out Raw_Types.Serpent_Msg) is
114 Pos: Integer := Msg'First;
115 U16: Interfaces.Unsigned_16;
(68 . 7)(72 . 7)
117
118 -- write filename as text field (size+2, text)
119 -- check against overflows
120 if Chunk.Name_Len > Text_Len'Last - 2 or
121 if Chunk.Name_Len > Raw_Types.Text_Len'Last - 2 or
122 Pos + Integer(Chunk.Name_Len) + 2 > Msg'Last then
123 raise Invalid_Msg;
124 end if;
(84 . 7)(88 . 7)
126
127 --write content
128 -- check against overflow, including the 2 octets for counter at the end
129 if Chunk.Len > Text_Len'Last - 2 or
130 if Chunk.Len > Raw_Types.Text_Len'Last - 2 or
131 Pos + Integer(Chunk.Len) + 4 > Msg'Last then
132 raise Invalid_Msg;
133 end if;
(97 . 13)(101 . 8)
135 Msg(Pos..Pos+Chunk.Content'Length-1) := Chunk.Content;
136 Pos := Pos + Chunk.Content'Length;
137
138 -- write counter
139 Write_U16( Msg, Pos, Chunk.Count );
140
141 -- write padding if needed
142 if Pos <= Msg'Last then
143 RNG.Get_Octets( Msg(Pos..Msg'Last) );
144 end if;
145 -- write counter + padding
146 Write_End( Msg, Pos, Chunk.Count, Pad );
147
148 end Write_File_Transfer;
149
(115 . 9)(114 . 9)
151 Pos: Integer := Msg'First;
152 U16: Interfaces.Unsigned_16;
153 S_Name, E_Name: Integer; --start/end for filename in Msg
154 S_Len: Text_Len; -- length of filename (needed as Text_Len anyway)
155 S_Len: Raw_Types.Text_Len; -- length of filename
156 S_Content, E_Content: Integer; --start/end for content in Msg
157 Content_Len: text_Len; -- length of content (needed as Text_Len anyway)
158 Content_Len: Raw_Types.Text_Len; -- length of content
159 begin
160 -- read and check type ID
161 if Msg(Pos) /= File_Transfer_S_Type then
(134 . 7)(133 . 7)
163 raise Invalid_Msg;
164 end if;
165 U16 := U16 - 2;
166 S_Len := Text_Len(U16);
167 S_Len := Raw_Types.Text_Len(U16);
168
169 -- set start + end for reading filename later, when ready
170 S_Name := Pos;
(149 . 7)(148 . 7)
172 raise Invalid_msg;
173 end if;
174 U16 := U16 - 2;
175 Content_Len := Text_Len(U16);
176 Content_Len := Raw_Types.Text_Len(U16);
177 -- set start and end for reading content later, when ready
178 S_Content := Pos;
179 E_Content := Pos + Integer(U16) - 1;
(180 . 6)(179 . 7)
181 ---- File Requests ----
182 procedure Write_File_Request( FR : in Filenames;
183 Counter : in Interfaces.Unsigned_16;
184 Pad : in Raw_Types.Octets_8;
185 Msg : out Raw_Types.Serpent_Msg;
186 Written : out Natural) is
187 Pos : Integer := Msg'First;
(262 . 13)(262 . 9)
189 end;
190 end loop;
191
192 -- write the message counter in little endian at all times
193 Write_U16( Msg, Pos, Counter );
194 -- write counter + padding
195 Write_End( Msg, Pos, Counter, Pad );
196
197 -- write padding if needed
198 if Pos <= Msg'Last then
199 Rng.Get_Octets( Msg(Pos..Msg'Last) );
200 end if;
201 end Write_File_Request;
202
203 -- Reads a request for files; the opposite of Write_File_Request above
(314 . 7)(310 . 8)
205 -- if it's not that => Invalid_Msg
206 -- F_No and Text_Sz are not overflow (earlier check + calc)
207 declare
208 F : Filenames(Text_Len(F_No), Text_Len(Text_Sz-F_No+1));
209 F : Filenames(Raw_Types.Text_Len(F_No),
210 Raw_Types.Text_Len(Text_Sz-F_No+1));
211 S_Pos : Positive;
212 Index : Positive;
213 begin
(350 . 16)(347 . 158)
215
216 end Read_File_Request;
217
218 -- writes the action (octets+length) into the specified Serpent message
219 procedure Write_Action( A : in Raw_Types.Text_Octets;
220 Counter : in Interfaces.Unsigned_16;
221 Pad : in Raw_Types.Octets_8;
222 Msg : out Raw_Types.Serpent_Msg) is
223 Pos : Natural := Msg'First + 1;
224 MaxPos : Natural := Msg'Last - 1; --2 octets reserved for counter at end
225 U16 : Interfaces.Unsigned_16;
226 begin
227 -- check whether given action FITS into a Serpent message
228 if Pos + 2 + A.Len > MaxPos then
229 raise Invalid_Msg;
230 end if;
231
232 -- write correct type ID
233 Msg( Msg'First ) := Client_Action_S_Type;
234
235 -- write action's TOTAL length
236 U16 := Interfaces.Unsigned_16(A.Len + 2);
237 Write_U16( Msg, Pos, U16 );
238
239 -- write the action itself
240 Msg( Pos..Pos+A.Len-1 ) := A.Content;
241 Pos := Pos + A.Len;
242
243 -- write counter + padding
244 Write_End( Msg, Pos, Counter, Pad );
245
246 end Write_Action;
247
248 -- reads a client action as octets+length from the given Serpent message
249 procedure Read_Action( Msg : in Raw_Types.Serpent_Msg;
250 Counter : out Interfaces.Unsigned_16;
251 A : out Raw_Types.Text_Octets) is
252 Pos : Natural := Msg'First + 1;
253 U16 : Interfaces.Unsigned_16;
254 begin
255 -- read and check message type ID
256 if Msg( Msg'First ) /= Client_Action_S_Type then
257 raise Invalid_Msg;
258 end if;
259
260 -- read size of action (content+ 2 octets the size itself)
261 Read_U16( Msg, Pos, U16 );
262
263 -- check size
264 if U16 < 3 or Pos + Natural(U16) - 2 > Msg'Last - 1 then
265 raise Invalid_Msg;
266 else
267 U16 := U16 - 2; --size of content only
268 end if;
269
270 -- create action, read it from message + assign to output variable
271 declare
272 Act : Raw_Types.Text_Octets( Raw_Types.Text_Len( U16 ) );
273 begin
274 Act.Content := Msg( Pos..Pos+Act.Len-1 );
275 Pos := Pos + Act.Len;
276 A := Act;
277 end;
278
279 -- read counter
280 Read_U16( Msg, Pos, Counter );
281
282 end Read_Action;
283
284 ------------------
285 -- RSA Messages --
286 ------------------
287
288 procedure Write_RKeys_RMsg( K : in Player_RSA;
289 Counter : in Interfaces.Unsigned_16;
290 Pad : in Raw_Types.Octets_8;
291 Msg : out Raw_Types.RSA_Msg) is
292 Pos : Natural := Msg'First + 1;
293 begin
294 -- write correct message type
295 Msg( Msg'First ) := RKeys_R_Type;
296
297 -- write protocol version and subversion
298 Msg( Pos ) := K.Proto_V;
299 Pos := Pos + 1;
300 Write_U16( Msg, Pos, K.Proto_Subv );
301
302 -- write keccak hash of client binary
303 Msg( Pos..Pos + K.Client_Hash'Length-1 ) := K.Client_Hash;
304 Pos := Pos + K.Client_Hash'Length;
305
306 -- write e of RSA key
307 Msg( Pos..Pos + K.e'Length - 1 ) := K.e;
308 Pos := Pos + K.e'Length;
309
310 -- write n of RSA key
311 Msg( Pos..Pos + K.n'Length - 1 ) := K.n;
312 Pos := Pos + K.n'Length;
313
314 -- write preferred padding
315 Msg( Pos..Pos + K.Padding'Length - 1 ) := K.Padding;
316 Pos := Pos + K.Padding'Length;
317
318 -- write counter + padding
319 Write_End( Msg, Pos, Counter, Pad );
320
321 end Write_RKeys_RMsg;
322
323 -- Reads a RSA Keyset (Player_RSA structures) from the given RSA Message.
324 -- Opposite of Write_RKeys_RMsg above
325 procedure Read_RKeys_RMsg( Msg : in Raw_Types.RSA_Msg;
326 Counter : out Interfaces.Unsigned_16;
327 K : out Player_RSA) is
328 Pos : Natural := Msg'First + 1;
329 begin
330 -- check type id and raise exception if incorrect
331 if Msg(Msg'First) /= RKeys_R_Type then
332 raise Invalid_Msg;
333 end if;
334
335 -- read protocol version and subversion
336 K.Proto_V := Msg( Pos );
337 Pos := Pos + 1;
338 Read_U16( Msg, Pos, K.Proto_Subv );
339
340 -- read Keccak hash of client binary
341 K.Client_Hash := Msg( Pos..Pos+K.Client_Hash'Length - 1 );
342 Pos := Pos + K.Client_Hash'Length;
343
344 -- read e
345 K.e := Msg( Pos .. Pos + K.e'Length - 1 );
346 Pos := Pos + K.e'Length;
347
348 -- read n
349 K.n := Msg( Pos .. Pos + K.n'Length - 1 );
350 Pos := Pos + K.n'Length;
351
352 -- read choice of padding
353 K.Padding := Msg( Pos .. Pos+K.Padding'Length - 1 );
354 Pos := Pos + K.Padding'Length;
355
356 -- read message counter
357 Read_U16( Msg, Pos, Counter );
358
359 -- the rest is message padding, so ignore it
360
361 end Read_RKeys_RMsg;
362
363 procedure Write_SKeys_RMsg( Keyset : in Serpent_Keyset;
364 Counter : in Interfaces.Unsigned_16;
365 Pad : in Raw_Types.Octets_8;
366 Msg : out Raw_Types.RSA_Msg) is
367 begin
368 -- call internal write of Serpent keys with correct type ID
369 Write_SKeys( Keyset, Counter, SKeys_R_Type, Msg );
370 Write_SKeys( Keyset, Counter, SKeys_R_Type, Pad, Msg );
371 end Write_SKeys_RMsg;
372
373 procedure Read_SKeys_RMsg( Msg : in Raw_Types.RSA_Msg;
(376 . 10)(515 . 11)
375
376 procedure Write_KMgm_RMsg( KMgm : in Keys_Mgm;
377 Counter : in Interfaces.Unsigned_16;
378 Pad : in Raw_Types.Octets_8;
379 Msg : out Raw_Types.RSA_Msg) is
380 begin
381 -- call internal write of key mgm with correct type ID
382 Write_KMgm( KMgm, Counter, Key_Mgm_R_Type, Msg );
383 Write_KMgm( KMgm, Counter, Key_Mgm_R_Type, Pad, Msg );
384 end Write_KMgm_RMsg;
385
386 procedure Read_KMgm_RMsg( Msg : in Raw_Types.RSA_Msg;
(436 . 6)(576 . 7)
388 procedure Write_SKeys( Keyset : in Serpent_Keyset;
389 Counter : in Interfaces.Unsigned_16;
390 Type_ID : in Interfaces.Unsigned_8;
391 Pad : in Raw_Types.Octets_8;
392 Msg : out Raw_Types.Octets) is
393 Pos : Integer := Msg'First;
394 Check : CRC32.CRC32;
(471 . 13)(612 . 8)
396 Msg(Pos) := Keyset.Flag;
397 Pos := Pos + 1;
398
399 -- write message counter
400 Write_U16( Msg, Pos, Counter );
401
402 -- write padding as needed; endianness is irrelevant here
403 if Pos <= Msg'Last then
404 RNG.Get_Octets( Msg(Pos..Msg'Last) );
405 end if;
406 -- write counter + padding
407 Write_End( Msg, Pos, Counter, Pad );
408
409 end Write_SKeys;
410
(539 . 6)(675 . 7)
412 procedure Write_KMgm( KMgm : in Keys_Mgm;
413 Counter : in Interfaces.Unsigned_16;
414 Type_ID : in Interfaces.Unsigned_8;
415 Pad : in Raw_Types.Octets_8;
416 Msg : out Raw_Types.Octets) is
417 Pos : Integer := Msg'First;
418 begin
(568 . 13)(705 . 8)
420 Pos := Pos + KMgm.Burnt'Length;
421 end if;
422
423 -- write the message count
424 Write_U16( Msg, Pos, Counter );
425
426 -- pad with random octets until the end of Msg
427 if Pos <= Msg'Last then
428 RNG.Get_Octets( Msg(Pos..Msg'Last) );
429 end if;
430 -- write counter + padding
431 Write_End( Msg, Pos, Counter, Pad );
432
433 end Write_KMgm;
434
(647 . 4)(779 . 33)
436 Pos := Pos + 2;
437 end Read_U16;
438
439 -- Writes Counter and padding (rng or otherwise) into Msg starting from Pos.
440 procedure Write_End( Msg : in out Raw_Types.Octets;
441 Pos : in out Natural;
442 Counter : in Interfaces.Unsigned_16;
443 Padding : in Raw_Types.Octets_8) is
444 begin
445 -- check that there is space for Counter at the very least
446 if Pos > Msg'Last - 1 then
447 raise Invalid_Msg;
448 end if;
449
450 -- write counter
451 Write_U16( Msg, Pos, Counter );
452
453 -- pad to the end of the message
454 if Pos <= Msg'Last then
455 if Padding = RNG_PAD then
456 RNG.Get_Octets( Msg( Pos..Msg'Last ) );
457 else
458 -- repeat the Padding value itself
459 for I in Pos..Msg'Last loop
460 Msg(I) := Padding( Padding'First + (I - Pos) mod Padding'Length );
461 end loop;
462 end if;
463 -- either rng or fixed, update Pos though
464 Pos := Msg'Last + 1;
465 end if;
466 end Write_End;
467
468 end Messages;