raw
smg_comms_skeys_s...    1  -- Message reader & writers for SMG Communication Protocol
smg_comms_skeys_s... 2 -- S.MG, 2018
smg_comms_skeys_s... 3
smg_comms_skeys_s... 4 with Interfaces; use Interfaces;
smg_comms_skeys_s... 5 with Serpent;
smg_comms_skeys_s... 6 with System; use System;
smg_comms_skeys_s... 7
smg_comms_skeys_s... 8 package body Messages is
smg_comms_skeys_s... 9
smg_comms_keymgm 10 ----------------------
smg_comms_keymgm 11 -- Serpent Messages --
smg_comms_keymgm 12 ----------------------
smg_comms_keymgm 13
smg_comms_skeys_s... 14 procedure Write_SKeys_SMsg( Keyset : in Serpent_Keyset;
smg_comms_skeys_s... 15 Counter : in Interfaces.Unsigned_16;
smg_comms_skeys_s... 16 Msg : out Raw_Types.Serpent_Msg) is
smg_comms_keymgm 17 begin
smg_comms_keymgm 18 -- call internal write on Octets with correct type id
smg_comms_keymgm 19 Write_SKeys( Keyset, Counter, SKeys_S_Type, Msg );
smg_comms_keymgm 20 end Write_SKeys_SMsg;
smg_comms_keymgm 21
smg_comms_keymgm 22
smg_comms_keymgm 23 -- Reads a Serpent keyset from given Serpent Message
smg_comms_keymgm 24 procedure Read_SKeys_SMsg( Msg : in Raw_Types.Serpent_Msg;
smg_comms_keymgm 25 Counter : out Interfaces.Unsigned_16;
smg_comms_keymgm 26 Keyset : out Serpent_Keyset) is
smg_comms_keymgm 27 begin
smg_comms_keymgm 28 -- check type id and call internal Read_SKeys if correct
smg_comms_keymgm 29 if Msg(Msg'First) /= SKeys_S_Type then
smg_comms_keymgm 30 raise Invalid_Msg;
smg_comms_keymgm 31 else
smg_comms_keymgm 32 Read_SKeys( Msg, Counter, Keyset );
smg_comms_keymgm 33 end if;
smg_comms_keymgm 34 end Read_SKeys_SMsg;
smg_comms_keymgm 35
smg_comms_keymgm 36 -- writes given key mgm structure into a Serpent message
smg_comms_keymgm 37 procedure Write_KMgm_SMsg( KMgm : in Keys_Mgm;
smg_comms_keymgm 38 Counter : in Interfaces.Unsigned_16;
smg_comms_keymgm 39 Msg : out Raw_Types.Serpent_Msg) is
smg_comms_keymgm 40 begin
smg_comms_keymgm 41 -- call internal write of key mgm with correct type ID
smg_comms_keymgm 42 Write_KMgm( KMgm, Counter, Key_Mgm_S_Type, Msg );
smg_comms_keymgm 43 end Write_KMgm_SMsg;
smg_comms_keymgm 44
smg_comms_keymgm 45 -- reads a key mgm structure from the given Serpent message
smg_comms_keymgm 46 procedure Read_KMgm_SMsg( Msg : in Raw_Types.Serpent_Msg;
smg_comms_keymgm 47 Counter : out Interfaces.Unsigned_16;
smg_comms_keymgm 48 KMgm : out Keys_Mgm) is
smg_comms_keymgm 49 begin
smg_comms_keymgm 50 -- check type id and call internal Read_KMgm if correct
smg_comms_keymgm 51 if Msg(Msg'First) /= Key_Mgm_S_Type then
smg_comms_keymgm 52 raise Invalid_Msg;
smg_comms_keymgm 53 else
smg_comms_keymgm 54 Read_KMgm( Msg, Counter, KMgm );
smg_comms_keymgm 55 end if;
smg_comms_keymgm 56 end Read_KMgm_SMsg;
smg_comms_keymgm 57
smg_comms_keymgm 58
smg_comms_keymgm 59 ------------------
smg_comms_keymgm 60 -- RSA Messages --
smg_comms_keymgm 61 ------------------
smg_comms_keymgm 62
smg_comms_keymgm 63 procedure Write_SKeys_RMsg( Keyset : in Serpent_Keyset;
smg_comms_keymgm 64 Counter : in Interfaces.Unsigned_16;
smg_comms_keymgm 65 Msg : out Raw_Types.RSA_Msg) is
smg_comms_keymgm 66 begin
smg_comms_keymgm 67 -- call internal write of Serpent keys with correct type ID
smg_comms_keymgm 68 Write_SKeys( Keyset, Counter, SKeys_R_Type, Msg );
smg_comms_keymgm 69 end Write_SKeys_RMsg;
smg_comms_keymgm 70
smg_comms_keymgm 71 procedure Read_SKeys_RMsg( Msg : in Raw_Types.RSA_Msg;
smg_comms_keymgm 72 Counter : out Interfaces.Unsigned_16;
smg_comms_keymgm 73 Keyset : out Serpent_Keyset) is
smg_comms_keymgm 74 begin
smg_comms_keymgm 75 -- check type id and call internal Read_SKeys if correct
smg_comms_keymgm 76 if Msg(Msg'First) /= SKeys_R_Type then
smg_comms_keymgm 77 raise Invalid_Msg;
smg_comms_keymgm 78 else
smg_comms_keymgm 79 Read_SKeys( Msg, Counter, Keyset );
smg_comms_keymgm 80 end if;
smg_comms_keymgm 81 end Read_SKeys_RMsg;
smg_comms_keymgm 82
smg_comms_keymgm 83 procedure Write_KMgm_RMsg( KMgm : in Keys_Mgm;
smg_comms_keymgm 84 Counter : in Interfaces.Unsigned_16;
smg_comms_keymgm 85 Msg : out Raw_Types.RSA_Msg) is
smg_comms_keymgm 86 begin
smg_comms_keymgm 87 -- call internal write of key mgm with correct type ID
smg_comms_keymgm 88 Write_KMgm( KMgm, Counter, Key_Mgm_R_Type, Msg );
smg_comms_keymgm 89 end Write_KMgm_RMsg;
smg_comms_keymgm 90
smg_comms_keymgm 91 procedure Read_KMgm_RMsg( Msg : in Raw_Types.RSA_Msg;
smg_comms_keymgm 92 Counter : out Interfaces.Unsigned_16;
smg_comms_keymgm 93 KMgm : out Keys_Mgm) is
smg_comms_keymgm 94 begin
smg_comms_keymgm 95 -- check type id and call internal Read_KMgm if correct
smg_comms_keymgm 96 if Msg(Msg'First) /= Key_Mgm_R_Type then
smg_comms_keymgm 97 raise Invalid_Msg;
smg_comms_keymgm 98 else
smg_comms_keymgm 99 Read_KMgm( Msg, Counter, KMgm );
smg_comms_keymgm 100 end if;
smg_comms_keymgm 101 end Read_KMgm_RMsg;
smg_comms_keymgm 102
smg_comms_keymgm 103 ------------------
smg_comms_keymgm 104 -- private part --
smg_comms_keymgm 105 ------------------
smg_comms_keymgm 106 procedure Cast_LE( LE: in out Raw_Types.Octets ) is
smg_comms_keymgm 107 begin
smg_comms_keymgm 108 -- flip octets ONLY if native is big endian.
smg_comms_keymgm 109 if System.Default_Bit_Order = System.High_Order_First then
smg_comms_keymgm 110 declare
smg_comms_keymgm 111 BE: constant Raw_Types.Octets := LE;
smg_comms_keymgm 112 begin
smg_comms_keymgm 113 for I in 1..LE'Length loop
smg_comms_keymgm 114 LE(LE'First+I-1) := BE(BE'Last-I+1);
smg_comms_keymgm 115 end loop;
smg_comms_keymgm 116 end;
smg_comms_keymgm 117 end if;
smg_comms_keymgm 118 -- NOTHING to do for native little endian
smg_comms_keymgm 119 end Cast_LE;
smg_comms_keymgm 120
smg_comms_keymgm 121 procedure Write_SKeys( Keyset : in Serpent_Keyset;
smg_comms_keymgm 122 Counter : in Interfaces.Unsigned_16;
smg_comms_keymgm 123 Type_ID : in Interfaces.Unsigned_8;
smg_comms_keymgm 124 Msg : out Raw_Types.Octets) is
smg_comms_skeys_s... 125 Pos : Integer := Msg'First;
smg_comms_skeys_s... 126 Check : CRC32.CRC32;
smg_comms_skeys_s... 127 PadLen: Integer;
smg_comms_skeys_s... 128 K : Serpent.Key;
smg_comms_skeys_s... 129 begin
smg_comms_skeys_s... 130 -- write Type ID
smg_comms_keymgm 131 Msg(Pos) := Type_ID;
smg_comms_skeys_s... 132 Pos := Pos + 1;
smg_comms_skeys_s... 133
smg_comms_skeys_s... 134 -- write count of keys (NB: this IS 8 bits by definition)
smg_comms_skeys_s... 135 Msg(Pos) := Keyset.Keys'Length;
smg_comms_skeys_s... 136 Pos := Pos + 1;
smg_comms_skeys_s... 137
smg_comms_skeys_s... 138 -- write keys
smg_comms_skeys_s... 139 for I in Keyset.Keys'Range loop
smg_comms_skeys_s... 140 -- retrieve Key to write
smg_comms_skeys_s... 141 K := Keyset.Keys( I );
smg_comms_skeys_s... 142
smg_comms_skeys_s... 143 -- write key itself
smg_comms_skeys_s... 144 Msg(Pos..Pos+K'Length-1) := K;
smg_comms_skeys_s... 145 -- ensure little endian order in message
smg_comms_skeys_s... 146 Cast_LE(Msg(Pos..Pos+K'Length-1));
smg_comms_skeys_s... 147 Pos := Pos + K'Length;
smg_comms_skeys_s... 148
smg_comms_skeys_s... 149 -- write CRC of key
smg_comms_skeys_s... 150 Check := CRC32.CRC( K );
smg_comms_skeys_s... 151 Msg(Pos..Pos+3) := Raw_Types.Cast(Check);
smg_comms_skeys_s... 152 Cast_LE(Msg(Pos..Pos+3));
smg_comms_skeys_s... 153 Pos := Pos + 4;
smg_comms_skeys_s... 154 end loop;
smg_comms_skeys_s... 155
smg_comms_skeys_s... 156 -- write flag
smg_comms_skeys_s... 157 Msg(Pos) := Keyset.Flag;
smg_comms_skeys_s... 158 Pos := Pos + 1;
smg_comms_skeys_s... 159
smg_comms_skeys_s... 160 -- write message counter
smg_comms_skeys_s... 161 Msg(Pos..Pos+1) := Raw_Types.Cast(Counter);
smg_comms_skeys_s... 162 Cast_LE(Msg(Pos..Pos+1));
smg_comms_skeys_s... 163 Pos := Pos + 2;
smg_comms_skeys_s... 164
smg_comms_skeys_s... 165 -- write padding as needed; endianness is irrelevant here
smg_comms_skeys_s... 166 PadLen := Msg'Last - Pos + 1;
smg_comms_skeys_s... 167 if PadLen > 0 then
smg_comms_skeys_s... 168 declare
smg_comms_skeys_s... 169 Pad : Raw_Types.Octets(1..PadLen);
smg_comms_skeys_s... 170 begin
smg_comms_skeys_s... 171 RNG.Get_Octets( Pad );
smg_comms_skeys_s... 172 Msg(Pos..Pos+PadLen-1) := Pad;
smg_comms_skeys_s... 173 end;
smg_comms_skeys_s... 174 end if;
smg_comms_skeys_s... 175
smg_comms_keymgm 176 end Write_SKeys;
smg_comms_skeys_s... 177
smg_comms_keymgm 178 procedure Read_SKeys( Msg : in Raw_Types.Octets;
smg_comms_keymgm 179 Counter : out Interfaces.Unsigned_16;
smg_comms_keymgm 180 Keyset : out Serpent_Keyset) is
smg_comms_skeys_s... 181 Pos: Integer := Msg'First;
smg_comms_skeys_s... 182 begin
smg_comms_skeys_s... 183 -- read type and check
smg_comms_keymgm 184 if Msg(Pos) = SKeys_S_Type or
smg_comms_keymgm 185 Msg(Pos) = SKeys_R_Type then
smg_comms_skeys_s... 186 Pos := Pos + 1;
smg_comms_skeys_s... 187 else
smg_comms_skeys_s... 188 raise Invalid_Msg;
smg_comms_skeys_s... 189 end if;
smg_comms_skeys_s... 190
smg_comms_skeys_s... 191 -- read count of keys and check
smg_comms_skeys_s... 192 if Msg(Pos) in Keys_Count'Range then
smg_comms_skeys_s... 193 declare
smg_comms_skeys_s... 194 N : Keys_Count := Keys_Count(Msg(Pos));
smg_comms_skeys_s... 195 KS : Serpent_Keyset(N);
smg_comms_skeys_s... 196 K : Serpent.Key;
smg_comms_skeys_s... 197 Check : CRC32.CRC32;
smg_comms_skeys_s... 198 O4 : Raw_Types.Octets_4;
smg_comms_skeys_s... 199 O2 : Raw_Types.Octets_2;
smg_comms_skeys_s... 200 begin
smg_comms_skeys_s... 201 Pos := Pos + 1;
smg_comms_skeys_s... 202 --read keys and check crc for each
smg_comms_skeys_s... 203 for I in 1 .. N loop
smg_comms_skeys_s... 204 -- read key and advance pos
smg_comms_skeys_s... 205 K := Msg(Pos..Pos+K'Length-1);
smg_comms_skeys_s... 206 Cast_LE(K);
smg_comms_skeys_s... 207 Pos := Pos + K'Length;
smg_comms_skeys_s... 208 -- read crc and compare to crc32(key)
smg_comms_skeys_s... 209 O4 := Msg(Pos..Pos+3);
smg_comms_skeys_s... 210 Cast_LE(O4);
smg_comms_skeys_s... 211 Check := Raw_Types.Cast(O4);
smg_comms_skeys_s... 212 Pos := Pos + 4;
smg_comms_skeys_s... 213 if Check /= CRC32.CRC(K) then
smg_comms_skeys_s... 214 raise Invalid_Msg;
smg_comms_skeys_s... 215 end if;
smg_comms_skeys_s... 216 -- if it got here, key is fine so add to set
smg_comms_skeys_s... 217 KS.Keys(KS.Keys'First + I -1) := K;
smg_comms_skeys_s... 218 end loop;
smg_comms_skeys_s... 219 -- read and set flag
smg_comms_skeys_s... 220 KS.Flag := Msg(Pos);
smg_comms_skeys_s... 221 Pos := Pos + 1;
smg_comms_skeys_s... 222 -- read and set message counter
smg_comms_skeys_s... 223 O2 := Msg(Pos..Pos+1);
smg_comms_skeys_s... 224 Cast_LE(O2);
smg_comms_skeys_s... 225 Counter := Raw_Types.Cast(O2);
smg_comms_skeys_s... 226 -- rest of message is padding so it's ignored
smg_comms_skeys_s... 227 -- copy keyset to output variable
smg_comms_skeys_s... 228 Keyset := KS;
smg_comms_skeys_s... 229 end;
smg_comms_skeys_s... 230 else
smg_comms_skeys_s... 231 raise Invalid_Msg;
smg_comms_skeys_s... 232 end if;
smg_comms_keymgm 233 end Read_SKeys;
smg_comms_skeys_s... 234
smg_comms_keymgm 235 -- writes given key management structure to the given octets array
smg_comms_keymgm 236 procedure Write_KMgm( KMgm : in Keys_Mgm;
smg_comms_keymgm 237 Counter : in Interfaces.Unsigned_16;
smg_comms_keymgm 238 Type_ID : in Interfaces.Unsigned_8;
smg_comms_keymgm 239 Msg : out Raw_Types.Octets) is
smg_comms_keymgm 240 Pos : Integer := Msg'First;
smg_comms_skeys_s... 241 begin
smg_comms_keymgm 242 -- write given type id
smg_comms_keymgm 243 Msg(Pos) := Type_ID;
smg_comms_keymgm 244 Pos := Pos + 1;
smg_comms_keymgm 245
smg_comms_keymgm 246 -- write count of server keys requested
smg_comms_keymgm 247 Msg(Pos) := KMgm.N_Server;
smg_comms_keymgm 248 Pos := Pos + 1;
smg_comms_keymgm 249
smg_comms_keymgm 250 -- write count of client keys requested
smg_comms_keymgm 251 Msg(Pos) := KMgm.N_Client;
smg_comms_keymgm 252 Pos := Pos + 1;
smg_comms_keymgm 253
smg_comms_keymgm 254 -- write id of key preferred for further inbound Serpent messages
smg_comms_keymgm 255 Msg(Pos) := KMgm.Key_ID;
smg_comms_keymgm 256 Pos := Pos + 1;
smg_comms_keymgm 257
smg_comms_keymgm 258 -- write count of burnt keys in this message
smg_comms_keymgm 259 Msg(Pos..Pos) := Cast( KMgm.N_Burnt );
smg_comms_keymgm 260 Pos := Pos + 1;
smg_comms_keymgm 261
smg_comms_keymgm 262 -- if there are any burnt keys, write their ids
smg_comms_keymgm 263 if KMgm.N_Burnt > 0 then
smg_comms_keymgm 264 Msg( Pos .. Pos + KMgm.Burnt'Length - 1 ) := KMgm.Burnt;
smg_comms_keymgm 265 Pos := Pos + KMgm.Burnt'Length;
smg_comms_skeys_s... 266 end if;
smg_comms_keymgm 267
smg_comms_keymgm 268 -- write the message count
smg_comms_keymgm 269 Msg(Pos..Pos+1) := Raw_Types.Cast( Counter );
smg_comms_keymgm 270 Cast_LE( Msg(Pos..Pos+1) );
smg_comms_keymgm 271 Pos := Pos + 2;
smg_comms_keymgm 272
smg_comms_keymgm 273 -- pad with random octets until the end of Msg
smg_comms_keymgm 274 RNG.Get_Octets( Msg(Pos..Msg'Last) );
smg_comms_keymgm 275
smg_comms_keymgm 276 end Write_KMgm;
smg_comms_keymgm 277
smg_comms_keymgm 278 -- attempts to read from the given array of octets a key management structure
smg_comms_keymgm 279 procedure Read_KMgm( Msg : in Raw_Types.Octets;
smg_comms_keymgm 280 Counter : out Interfaces.Unsigned_16;
smg_comms_keymgm 281 KMgm : out Keys_Mgm) is
smg_comms_keymgm 282 Pos : Integer := Msg'First;
smg_comms_keymgm 283 Burnt_Pos : Integer := Msg'First + 4;
smg_comms_keymgm 284 begin
smg_comms_keymgm 285 -- read type and check
smg_comms_keymgm 286 if Msg(Pos) = Key_Mgm_S_Type or
smg_comms_keymgm 287 Msg(Pos) = Key_Mgm_R_Type then
smg_comms_keymgm 288 Pos := Pos + 1;
smg_comms_keymgm 289 else
smg_comms_keymgm 290 raise Invalid_Msg;
smg_comms_keymgm 291 end if;
smg_comms_keymgm 292
smg_comms_keymgm 293 -- read the count of burnt keys and check
smg_comms_keymgm 294 -- NB: Burnt_Pos IS in range of Counter_8bits since it's an octet
smg_comms_keymgm 295 declare
smg_comms_keymgm 296 N_Burnt : Counter_8bits := Counter_8bits(Msg(Burnt_Pos));
smg_comms_keymgm 297 Mgm : Keys_Mgm(N_Burnt);
smg_comms_keymgm 298 O2 : Raw_Types.Octets_2;
smg_comms_keymgm 299 begin
smg_comms_keymgm 300 -- read count of server keys requested
smg_comms_keymgm 301 Mgm.N_Server := Msg(Pos);
smg_comms_keymgm 302 Pos := Pos + 1;
smg_comms_keymgm 303
smg_comms_keymgm 304 -- read count of client keys requested
smg_comms_keymgm 305 Mgm.N_Client := Msg(Pos);
smg_comms_keymgm 306 Pos := Pos + 1;
smg_comms_keymgm 307
smg_comms_keymgm 308 -- read ID of Serpent key preferred for further inbound messages
smg_comms_keymgm 309 Mgm.Key_ID := Msg(Pos);
smg_comms_keymgm 310 Pos := Pos + 2; --skip the count of burnt keys as it's read already
smg_comms_keymgm 311
smg_comms_keymgm 312 -- read ids of burnt keys, if any
smg_comms_keymgm 313 if N_Burnt > 0 then
smg_comms_keymgm 314 Mgm.Burnt := Msg(Pos..Pos+N_Burnt-1);
smg_comms_keymgm 315 Pos := Pos + N_Burnt;
smg_comms_keymgm 316 end if;
smg_comms_keymgm 317
smg_comms_keymgm 318 -- read and set message counter
smg_comms_keymgm 319 O2 := Msg(Pos..Pos+1);
smg_comms_keymgm 320 Cast_LE(O2);
smg_comms_keymgm 321 Counter := Raw_Types.Cast(O2);
smg_comms_keymgm 322 -- rest of message is padding so it's ignored
smg_comms_keymgm 323 -- copy the keys mgm structure to output param
smg_comms_keymgm 324 KMgm := Mgm;
smg_comms_keymgm 325 end;
smg_comms_keymgm 326 end Read_KMgm;
smg_comms_keymgm 327
smg_comms_skeys_s... 328
smg_comms_skeys_s... 329 end Messages;