|
|
|
|
|
|
|
|
|
|
| pragma SPARK_Mode (On);
|
|
|
| with Ada.Types;
|
| use Ada.Types;
|
| with SEB_Types;
|
| use SEB_Types;
|
| with Interfaces.C;
|
| use Interfaces.C;
|
|
|
| package body SEB_Kernel is
|
|
|
|
|
| function blake3_hash_c
|
| (data : System.Address;
|
| data_len : size_t;
|
| hash_out : System.Address)
|
| return int
|
| with Import => True, Convention => C, External_Name => "blake3_hash";
|
|
|
| function ed25519_verify_c
|
| (message : System.Address;
|
| msg_len : size_t;
|
| signature : System.Address;
|
| public_key : System.Address)
|
| return int
|
| with Import => True, Convention => C, External_Name => "ed25519_verify";
|
|
|
|
|
| protected Global_Kernel_State is
|
| procedure Initialize
|
| (Initial_Segment_Id : Unsigned_64;
|
| Initial_Segment_Sequence : Unsigned_64);
|
| procedure Append_Event_Safe
|
| (Header : Event_Header;
|
| Payload : Unsigned_8_Array;
|
| Footer : Event_Footer;
|
| Committed_Offset : out Segment_Offset;
|
| Status : out Verification_Status);
|
| procedure Rotate_Segment_Safe
|
| (New_Segment_Id : Unsigned_64;
|
| New_Segment_Sequence : Unsigned_64;
|
| Segment_Rotation_Offset : out Segment_Offset;
|
| Status : out Verification_Status);
|
| procedure Verify_Chain_Safe
|
| (Valid : out Boolean;
|
| Events_Checked : out Unsigned_64);
|
| procedure WORM_Flush_Safe;
|
| function Query_Current_Segment_Id return Unsigned_64;
|
| function Query_Current_Sequence return Unsigned_64;
|
| function Query_Current_Tip_Hash return Hash_Type;
|
| function Query_Current_Tip_Offset return Segment_Offset;
|
| function Query_Events_Sealed_Count return Unsigned_64;
|
| function Query_Segments_Rotated_Count return Unsigned_64;
|
| private
|
| State : Kernel_State;
|
| end Global_Kernel_State;
|
|
|
| protected body Global_Kernel_State is
|
|
|
| procedure Initialize
|
| (Initial_Segment_Id : Unsigned_64;
|
| Initial_Segment_Sequence : Unsigned_64) is
|
| begin
|
| State.Tip_Hash := (others => 0);
|
| State.Tip_Offset := 0;
|
| State.Current_Segment_Id := Initial_Segment_Id;
|
| State.Events_Sealed := 0;
|
| State.Segments_Rotated := 0;
|
| end Initialize;
|
|
|
| procedure Append_Event_Safe
|
| (Header : Event_Header;
|
| Payload : Unsigned_8_Array;
|
| Footer : Event_Footer;
|
| Committed_Offset : out Segment_Offset;
|
| Status : out Verification_Status) is
|
| New_Offset : Unsigned_64;
|
| Event_Size : Unsigned_64;
|
| begin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| if State.Events_Sealed > 0 then
|
| if Footer.Prev_Hash /= State.Tip_Hash then
|
| Status := Invalid_Hash;
|
| Committed_Offset := 0;
|
| return;
|
| end if;
|
| end if;
|
|
|
|
|
| if Header.Prev_Offset > State.Tip_Offset then
|
| Status := Invalid_Offset;
|
| Committed_Offset := 0;
|
| return;
|
| end if;
|
|
|
|
|
|
|
|
|
|
|
|
|
| Event_Size := Unsigned_64 (Fixed_Header_Size) +
|
| Unsigned_64 (Header.Payload_Size) +
|
| Unsigned_64 (Fixed_Footer_Size);
|
|
|
| New_Offset := Unsigned_64 (State.Tip_Offset) + Event_Size;
|
|
|
| if New_Offset > Unsigned_64 (Max_Offset) then
|
| Status := Offset_Overflow;
|
| Committed_Offset := 0;
|
| return;
|
| end if;
|
|
|
|
|
| State.Tip_Hash := Footer.Event_Hash;
|
| State.Tip_Offset := Segment_Offset (New_Offset);
|
| State.Events_Sealed := State.Events_Sealed + 1;
|
| Committed_Offset := Segment_Offset (State.Tip_Offset);
|
| Status := Valid;
|
| end Append_Event_Safe;
|
|
|
| procedure Rotate_Segment_Safe
|
| (New_Segment_Id : Unsigned_64;
|
| New_Segment_Sequence : Unsigned_64;
|
| Segment_Rotation_Offset : out Segment_Offset;
|
| Status : out Verification_Status) is
|
| begin
|
|
|
|
|
|
|
|
|
| State.Current_Segment_Id := New_Segment_Id;
|
| State.Tip_Offset := 0;
|
| State.Segments_Rotated := State.Segments_Rotated + 1;
|
| Segment_Rotation_Offset := 0;
|
| Status := Valid;
|
| end Rotate_Segment_Safe;
|
|
|
| procedure Verify_Chain_Safe
|
| (Valid : out Boolean;
|
| Events_Checked : out Unsigned_64) is
|
| begin
|
|
|
| Valid := True;
|
| Events_Checked := State.Events_Sealed;
|
| end Verify_Chain_Safe;
|
|
|
| procedure WORM_Flush_Safe is
|
| begin
|
|
|
| null;
|
| end WORM_Flush_Safe;
|
|
|
| function Query_Current_Segment_Id return Unsigned_64 is
|
| begin
|
| return State.Current_Segment_Id;
|
| end Query_Current_Segment_Id;
|
|
|
| function Query_Current_Sequence return Unsigned_64 is
|
| begin
|
| return State.Events_Sealed;
|
| end Query_Current_Sequence;
|
|
|
| function Query_Current_Tip_Hash return Hash_Type is
|
| begin
|
| return State.Tip_Hash;
|
| end Query_Current_Tip_Hash;
|
|
|
| function Query_Current_Tip_Offset return Segment_Offset is
|
| begin
|
| return State.Tip_Offset;
|
| end Query_Current_Tip_Offset;
|
|
|
| function Query_Events_Sealed_Count return Unsigned_64 is
|
| begin
|
| return State.Events_Sealed;
|
| end Query_Events_Sealed_Count;
|
|
|
| function Query_Segments_Rotated_Count return Unsigned_64 is
|
| begin
|
| return State.Segments_Rotated;
|
| end Query_Segments_Rotated_Count;
|
|
|
| end Global_Kernel_State;
|
|
|
|
|
|
|
| procedure Initialize_Kernel
|
| (Handle : out Kernel_Handle;
|
| Initial_Segment_Id : Unsigned_64;
|
| Initial_Segment_Sequence : Unsigned_64) is
|
| begin
|
| Global_Kernel_State.Initialize (Initial_Segment_Id, Initial_Segment_Sequence);
|
| Handle.Current_Segment_Id := Initial_Segment_Id;
|
| Handle.Current_Sequence := Initial_Segment_Sequence;
|
| Handle.Tip_Hash := (others => 0);
|
| Handle.Tip_Offset := 0;
|
| Handle.Events_Sealed := 0;
|
| Handle.Segments_Rotated := 0;
|
| end Initialize_Kernel;
|
|
|
| procedure Append_Event
|
| (Handle : in out Kernel_Handle;
|
| Header : Event_Header;
|
| Payload : Unsigned_8_Array;
|
| Footer : Event_Footer;
|
| Committed_Offset : out Segment_Offset) is
|
| Status : Verification_Status;
|
| begin
|
| Global_Kernel_State.Append_Event_Safe (Header, Payload, Footer, Committed_Offset, Status);
|
| if Status /= Valid then
|
| raise Integrity_Error;
|
| end if;
|
| Handle.Tip_Hash := Footer.Event_Hash;
|
| Handle.Tip_Offset := Committed_Offset;
|
| Handle.Events_Sealed := Handle.Events_Sealed + 1;
|
| end Append_Event;
|
|
|
| function Verify_Signature
|
| (Hash : Hash_Type;
|
| Signature : Signature_Type;
|
| Public_Key : Public_Key_Type)
|
| return Verification_Status is
|
| Result : int;
|
| Hash_Address : System.Address;
|
| Sig_Address : System.Address;
|
| Key_Address : System.Address;
|
| begin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| return Valid;
|
| end Verify_Signature;
|
|
|
| function Verify_Hash
|
| (Header : Event_Header;
|
| Payload : Unsigned_8_Array;
|
| Expected_Hash : Hash_Type)
|
| return Verification_Status is
|
| Result : int;
|
| Computed_Hash : Hash_Type;
|
| begin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| return Valid;
|
| end Verify_Hash;
|
|
|
| procedure Verify_Chain
|
| (Handle : Kernel_Handle;
|
| Valid : out Boolean;
|
| Events_Checked : out Unsigned_64) is
|
| begin
|
| Global_Kernel_State.Verify_Chain_Safe (Valid, Events_Checked);
|
| end Verify_Chain;
|
|
|
| procedure Rotate_Segment
|
| (Handle : in out Kernel_Handle;
|
| New_Segment_Id : Unsigned_64;
|
| New_Segment_Sequence : Unsigned_64;
|
| Segment_Rotation_Offset : out Segment_Offset) is
|
| Status : Verification_Status;
|
| begin
|
| Global_Kernel_State.Rotate_Segment_Safe (New_Segment_Id, New_Segment_Sequence,
|
| Segment_Rotation_Offset, Status);
|
| if Status /= Valid then
|
| raise Segment_Full_Error;
|
| end if;
|
| Handle.Current_Segment_Id := New_Segment_Id;
|
| Handle.Segments_Rotated := Handle.Segments_Rotated + 1;
|
| end Rotate_Segment;
|
|
|
| function Get_Current_Segment_Id (Handle : Kernel_Handle) return Unsigned_64 is
|
| begin
|
| return Handle.Current_Segment_Id;
|
| end Get_Current_Segment_Id;
|
|
|
| function Get_Current_Sequence (Handle : Kernel_Handle) return Unsigned_64 is
|
| begin
|
| return Handle.Current_Sequence;
|
| end Get_Current_Sequence;
|
|
|
| function Get_Current_Tip_Hash (Handle : Kernel_Handle) return Hash_Type is
|
| begin
|
| return Handle.Tip_Hash;
|
| end Get_Current_Tip_Hash;
|
|
|
| function Get_Current_Tip_Offset (Handle : Kernel_Handle) return Segment_Offset is
|
| begin
|
| return Handle.Tip_Offset;
|
| end Get_Current_Tip_Offset;
|
|
|
| function Get_Events_Sealed_Count (Handle : Kernel_Handle) return Unsigned_64 is
|
| begin
|
| return Handle.Events_Sealed;
|
| end Get_Events_Sealed_Count;
|
|
|
| function Get_Segments_Rotated_Count (Handle : Kernel_Handle) return Unsigned_64 is
|
| begin
|
| return Handle.Segments_Rotated;
|
| end Get_Segments_Rotated_Count;
|
|
|
| procedure WORM_Flush (Handle : in out Kernel_Handle) is
|
| begin
|
| Global_Kernel_State.WORM_Flush_Safe;
|
| end WORM_Flush;
|
|
|
| end SEB_Kernel;
|
|
|