raw
smg_comms_packing...    1   -- Packing/unpacking for Eulora's communication protocol:
smg_comms_packing... 2 -- Serpent Message to/from Serpent Packet
smg_comms_packing... 3 -- RSA Message to/from RSA Packet
smg_comms_packing... 4 -- S.MG, 2018
smg_comms_packing... 5
smg_comms_packing... 6 package body Packing is
smg_comms_packing... 7
smg_comms_packing... 8 -- Packing a Serpent message into Serpent package, using the given key
smg_comms_packing... 9 function Pack( Msg : in Raw_Types.Serpent_Msg;
smg_comms_packing... 10 K : in Serpent.Key )
smg_comms_packing... 11 return Raw_Types.Serpent_Pkt is
smg_comms_packing... 12
smg_comms_packing... 13 -- single Serpent blocks containing plain / encrypted data
smg_comms_packing... 14 Plain : Serpent.Block;
smg_comms_packing... 15 Encr : Serpent.Block;
smg_comms_packing... 16
smg_comms_packing... 17 -- Serpent Key Schedule - needed for direct encr/decr calls
smg_comms_packing... 18 KS : Serpent.Key_Schedule;
smg_comms_packing... 19
smg_comms_packing... 20 -- final resulting Serpent package
smg_comms_packing... 21 Pkt : Raw_Types.Serpent_Pkt := (others => 0);
smg_comms_packing... 22 begin
smg_comms_packing... 23 -- prepare the Serpent key schedule based on given key
smg_comms_packing... 24 Serpent.Prepare_Key( K, KS );
smg_comms_packing... 25
smg_comms_packing... 26 -- encrypt message block by block and copy result in packet
smg_comms_packing... 27 for I in 1 .. S_Blocks loop
smg_comms_packing... 28 -- get current block to encrypt
smg_comms_packing... 29 Plain := Msg( Msg'First + (I-1) * Block_Len ..
smg_comms_packing... 30 Msg'First + I * Block_Len - 1 );
smg_comms_packing... 31 -- encrypt with Serpent
smg_comms_packing... 32 Serpent.Encrypt( KS, Plain, Encr );
smg_comms_packing... 33 -- copy result to output packet
smg_comms_packing... 34 Pkt( Pkt'First + (I-1) * Block_Len ..
smg_comms_packing... 35 Pkt'First + I * Block_Len - 1 )
smg_comms_packing... 36 := Encr;
smg_comms_packing... 37 end loop;
smg_comms_packing... 38
smg_comms_packing... 39 -- return result
smg_comms_packing... 40 return Pkt;
smg_comms_packing... 41 end Pack;
smg_comms_packing... 42
smg_comms_packing... 43 -- Unpacking a Serpent packet into contained message, using the given key
smg_comms_packing... 44 function Unpack( Pkt : in Raw_Types.Serpent_Pkt;
smg_comms_packing... 45 K : in Serpent.Key)
smg_comms_packing... 46 return Raw_Types.Serpent_Msg is
smg_comms_packing... 47 -- single Serpent blocks containing plain / encrypted data
smg_comms_packing... 48 Plain : Serpent.Block;
smg_comms_packing... 49 Encr : Serpent.Block;
smg_comms_packing... 50
smg_comms_packing... 51 -- Serpent Key Schedule - needed for direct encr/decr calls
smg_comms_packing... 52 KS : Serpent.Key_Schedule;
smg_comms_packing... 53
smg_comms_packing... 54 -- the message extracted from the given packet
smg_comms_packing... 55 Msg : Raw_Types.Serpent_Msg := (others => 0);
smg_comms_packing... 56 begin
smg_comms_packing... 57 -- prepare the Serpent key for use
smg_comms_packing... 58 Serpent.Prepare_Key( K, KS );
smg_comms_packing... 59
smg_comms_packing... 60 -- decrypt the Serpent packet block by block
smg_comms_packing... 61 for I in 1 .. S_Blocks loop
smg_comms_packing... 62 -- get current block from input and decrypt
smg_comms_packing... 63 Encr := Pkt( Pkt'First + (I-1) * Block_Len ..
smg_comms_packing... 64 Pkt'First + I * Block_Len - 1 );
smg_comms_packing... 65 Serpent.Decrypt( KS, Encr, Plain );
smg_comms_packing... 66
smg_comms_packing... 67 -- copy result to its correct position in final output
smg_comms_packing... 68 Msg( Msg'First + (I-1) * Block_Len ..
smg_comms_packing... 69 Msg'First + I * Block_Len - 1 )
smg_comms_packing... 70 := Plain;
smg_comms_packing... 71 end loop;
smg_comms_packing... 72
smg_comms_packing... 73 -- return the result - the message content of given package
smg_comms_packing... 74 return Msg;
smg_comms_packing... 75 end Unpack;
smg_comms_packing... 76
smg_comms_packing... 77 -- Packing a RSA message into RSA packet, using the given key
smg_comms_packing... 78 function Pack( Msg : in Raw_Types.RSA_Msg;
smg_comms_packing... 79 K : in RSA_OAEP.RSA_pkey)
smg_comms_packing... 80 return Raw_Types.RSA_Pkt is
smg_comms_packing... 81
smg_comms_packing... 82 -- a chunk that can be processed via rsa+oaep at any given time
smg_comms_packing... 83 Chunk: Raw_Types.Octets(1..Raw_Types.OAEP_MAX_LEN) := (others => 0);
smg_comms_packing... 84
smg_comms_packing... 85 -- number of chunks in the message to process
smg_comms_packing... 86 -- NO incomplete chunks will be processed!
smg_comms_packing... 87 -- NB: values are set so that there are no incomplete blocks here
smg_comms_packing... 88 N : constant Natural := Msg'Length / Chunk'Length;
smg_comms_packing... 89
smg_comms_packing... 90 -- intermediate result, as obtained from rsa_oaep
smg_comms_packing... 91 Encr: Raw_Types.RSA_len := (others => 0);
smg_comms_packing... 92
smg_comms_packing... 93 -- final resulting RSA Packet
smg_comms_packing... 94 Pkt : Raw_Types.RSA_Pkt := (others => 0);
smg_comms_packing... 95 begin
smg_comms_packing... 96 -- there should ALWAYS be precisely N chunks in Msg to feed to rsa_oaep
smg_comms_packing... 97 -- process chunks of Msg one at a time
smg_comms_packing... 98 for I in 1..N loop
smg_comms_packing... 99 -- get current chunk
smg_comms_packing... 100 Chunk := Msg(Msg'First + (I-1) * Chunk'Length ..
smg_comms_packing... 101 Msg'First + I * Chunk'Length - 1 );
smg_comms_packing... 102 -- call rsa oaep encrypt on current chunk
smg_comms_packing... 103 RSA_OAEP.Encrypt( Chunk, K, Encr );
smg_comms_packing... 104 -- copy result to its place in final packet
smg_comms_packing... 105 Pkt( Pkt'First + (I-1) * Encr'Length ..
smg_comms_packing... 106 Pkt'First + I * Encr'Length - 1 ) := Encr;
smg_comms_packing... 107 end loop;
smg_comms_packing... 108 -- return final result
smg_comms_packing... 109 return Pkt;
smg_comms_packing... 110 end Pack;
smg_comms_packing... 111
smg_comms_packing... 112 -- Unpacking a RSA packet into contained message, using the given key
smg_comms_packing... 113 function Unpack( Pkt : in Raw_Types.RSA_Pkt;
smg_comms_packing... 114 K : in RSA_OAEP.RSA_skey;
smg_comms_packing... 115 Success : out Boolean)
smg_comms_packing... 116 return Raw_Types.RSA_Msg is
smg_comms_packing... 117 -- a chunk - basically input for RSA_OAEP.Decrypt
smg_comms_packing... 118 Chunk : Raw_Types.RSA_len := (others => 0);
smg_comms_packing... 119
smg_comms_packing... 120 -- intermediate result of rsa_oaep decrypt
smg_comms_packing... 121 Decr : Raw_Types.Octets( 1..Raw_Types.OAEP_MAX_LEN ) := (others => 0);
smg_comms_packing... 122 Len : Natural;
smg_comms_packing... 123 Flag : Boolean;
smg_comms_packing... 124
smg_comms_packing... 125 -- number of chunks in the packet
smg_comms_packing... 126 -- NB: there should be only FULL chunks! otherwise -> fail
smg_comms_packing... 127 N : constant Natural := Pkt'Length / Chunk'Length;
smg_comms_packing... 128
smg_comms_packing... 129 -- final resulting message content of the given RSA packet
smg_comms_packing... 130 Msg : Raw_Types.RSA_Msg := (others => 0);
smg_comms_packing... 131 begin
smg_comms_packing... 132 -- initialize Success flag
smg_comms_packing... 133 Success := True;
smg_comms_packing... 134
smg_comms_packing... 135 -- process given packet, chunk by chunk
smg_comms_packing... 136 for I in 1..N loop
smg_comms_packing... 137 -- get current chunk
smg_comms_packing... 138 Chunk := Pkt( Pkt'First + (I-1) * Chunk'Length ..
smg_comms_packing... 139 Pkt'First + I * Chunk'Length - 1 );
smg_comms_packing... 140 -- decrypt it via rsa+oaep
smg_comms_packing... 141 RSA_OAEP.Decrypt( Chunk, K, Decr, Len, Flag );
smg_comms_packing... 142 -- check result and if ok then copy it to final result at its place
smg_comms_packing... 143 -- NB: if returned length is EVER less than OAEP_MAX_LEN then -> fail!
smg_comms_packing... 144 -- the reason for above: there will be undefined bits in the output!
smg_comms_packing... 145 if Len /= Raw_Types.OAEP_MAX_LEN or (not Flag) then
smg_comms_packing... 146 Success := False;
smg_comms_packing... 147 return Msg;
smg_comms_packing... 148 else
smg_comms_packing... 149 Msg( Msg'First + (I-1) * Decr'Length ..
smg_comms_packing... 150 Msg'First + I * Decr'Length - 1 ) := Decr;
smg_comms_packing... 151 end if;
smg_comms_packing... 152 end loop;
smg_comms_packing... 153
smg_comms_packing... 154 -- return obtained message
smg_comms_packing... 155 return Msg;
smg_comms_packing... 156 end Unpack;
smg_comms_packing... 157
smg_comms_packing... 158
smg_comms_packing... 159 end Packing;