-- Implementation of TMSR's OAEP with Keccak as hash function -- NB: this uses Eulora's protocol constants (esp. RSA key length) and types. -- -- S.MG, 2018 with Keccak; -- Keccak is used as hash function with Raw_Types; -- Eulora's protocol raw types and constant values with Interfaces; use Interfaces; -- for Unsigned_8 type and bit-level ops package OAEP is pragma Pure( OAEP ); -- stateless, no side effects -> can cache calls -- constants for OAEP OAEP_LENGTH_OCTETS : constant := Raw_Types.RSA_KEY_OCTETS; OAEP_LENGTH_BITS : constant := OAEP_LENGTH_OCTETS * 8; OAEP_HALF_OCTETS : constant := OAEP_LENGTH_OCTETS / 2; TMSR_STR : constant String := "TMSR-RSA"; -- "TMSR-RSA" as unsigned_8 values: TMSR : constant Raw_Types.Octets := (84,77,83,82,45,82,83,65); MAX_LEN_MSG : constant Natural := OAEP_HALF_OCTETS - TMSR_STR'Length - 3; -- subtypes for OAEP encrypt/decrypt subtype OAEP_Block is Raw_Types.Octets( 1 .. OAEP_LENGTH_OCTETS ); subtype OAEP_HALF is Raw_Types.Octets( 1 .. OAEP_HALF_OCTETS ); -- padding & formatting of maximum MAX_LEN_MSG octets of the given input -- uses TMSR's OAEP schema: -- 1.format M00 as: [random octet][sz1][sz2]"TMSR-RSA"[random]*Message -- where sz1 and sz2 store the length of the message in bits -- the random octets before message are padding to make OAEP_LENGTH_OCTETS -- 2. R = OAEP_HALF_OCTETS random bits -- 3. X = M00 xor hash(R) -- 4. Y = R xor hash(X) -- 5. Result is X || Y -- NB: the Entropy parameter should be random octets from which this method -- will use as many as required for the OAEP encryption of given Msg -- NB: at MOST MAX_LEN_MSG octets of Msg! (Msg at most MAX_LEN_MSG*8 bits!) procedure OAEP_Encrypt( Msg : in Raw_Types.Octets; Entropy : in OAEP_Block; Output : out OAEP_Block); -- This is the opposite of OAEP_Encrypt above. -- @param Encr - an OAEP block previously obtained from OAEP_Encrypt -- @param Len - this will hold the length of the obtained message (in bits!) -- @param Output - the first Len octets of this are the recovered message -- @param Success - set to TRUE if message was recovered, false otherwise -- NB: when Success is FALSE, both Len and Output have undefined values procedure OAEP_Decrypt( Encr : in OAEP_Block; Len : out Natural; Output : out OAEP_HALF; Success : out Boolean); private -- gnat-specific methods for bit-level operations function Shift_Right( Value : Unsigned_8; Amount : Natural ) return Unsigned_8; pragma Import(Intrinsic, Shift_Right); function Shift_Left( Value : Unsigned_8; Amount : Natural ) return Unsigned_8; pragma Import(Intrinsic, Shift_Left); -- helper method: xor 2 half-oaep blocks function XOR_Octets(A : in OAEP_HALF; B : in OAEP_HALF) return OAEP_HALF; -- conversions between bitstream and string -- NB: caller has to ensure correct size of output parameter! no checks here. procedure ToOctets ( B : in Keccak.Bitstream; O : out Raw_Types.Octets ); procedure ToBitstream( O : in Raw_Types.Octets; B : out Keccak.Bitstream ); -- wrapper for Sponge to use Octets for input/output procedure HashKeccak( Input : in Raw_Types.Octets; Output : out Raw_Types.Octets; Block_Len : in Keccak.Keccak_Rate := Keccak.Default_Bitrate); end OAEP;