-
+ 899126526FA67B199AE8B8C17F0DCBBB68F59E0C6E88BFB21DACAC13D02FC11F3C6A2AF97920AFD44660C7AC689B51D474E3671CDDEE4443EEEAA5891CA374E6
smg_comms/src/messages.adb
(0 . 0)(1 . 139)
288 -- Message reader & writers for SMG Communication Protocol
289 -- S.MG, 2018
290
291 with Interfaces; use Interfaces;
292 with Serpent;
293 with System; use System;
294
295 package body Messages is
296
297 procedure Write_SKeys_SMsg( Keyset : in Serpent_Keyset;
298 Counter : in Interfaces.Unsigned_16;
299 Msg : out Raw_Types.Serpent_Msg) is
300 Pos : Integer := Msg'First;
301 Check : CRC32.CRC32;
302 PadLen: Integer;
303 K : Serpent.Key;
304 begin
305 -- write Type ID
306 Msg(Pos) := SKeys_S_Type;
307 Pos := Pos + 1;
308
309 -- write count of keys (NB: this IS 8 bits by definition)
310 Msg(Pos) := Keyset.Keys'Length;
311 Pos := Pos + 1;
312
313 -- write keys
314 for I in Keyset.Keys'Range loop
315 -- retrieve Key to write
316 K := Keyset.Keys( I );
317
318 -- write key itself
319 Msg(Pos..Pos+K'Length-1) := K;
320 -- ensure little endian order in message
321 Cast_LE(Msg(Pos..Pos+K'Length-1));
322 Pos := Pos + K'Length;
323
324 -- write CRC of key
325 Check := CRC32.CRC( K );
326 Msg(Pos..Pos+3) := Raw_Types.Cast(Check);
327 Cast_LE(Msg(Pos..Pos+3));
328 Pos := Pos + 4;
329 end loop;
330
331 -- write flag
332 Msg(Pos) := Keyset.Flag;
333 Pos := Pos + 1;
334
335 -- write message counter
336 Msg(Pos..Pos+1) := Raw_Types.Cast(Counter);
337 Cast_LE(Msg(Pos..Pos+1));
338 Pos := Pos + 2;
339
340 -- write padding as needed; endianness is irrelevant here
341 PadLen := Msg'Last - Pos + 1;
342 if PadLen > 0 then
343 declare
344 Pad : Raw_Types.Octets(1..PadLen);
345 begin
346 RNG.Get_Octets( Pad );
347 Msg(Pos..Pos+PadLen-1) := Pad;
348 end;
349 end if;
350 end Write_SKeys_SMsg;
351
352
353 -- Reads a Serpent keyset from given Serpent Message
354 procedure Read_SKeys_SMsg( Msg : in Raw_Types.Serpent_Msg;
355 Counter : out Interfaces.Unsigned_16;
356 Keyset : out Serpent_Keyset) is
357 Pos: Integer := Msg'First;
358 begin
359 -- read type and check
360 if Msg(Pos) = SKeys_S_Type then
361 Pos := Pos + 1;
362 else
363 raise Invalid_Msg;
364 end if;
365
366 -- read count of keys and check
367 if Msg(Pos) in Keys_Count'Range then
368 declare
369 N : Keys_Count := Keys_Count(Msg(Pos));
370 KS : Serpent_Keyset(N);
371 K : Serpent.Key;
372 Check : CRC32.CRC32;
373 O4 : Raw_Types.Octets_4;
374 O2 : Raw_Types.Octets_2;
375 begin
376 Pos := Pos + 1;
377 --read keys and check crc for each
378 for I in 1 .. N loop
379 -- read key and advance pos
380 K := Msg(Pos..Pos+K'Length-1);
381 Cast_LE(K);
382 Pos := Pos + K'Length;
383 -- read crc and compare to crc32(key)
384 O4 := Msg(Pos..Pos+3);
385 Cast_LE(O4);
386 Check := Raw_Types.Cast(O4);
387 Pos := Pos + 4;
388 if Check /= CRC32.CRC(K) then
389 raise Invalid_Msg;
390 end if;
391 -- if it got here, key is fine so add to set
392 KS.Keys(KS.Keys'First + I -1) := K;
393 end loop;
394 -- read and set flag
395 KS.Flag := Msg(Pos);
396 Pos := Pos + 1;
397 -- read and set message counter
398 O2 := Msg(Pos..Pos+1);
399 Cast_LE(O2);
400 Counter := Raw_Types.Cast(O2);
401 -- rest of message is padding so it's ignored
402 -- copy keyset to output variable
403 Keyset := KS;
404 end;
405 else
406 raise Invalid_Msg;
407 end if;
408 end Read_SKeys_SMsg;
409
410 -- private part
411 procedure Cast_LE( LE: in out Raw_Types.Octets ) is
412 begin
413 -- flip octets ONLY if native is big endian.
414 if System.Default_Bit_Order = System.High_Order_First then
415 declare
416 BE: constant Raw_Types.Octets := LE;
417 begin
418 for I in 1..LE'Length loop
419 LE(LE'First+I-1) := BE(BE'Last-I+1);
420 end loop;
421 end;
422 end if;
423 -- NOTHING to do for native little endian
424 end Cast_LE;
425
426 end Messages;