From caa3d0a012eb8128b42a4feb0c434991250a1abe Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Thu, 20 Nov 2025 22:50:40 +0100 Subject: [PATCH 01/51] Refactored Ada binding. Separated code that depends upon Interfaces.C.Strings and GNAT.Sockets into a child package of the WolfSSL package. --- wrapper/Ada/spark_terminal.ads | 6 +- wrapper/Ada/tls_client.adb | 14 +-- wrapper/Ada/tls_client.ads | 10 +- wrapper/Ada/tls_server.adb | 8 +- wrapper/Ada/wolfssl-full_runtime.adb | 87 ++++++++++++++++ wrapper/Ada/wolfssl-full_runtime.ads | 77 ++++++++++++++ wrapper/Ada/wolfssl.adb | 145 ++++++--------------------- wrapper/Ada/wolfssl.ads | 88 +++------------- 8 files changed, 227 insertions(+), 208 deletions(-) create mode 100644 wrapper/Ada/wolfssl-full_runtime.adb create mode 100644 wrapper/Ada/wolfssl-full_runtime.ads diff --git a/wrapper/Ada/spark_terminal.ads b/wrapper/Ada/spark_terminal.ads index 1c516ca7b3a..f664ce08282 100644 --- a/wrapper/Ada/spark_terminal.ads +++ b/wrapper/Ada/spark_terminal.ads @@ -21,9 +21,9 @@ with Ada.Command_Line; --- SPARK wrapper package around Ada.Command_Line and Interfaces.C --- packages because these packages lack contracts in their specification --- files that SPARK can use to verify the context in which +-- SPARK wrapper package around the Ada.Command_Line package +-- because this package lacks contracts in the specification +-- file that SPARK can use to verify the context in which -- subprograms can safely be called. package SPARK_Terminal with SPARK_Mode is diff --git a/wrapper/Ada/tls_client.adb b/wrapper/Ada/tls_client.adb index 4cd56c08bd0..30686ef6108 100644 --- a/wrapper/Ada/tls_client.adb +++ b/wrapper/Ada/tls_client.adb @@ -28,6 +28,8 @@ with Interfaces.C.Strings; with SPARK_Terminal; +with WolfSSL.Full_Runtime; + package body Tls_Client with SPARK_Mode is use type WolfSSL.Mode_Type; @@ -41,7 +43,7 @@ package body Tls_Client with SPARK_Mode is subtype Byte_Type is WolfSSL.Byte_Type; - subtype chars_ptr is WolfSSL.chars_ptr; + subtype chars_ptr is WolfSSL.Full_Runtime.chars_ptr; subtype unsigned is WolfSSL.unsigned; package Natural_IO is new Ada.Text_IO.Integer_IO (Natural); @@ -110,7 +112,7 @@ package body Tls_Client with SPARK_Mode is procedure Put (Number : Natural) with - Annotate => (GNATprove, Might_Not_Return) + Always_Terminates => False is begin Natural_IO.Put (Item => Number, Width => 0, Base => 10); @@ -118,7 +120,7 @@ package body Tls_Client with SPARK_Mode is procedure Put (Number : Byte_Index) with - Annotate => (GNATprove, Might_Not_Return) + Always_Terminates => False is begin Natural_IO.Put (Item => Natural (Number), Width => 0, Base => 10); @@ -348,14 +350,14 @@ package body Tls_Client with SPARK_Mode is if PSK then -- Use PSK for authentication. - WolfSSL.Set_PSK_Client_Callback + WolfSSL.Full_Runtime.Set_PSK_Client_Callback (Ssl => Ssl, Callback => PSK_Client_Callback'Access); end if; if DTLS then - Result := WolfSSL.DTLS_Set_Peer(Ssl => Ssl, - Address => A); + Result := WolfSSL.Full_Runtime.DTLS_Set_Peer(Ssl => Ssl, + Address => A); if Result /= Success then Put_Line ("ERROR: Failed to set the DTLS peer."); SPARK_Sockets.Close_Socket (C); diff --git a/wrapper/Ada/tls_client.ads b/wrapper/Ada/tls_client.ads index aa1ad36e01a..1d5525eaea8 100644 --- a/wrapper/Ada/tls_client.ads +++ b/wrapper/Ada/tls_client.ads @@ -29,10 +29,10 @@ package Tls_Client with SPARK_Mode is procedure Run (Ssl : in out WolfSSL.WolfSSL_Type; Ctx : in out WolfSSL.Context_Type; Client : in out SPARK_Sockets.Optional_Socket) with - Pre => (not Client.Exists and not - WolfSSL.Is_Valid (Ssl) and not WolfSSL.Is_Valid (Ctx)), - Post => (not Client.Exists and not WolfSSL.Is_Valid (Ssl) and - not WolfSSL.Is_Valid (Ctx)), - Annotate => (GNATprove, Might_Not_Return); + Pre => (not Client.Exists and not + WolfSSL.Is_Valid (Ssl) and not WolfSSL.Is_Valid (Ctx)), + Post => (not Client.Exists and not WolfSSL.Is_Valid (Ssl) and + not WolfSSL.Is_Valid (Ctx)), + Always_Terminates => False; end Tls_Client; diff --git a/wrapper/Ada/tls_server.adb b/wrapper/Ada/tls_server.adb index 64e4f988d1e..beebd685171 100644 --- a/wrapper/Ada/tls_server.adb +++ b/wrapper/Ada/tls_server.adb @@ -28,6 +28,8 @@ with Interfaces.C.Strings; with SPARK_Terminal; pragma Elaborate_All (SPARK_Terminal); +with WolfSSL.Full_Runtime; + package body Tls_Server with SPARK_Mode is use type WolfSSL.Mode_Type; @@ -37,7 +39,7 @@ package body Tls_Server with SPARK_Mode is Success : WolfSSL.Subprogram_Result renames WolfSSL.Success; - subtype chars_ptr is WolfSSL.chars_ptr; + subtype chars_ptr is WolfSSL.Full_Runtime.chars_ptr; subtype unsigned is WolfSSL.unsigned; procedure Put (Char : Character) is @@ -158,7 +160,7 @@ package body Tls_Server with SPARK_Mode is Ch : Character; Result : WolfSSL.Subprogram_Result; - DTLS, PSK : Boolean := True; + DTLS, PSK : Boolean := False; Shall_Continue : Boolean := True; Input : WolfSSL.Read_Result; @@ -318,7 +320,7 @@ package body Tls_Server with SPARK_Mode is if PSK then -- Use PSK for authentication. - WolfSSL.Set_Context_PSK_Server_Callback + WolfSSL.Full_Runtime.Set_Context_PSK_Server_Callback (Context => Ctx, Callback => PSK_Server_Callback'Access); end if; diff --git a/wrapper/Ada/wolfssl-full_runtime.adb b/wrapper/Ada/wolfssl-full_runtime.adb new file mode 100644 index 00000000000..4e88f3a008f --- /dev/null +++ b/wrapper/Ada/wolfssl-full_runtime.adb @@ -0,0 +1,87 @@ +pragma Warnings (Off, "* is an internal GNAT unit"); +with GNAT.Sockets.Thin_Common; +pragma Warnings (On, "* is an internal GNAT unit"); + +package body WolfSSL.Full_Runtime is + + function WolfSSL_DTLS_Set_Peer + (ssl : WolfSSL_Type; + peer : GNAT.Sockets.Thin_Common.Sockaddr_Access; + peerSz : Interfaces.C.unsigned) + return int with + Convention => C, + External_Name => "wolfSSL_dtls_set_peer", + Import => True; + + function DTLS_Set_Peer + (Ssl : WolfSSL_Type; + Address : GNAT.Sockets.Sock_Addr_Type) + return Subprogram_Result is + + Sin : aliased GNAT.Sockets.Thin_Common.Sockaddr; + Length : Interfaces.C.int; + + begin + + GNAT.Sockets.Thin_Common.Set_Address + (Sin => Sin'Unchecked_Access, + Address => Address, + Length => Length); + + pragma Assert (Length >= 0); + + return + Subprogram_Result + (WolfSSL_DTLS_Set_Peer + (ssl => Ssl, + peer => Sin'Unchecked_Access, + peerSz => Interfaces.C.unsigned (Length))); + + end DTLS_Set_Peer; + + procedure WolfSSL_Set_Psk_Client_Callback + (Ssl : WolfSSL_Type; + Cb : PSK_Client_Callback) + with + Convention => C, + External_Name => "wolfSSL_set_psk_client_callback", + Import => True; + + procedure Set_PSK_Client_Callback + (Ssl : WolfSSL_Type; + Callback : PSK_Client_Callback) is + begin + WolfSSL_Set_Psk_Client_Callback (Ssl, Callback); + end Set_PSK_Client_Callback; + + procedure WolfSSL_Set_Psk_Server_Callback + (Ssl : WolfSSL_Type; + Cb : PSK_Server_Callback) + with + Convention => C, + External_Name => "wolfSSL_set_psk_server_callback", + Import => True; + + procedure Set_PSK_Server_Callback + (Ssl : WolfSSL_Type; + Callback : PSK_Server_Callback) is + begin + WolfSSL_Set_Psk_Server_Callback (Ssl, Callback); + end Set_PSK_Server_Callback; + + procedure WolfSSL_CTX_Set_Psk_Server_Callback + (Ctx : Context_Type; + Cb : PSK_Server_Callback) + with + Convention => C, + External_Name => "wolfSSL_CTX_set_psk_server_callback", + Import => True; + + procedure Set_Context_PSK_Server_Callback + (Context : Context_Type; + Callback : PSK_Server_Callback) is + begin + WolfSSL_CTX_Set_Psk_Server_Callback (Context, Callback); + end Set_Context_PSK_Server_Callback; + +end WolfSSL.Full_Runtime; diff --git a/wrapper/Ada/wolfssl-full_runtime.ads b/wrapper/Ada/wolfssl-full_runtime.ads new file mode 100644 index 00000000000..c6b3e650ba8 --- /dev/null +++ b/wrapper/Ada/wolfssl-full_runtime.ads @@ -0,0 +1,77 @@ +with GNAT.Sockets; +with Interfaces.C.Strings; + +-- This package contains the subprograms that need the Ada run-time +-- to support the Interfaces.C.Strings and GNAT.Sockets packages. +-- An example of an Ada run-time that does not support this package +-- is the Zero Footprint run-time of the GNAT compiler. +package WolfSSL.Full_Runtime with SPARK_Mode is + + function DTLS_Set_Peer + (Ssl : WolfSSL_Type; + Address : GNAT.Sockets.Sock_Addr_Type) + return Subprogram_Result with + Pre => Is_Valid (Ssl); + -- This function wraps the corresponding WolfSSL C function to allow + -- clients to use Ada socket types when implementing a DTLS client. + + subtype chars_ptr is Interfaces.C.Strings.chars_ptr; + + type PSK_Client_Callback is access function + (Ssl : WolfSSL_Type; + Hint : chars_ptr; + Identity : chars_ptr; + Id_Max_Length : unsigned; + Key : chars_ptr; + Key_Max_Length : unsigned) + return unsigned with + Convention => C; + -- Return value is the key length on success or zero on error. + -- parameters: + -- Ssl - Pointer to the wolfSSL structure + -- Hint - A stored string that could be displayed to provide a + -- hint to the user. + -- Identity - The ID will be stored here. + -- Id_Max_Length - Size of the ID buffer. + -- Key - The key will be stored here. + -- Key_Max_Length - The max size of the key. + -- + -- The implementation of this callback will need `SPARK_Mode => Off` + -- since it will require the code to use the C memory model. + + procedure Set_PSK_Client_Callback + (Ssl : WolfSSL_Type; + Callback : PSK_Client_Callback) with + Pre => Is_Valid (Ssl); + -- Sets the PSK client side callback. + + type PSK_Server_Callback is access function + (Ssl : WolfSSL_Type; + Identity : chars_ptr; + Key : chars_ptr; + Key_Max_Length : unsigned) + return unsigned with + Convention => C; + -- Return value is the key length on success or zero on error. + -- PSK server callback parameters: + -- Ssl - Reference to the wolfSSL structure + -- Identity - The ID will be stored here. + -- Key - The key will be stored here. + -- Key_Max_Length - The max size of the key. + -- + -- The implementation of this callback will need `SPARK_Mode => Off` + -- since it will require the code to use the C memory model. + + procedure Set_PSK_Server_Callback + (Ssl : WolfSSL_Type; + Callback : PSK_Server_Callback) with + Pre => Is_Valid (Ssl); + -- Sets the PSK Server side callback. + + procedure Set_Context_PSK_Server_Callback + (Context : Context_Type; + Callback : PSK_Server_Callback) with + Pre => Is_Valid (Context); + -- Sets the PSK callback for the server side in the WolfSSL Context. + +end WolfSSL.Full_Runtime; diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index 2f7caba0b01..a517c1f16e8 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -1,6 +1,6 @@ -- wolfssl.adb -- --- Copyright (C) 2006-2023 wolfSSL Inc. +-- Copyright (C) 2006-2025 wolfSSL Inc. -- -- This file is part of wolfSSL. -- @@ -20,12 +20,7 @@ -- with Ada.Unchecked_Conversion; -pragma Warnings (Off, "* is an internal GNAT unit"); -with GNAT.Sockets.Thin_Common; -pragma Warnings (On, "* is an internal GNAT unit"); -with Interfaces.C.Extensions; with Interfaces.C.Strings; -with System; package body WolfSSL is @@ -231,7 +226,7 @@ package body WolfSSL is end Get_Verify; function Use_Certificate_File (Context : Context_Type; - File : char_array; + File : Byte_Array; Format : int) return int with Convention => C, @@ -244,7 +239,7 @@ package body WolfSSL is return Subprogram_Result is Ctx : constant Context_Type := Context; C : size_t; - F : char_array (1 .. File'Length + 1); + F : Byte_Array (1 .. File'Length + 1); Result : int; begin Interfaces.C.To_C (Item => File, @@ -256,7 +251,7 @@ package body WolfSSL is end Use_Certificate_File; function Use_Certificate_Buffer (Context : Context_Type; - Input : char_array; + Input : Byte_Array; Size : long; Format : int) return int with @@ -265,7 +260,7 @@ package body WolfSSL is Import => True; function Use_Certificate_Buffer (Context : Context_Type; - Input : char_array; + Input : Byte_Array; Format : File_Format) return Subprogram_Result is Result : int; @@ -276,7 +271,7 @@ package body WolfSSL is end Use_Certificate_Buffer; function Use_Private_Key_File (Context : Context_Type; - File : char_array; + File : Byte_Array; Format : int) return int with Convention => C, @@ -289,7 +284,7 @@ package body WolfSSL is return Subprogram_Result is Ctx : constant Context_Type := Context; C : size_t; - F : char_array (1 .. File'Length + 1); + F : Byte_Array (1 .. File'Length + 1); Result : int; begin Interfaces.C.To_C (Item => File, @@ -301,7 +296,7 @@ package body WolfSSL is end Use_Private_Key_File; function Use_Private_Key_Buffer (Context : Context_Type; - Input : char_array; + Input : Byte_Array; Size : long; Format : int) return int with @@ -322,8 +317,8 @@ package body WolfSSL is function Load_Verify_Locations1 (Context : Context_Type; - File : char_array; - Path : char_array) return int with + File : Byte_Array; + Path : Byte_Array) return int with Convention => C, External_Name => "wolfSSL_CTX_load_verify_locations", Import => True; @@ -343,28 +338,26 @@ package body WolfSSL is -- attempt to load all files in the directory. This function expects -- PEM formatted CERT_TYPE file with header "--BEGIN CERTIFICATE--". - subtype char_array_ptr is Interfaces.C.Strings.char_array_access; - function Load_Verify_Locations2 (Context : Context_Type; - File : char_array; - Path : char_array_ptr) return int with + File : Byte_Array; + Path : access Interfaces.C.char) return int with Convention => C, External_Name => "wolfSSL_CTX_load_verify_locations", Import => True; function Load_Verify_Locations3 (Context : Context_Type; - File : char_array_ptr; - Path : char_array) return int with + File : access Interfaces.C.char; + Path : Byte_Array) return int with Convention => C, External_Name => "wolfSSL_CTX_load_verify_locations", Import => True; function Load_Verify_Locations4 (Context : Context_Type; - File : char_array_ptr; - Path : char_array_ptr) return int with + File : access Interfaces.C.char; + Path : access Interfaces.C.char) return int with Convention => C, External_Name => "wolfSSL_CTX_load_verify_locations", Import => True; @@ -375,10 +368,10 @@ package body WolfSSL is return Subprogram_Result is Ctx : constant Context_Type := Context; FC : size_t; -- File Count, specifies the characters used in F. - F : aliased char_array := (1 .. File'Length + 1 => '#'); + F : aliased Byte_Array := (1 .. File'Length + 1 => '#'); PC : size_t; -- Path Count, specifies the characters used in P. - P : aliased char_array := (1 .. Path'Length + 1 => '#'); + P : aliased Byte_Array := (1 .. Path'Length + 1 => '#'); Result : int; begin @@ -418,7 +411,7 @@ package body WolfSSL is function Load_Verify_Buffer (Context : Context_Type; - Input : char_array; + Input : Byte_Array; Size : int; Format : int) return int with Convention => C, @@ -456,7 +449,7 @@ package body WolfSSL is end Create_WolfSSL; function Use_Certificate_File (Ssl : WolfSSL_Type; - File : char_array; + File : Byte_Array; Format : int) return int with Convention => C, @@ -468,7 +461,7 @@ package body WolfSSL is Format : File_Format) return Subprogram_Result is C : size_t; - F : char_array (1 .. File'Length + 1); + F : Byte_Array (1 .. File'Length + 1); Result : int; begin Interfaces.C.To_C (Item => File, @@ -480,7 +473,7 @@ package body WolfSSL is end Use_Certificate_File; function Use_Certificate_Buffer (Ssl : WolfSSL_Type; - Input : char_array; + Input : Byte_Array; Size : long; Format : int) return int with @@ -489,7 +482,7 @@ package body WolfSSL is Import => True; function Use_Certificate_Buffer (Ssl : WolfSSL_Type; - Input : char_array; + Input : Byte_Array; Format : File_Format) return Subprogram_Result is Result : int; @@ -500,7 +493,7 @@ package body WolfSSL is end Use_Certificate_Buffer; function Use_Private_Key_File (Ssl : WolfSSL_Type; - File : char_array; + File : Byte_Array; Format : int) return int with Convention => C, @@ -512,7 +505,7 @@ package body WolfSSL is Format : File_Format) return Subprogram_Result is C : size_t; - F : char_array (1 .. File'Length + 1); + F : Byte_Array (1 .. File'Length + 1); Result : int; begin Interfaces.C.To_C (Item => File, @@ -524,7 +517,7 @@ package body WolfSSL is end Use_Private_Key_File; function Use_Private_Key_Buffer (Ssl : WolfSSL_Type; - Input : char_array; + Input : Byte_Array; Size : long; Format : int) return int with @@ -543,86 +536,6 @@ package body WolfSSL is return Subprogram_Result (Result); end Use_Private_Key_Buffer; - function WolfSSL_DTLS_Set_Peer - (ssl : WolfSSL_Type; - peer : GNAT.Sockets.Thin_Common.Sockaddr_Access; - peerSz : Interfaces.C.unsigned) - return int with - Convention => C, - External_Name => "wolfSSL_dtls_set_peer", - Import => True; - - function DTLS_Set_Peer - (Ssl : WolfSSL_Type; - Address : GNAT.Sockets.Sock_Addr_Type) - return Subprogram_Result is - - Sin : aliased GNAT.Sockets.Thin_Common.Sockaddr; - Length : Interfaces.C.int; - - begin - - GNAT.Sockets.Thin_Common.Set_Address - (Sin => Sin'Unchecked_Access, - Address => Address, - Length => Length); - - pragma Assert (Length >= 0); - - return - Subprogram_Result - (WolfSSL_DTLS_Set_Peer - (ssl => Ssl, - peer => Sin'Unchecked_Access, - peerSz => Interfaces.C.unsigned (Length))); - - end DTLS_Set_Peer; - - procedure WolfSSL_Set_Psk_Client_Callback - (Ssl : WolfSSL_Type; - Cb : PSK_Client_Callback) - with - Convention => C, - External_Name => "wolfSSL_set_psk_client_callback", - Import => True; - - procedure Set_PSK_Client_Callback - (Ssl : WolfSSL_Type; - Callback : PSK_Client_Callback) is - begin - WolfSSL_Set_Psk_Client_Callback (Ssl, Callback); - end Set_PSK_Client_Callback; - - procedure WolfSSL_Set_Psk_Server_Callback - (Ssl : WolfSSL_Type; - Cb : PSK_Server_Callback) - with - Convention => C, - External_Name => "wolfSSL_set_psk_server_callback", - Import => True; - - procedure Set_PSK_Server_Callback - (Ssl : WolfSSL_Type; - Callback : PSK_Server_Callback) is - begin - WolfSSL_Set_Psk_Server_Callback (Ssl, Callback); - end Set_PSK_Server_Callback; - - procedure WolfSSL_CTX_Set_Psk_Server_Callback - (Ctx : Context_Type; - Cb : PSK_Server_Callback) - with - Convention => C, - External_Name => "wolfSSL_CTX_set_psk_server_callback", - Import => True; - - procedure Set_Context_PSK_Server_Callback - (Context : Context_Type; - Callback : PSK_Server_Callback) is - begin - WolfSSL_CTX_Set_Psk_Server_Callback (Context, Callback); - end Set_Context_PSK_Server_Callback; - function WolfSSL_Set_Fd (Ssl : WolfSSL_Type; Fd : int) return int with Convention => C, External_Name => "wolfSSL_set_fd", @@ -669,7 +582,7 @@ package body WolfSSL is end Free_Arrays; function WolfSSL_Read (Ssl : WolfSSL_Type; - Data : out char_array; + Data : out Byte_Array; Sz : int) return int with Convention => C, External_Name => "wolfSSL_read", @@ -705,7 +618,7 @@ package body WolfSSL is -- Use wolfSSL_get_error() to get a specific error code. function Read (Ssl : WolfSSL_Type) return Read_Result is - Data : char_array (1 .. Byte_Index'Last); + Data : Byte_Array (1 .. Byte_Index'Last); Size : int; begin Size := WolfSSL_Read (Ssl, Data, int (Byte_Index'Last)); @@ -721,7 +634,7 @@ package body WolfSSL is end Read; function WolfSSL_Write (Ssl : WolfSSL_Type; - Data : char_array; + Data : Byte_Array; Sz : int) return int with Convention => C, External_Name => "wolfSSL_write", diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 2a247a676cc..ecca3f9ef4b 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -1,6 +1,6 @@ -- wolfssl.ads -- --- Copyright (C) 2006-2023 wolfSSL Inc. +-- Copyright (C) 2006-2025 wolfSSL Inc. -- -- This file is part of wolfSSL. -- @@ -19,8 +19,7 @@ -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA -- -with GNAT.Sockets; -with Interfaces.C.Strings; +with Interfaces.C; -- This package is annotated "with SPARK_Mode" that SPARK can verify -- the API of this package is used correctly. @@ -40,10 +39,7 @@ package WolfSSL with SPARK_Mode is -- used by the library. subtype unsigned is Interfaces.C.unsigned; - - subtype char_array is Interfaces.C.char_array; -- Remove? - subtype chars_ptr is Interfaces.C.Strings.chars_ptr; - + subtype Byte_Type is Interfaces.C.char; subtype Byte_Index is Interfaces.C.size_t range 0 .. 16_000; subtype Byte_Array is Interfaces.C.char_array; @@ -165,7 +161,7 @@ package WolfSSL with SPARK_Mode is -- PEM file types. Please see the examples for proper usage. function Use_Certificate_Buffer (Context : Context_Type; - Input : char_array; + Input : Byte_Array; Format : File_Format) return Subprogram_Result with Pre => Is_Valid (Context); @@ -260,7 +256,7 @@ package WolfSSL with SPARK_Mode is -- either ASN1 or PEM. function Use_Certificate_Buffer (Ssl : WolfSSL_Type; - Input : char_array; + Input : Byte_Array; Format : File_Format) return Subprogram_Result with Pre => Is_Valid (Ssl); @@ -291,72 +287,6 @@ package WolfSSL with SPARK_Mode is -- of a file. The buffer is provided by the Input argument. -- Format specifies the format type of the buffer; ASN1 or PEM. -- Please see the examples for proper usage. - - function DTLS_Set_Peer - (Ssl : WolfSSL_Type; - Address : GNAT.Sockets.Sock_Addr_Type) - return Subprogram_Result with - Pre => Is_Valid (Ssl); - -- This function wraps the corresponding WolfSSL C function to allow - -- clients to use Ada socket types when implementing a DTLS client. - - type PSK_Client_Callback is access function - (Ssl : WolfSSL_Type; - Hint : chars_ptr; - Identity : chars_ptr; - Id_Max_Length : unsigned; - Key : chars_ptr; - Key_Max_Length : unsigned) - return unsigned with - Convention => C; - -- Return value is the key length on success or zero on error. - -- parameters: - -- Ssl - Pointer to the wolfSSL structure - -- Hint - A stored string that could be displayed to provide a - -- hint to the user. - -- Identity - The ID will be stored here. - -- Id_Max_Length - Size of the ID buffer. - -- Key - The key will be stored here. - -- Key_Max_Length - The max size of the key. - -- - -- The implementation of this callback will need `SPARK_Mode => Off` - -- since it will require the code to use the C memory model. - - procedure Set_PSK_Client_Callback - (Ssl : WolfSSL_Type; - Callback : PSK_Client_Callback) with - Pre => Is_Valid (Ssl); - -- Sets the PSK client side callback. - - - type PSK_Server_Callback is access function - (Ssl : WolfSSL_Type; - Identity : chars_ptr; - Key : chars_ptr; - Key_Max_Length : unsigned) - return unsigned with - Convention => C; - -- Return value is the key length on success or zero on error. - -- PSK server callback parameters: - -- Ssl - Reference to the wolfSSL structure - -- Identity - The ID will be stored here. - -- Key - The key will be stored here. - -- Key_Max_Length - The max size of the key. - -- - -- The implementation of this callback will need `SPARK_Mode => Off` - -- since it will require the code to use the C memory model. - - procedure Set_PSK_Server_Callback - (Ssl : WolfSSL_Type; - Callback : PSK_Server_Callback) with - Pre => Is_Valid (Ssl); - -- Sets the PSK Server side callback. - - procedure Set_Context_PSK_Server_Callback - (Context : Context_Type; - Callback : PSK_Server_Callback) with - Pre => Is_Valid (Context); - -- Sets the PSK callback for the server side in the WolfSSL Context. function Attach (Ssl : WolfSSL_Type; Socket : Integer) @@ -557,6 +487,14 @@ package WolfSSL with SPARK_Mode is private pragma SPARK_Mode (Off); + type chars_ptr is access all Character; + pragma Convention (C, chars_ptr); + + pragma No_Strict_Aliasing (chars_ptr); + -- Since this type is used for external interfacing, with the pointer + -- coming from who knows where, it seems a good idea to turn off any + -- strict aliasing assumptions for this type. + subtype int is Interfaces.C.int; use type int; type Opaque_Method is limited null record; From 053bfaaa513c937f8c99c6d681f4a9c6120180c8 Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Tue, 2 Dec 2025 22:04:16 +0100 Subject: [PATCH 02/51] Added Ada binding for the SHA256 implementation in the Wolfssl library. --- wrapper/Ada/ada_binding.c | 36 +++++++++ wrapper/Ada/examples.gpr | 4 +- wrapper/Ada/sha256_main.adb | 43 +++++++++++ wrapper/Ada/wolfssl.adb | 150 ++++++++++++++++++++++++++++++++++++ wrapper/Ada/wolfssl.ads | 46 +++++++++++ 5 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 wrapper/Ada/sha256_main.adb diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index 19ed080b19d..d4ad911b451 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -26,6 +26,11 @@ /* wolfSSL */ #include #include +#include +#include + +#define WOLFSSL_RSA_INSTANCES 2 +#define WOLFSSL_SHA256_INSTANCES 2 /* These functions give access to the integer values of the enumeration constants used in WolfSSL. These functions make it possible @@ -48,6 +53,12 @@ extern int get_wolfssl_filetype_asn1(void); extern int get_wolfssl_filetype_pem(void); extern int get_wolfssl_filetype_default(void); +extern int get_wolfssl_rsa_instances(void); +extern int ada_RsaPublicKeyDecode(const byte *input, word32 *inOutIdx, + uint32_t key, word32 inSz); + +extern void* ada_new_sha256 (int index); + extern int get_wolfssl_error_want_read(void) { return WOLFSSL_ERROR_WANT_READ; } @@ -107,3 +118,28 @@ extern int get_wolfssl_filetype_pem(void) { extern int get_wolfssl_filetype_default(void) { return WOLFSSL_FILETYPE_DEFAULT; } + +extern int get_wolfssl_rsa_instances(void) { + return WOLFSSL_RSA_INSTANCES; +} + +RsaKey preAllocatedRSAKeys[WOLFSSL_RSA_INSTANCES]; + +extern int +ada_RsaPublicKeyDecode(const byte *input, word32 *inOutIdx, + uint32_t key, word32 inSz) +{ + return wc_RsaPublicKeyDecode (input, inOutIdx, + &preAllocatedRSAKeys[key], inSz); +} + +wc_Sha256 preAllocatedSHA256[WOLFSSL_SHA256_INSTANCES]; + +extern void* ada_new_sha256 (int index) +{ + return &preAllocatedSHA256[index]; +} + +extern int get_wolfssl_sha256_instances(void) { + return WOLFSSL_SHA256_INSTANCES; +} diff --git a/wrapper/Ada/examples.gpr b/wrapper/Ada/examples.gpr index 218f93e51ed..35e0c46fba1 100644 --- a/wrapper/Ada/examples.gpr +++ b/wrapper/Ada/examples.gpr @@ -12,7 +12,9 @@ project Examples is for Object_Dir use "obj"; - for Main use ("tls_server_main.adb", "tls_client_main.adb"); + for Main use ("tls_server_main.adb", + "tls_client_main.adb", + "sha256_main.adb"); package Naming is for Spec_Suffix ("C") use ".h"; diff --git a/wrapper/Ada/sha256_main.adb b/wrapper/Ada/sha256_main.adb new file mode 100644 index 00000000000..56dffce79cc --- /dev/null +++ b/wrapper/Ada/sha256_main.adb @@ -0,0 +1,43 @@ +with Ada.Text_IO; +with WolfSSL; + +procedure SHA256_Main is + procedure Put (Text : String) renames Ada.Text_IO.Put; + + procedure New_Line is + begin + Ada.Text_IO.New_Line; + end New_Line; + + use type WolfSSL.Subprogram_Result; + + B : WolfSSL.Byte_Array := (1 => 'a', + 2 => 's', + 3 => 'd', + 4 => 'f'); + SHA256 : WolfSSL.SHA256_Type; + R : Integer; + S : WolfSSL.SHA256_As_String; +begin + WolfSSL.Create_SHA256 (Index => 1, SHA256 => SHA256, Result => R); + if R /= 0 then + Put ("SHA256 instance creation failed"); + New_Line; + return; + end if; + WolfSSL.Update_SHA256 (SHA256 => SHA256, Byte => B, Result => R); + if R /= 0 then + Put ("Update of SHA256 instance failed"); + New_Line; + return; + end if; + WolfSSL.Finalize_SHA256 (SHA256 => SHA256, Hash => S, Result => R); + if R = 0 then + Put (S); + New_Line; + else + Put ("Finalization of SHA256 instance failed"); + New_Line; + return; + end if; +end SHA256_Main; diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index a517c1f16e8..d6e35d3705f 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -21,6 +21,7 @@ with Ada.Unchecked_Conversion; with Interfaces.C.Strings; +with WolfSSL; package body WolfSSL is @@ -739,4 +740,153 @@ package body WolfSSL is return Natural (Get_WolfSSL_Max_Error_Size); end Max_Error_Size; + function Ada_RSA_Public_Key_Decode (Input : Byte_Array; + Index : in out Integer; + Key : RSA_Key_Index; + Size : Integer) return int with + Convention => C, + External_Name => "ada_RsaPublicKeyDecode", + Import => True; + + procedure Rsa_Public_Key_Decode (Input : Byte_Array; + Index : in out Integer; + Key : RSA_Key_Index; + Size : Integer; + Result : out Subprogram_Result) is + R : constant int := Ada_RSA_Public_Key_Decode (Input, Index, Key, Size); + begin + Result := Subprogram_Result (R); + end Rsa_Public_Key_Decode; + + function Init_SHA256 (SHA256 : not null Sha256_Type) return int with + Convention => C, + External_Name => "wc_InitSha256", + Import => True; + + function SHA256_Update (SHA256 : not null Sha256_Type; + Byte : Byte_Array; + Length : int) return int with + Convention => C, + External_Name => "wc_Sha256Update", + Import => True; + + function SHA256_Final (SHA256 : not null Sha256_Type; + Hash : out Byte_Array) return int with + Convention => C, + External_Name => "wc_Sha256Final", + Import => True; + + function Is_Valid (SHA256 : SHA256_Type) return Boolean is + begin + return SHA256 /= null; + end Is_Valid; + + function Ada_New_SHA256 (Index : SHA256_Index) + return SHA256_Type with + Convention => C, + External_Name => "ada_new_sha256", + Import => True; + + procedure Create_SHA256 (Index : SHA256_Index; + SHA256 : in out SHA256_Type; + Result : out Integer) is + R : int; + begin + SHA256 := Ada_New_SHA256 (Index); + R := Init_SHA256 (SHA256); + Result := Integer (R); + end Create_SHA256; + + procedure Update_SHA256 (SHA256 : in out SHA256_Type; + Byte : Byte_Array; + Result : out Integer) is + R : int; + begin + R := SHA256_Update (SHA256, Byte, Byte'Length); + Result := Integer (R); + end Update_SHA256; + + procedure Finalize_SHA256 (SHA256 : in out SHA256_Type; + Hash : out SHA256_As_String; + Result : out Integer) is + subtype Unsigned_8 is Interfaces.Unsigned_8; + + use type Unsigned_8; + + R : int; + H : Byte_Array (1 .. 32) := (others => '#'); + Hex_Chars : constant array (Unsigned_8 range 0 .. 15) of Character := + "0123456789ABCDEF"; + I : Integer; + C : Integer; + begin + R := SHA256_Final (SHA256, H); + Result := Integer (R); + for Index in Positive range 1 .. 32 loop + I := 2 * (Index - 1) + 1; + C := Interfaces.C.char'Pos (H (size_t (Index))); + Hash (I+0) := Hex_Chars ((Unsigned_8 (C) and 16#F0#) / 16); + Hash (I+1) := Hex_Chars (Unsigned_8 (C) and 16#0F#); + end loop; + end Finalize_SHA256; + + type Opaque_AES is limited null record; + type AES_Type is access Opaque_AES with Convention => C; + + function AES_Init (AES : not null AES_Type; + Heap : access Byte_Type; + Device : int) return int with + Convention => C, + External_Name => "wc_AesInit", + Import => True; + + function AES_Set_Key (AES : not null AES_Type; + Key : Byte_Array; + Length : int; + IV : Byte_Array; + Dir : int) return int with + Convention => C, + External_Name => "wc_AesSetKey", + Import => True; + + function AES_Set_IV (AES : not null AES_Type; + IV : Byte_Array) return int with + Convention => C, + External_Name => "wc_AesSetIV", + Import => True; + + function AES_Set_Cbc_Encrypt (AES : not null AES_Type; + Output : out Byte_Array; + Input : Byte_Array; + Size : int) return int with + Convention => C, + External_Name => "wc_AesCbcEncrypt", + Import => True; + + function AES_Set_Cbc_Decrypt (AES : not null AES_Type; + Output : out Byte_Array; + Input : Byte_Array; + Size : int) return int with + Convention => C, + External_Name => "wc_AesCbcDecrypt", + Import => True; + + function AES_Free (AES : not null AES_Type) return int with + Convention => C, + External_Name => "wc_AesFree", + Import => True; + + function Get_WolfSSL_RSA_Instances return int with + Convention => C, + External_Name => "get_wolfssl_rsa_instances", + Import => True; + + function Get_WolfSSL_SHA256_Instances return int with + Convention => C, + External_Name => "get_wolfssl_sha256_instances", + Import => True; + +begin + pragma Assert (RSA_INSTANCES = Get_WolfSSL_RSA_Instances); + pragma Assert (SHA256_INSTANCES = Get_WolfSSL_SHA256_Instances); end WolfSSL; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index ecca3f9ef4b..33bd1ed2a83 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -484,6 +484,49 @@ package WolfSSL with SPARK_Mode is -- Returns the value of the defined MAX_ERROR_SZ integer -- in wolfssl/wolfcrypt/error.h. + RSA_INSTANCES : constant := 2; + + type RSA_Key_Index is range 0 .. RSA_INSTANCES - 1; + + procedure Rsa_Public_Key_Decode (Input : Byte_Array; + Index : in out Integer; + Key : RSA_Key_Index; + Size : Integer; + Result : out Subprogram_Result); + -- This function parses a DER-formatted RSA public key, + -- extracts the public key and stores it in the RsaKey structure + -- specified by the Key input argument. It also sets the distance + -- parsed in Index. + + SHA256_INSTANCES : constant := 2; + + type SHA256_Index is range 0 .. SHA256_INSTANCES - 1; + + type SHA256_Type is limited private; + + function Is_Valid (SHA256 : SHA256_Type) return Boolean; + -- Indicates if the SHA256 has successfully been initialized. + + procedure Create_SHA256 (Index : SHA256_Index; + SHA256 : in out SHA256_Type; + Result : out Integer) with + Pre => not Is_Valid (SHA256); + -- If successful Is_Valid (SSHA256) = True, and Result = 0. + + procedure Update_SHA256 (SHA256 : in out SHA256_Type; + Byte : Byte_Array; + Result : out Integer) with + Pre => Is_Valid (SHA256); + -- If successful Result = 0. + + subtype SHA256_As_String is String (1 .. 64); + + procedure Finalize_SHA256 (SHA256 : in out SHA256_Type; + Hash : out SHA256_As_String; + Result : out Integer) with + Pre => Is_Valid (SHA256); + -- If successful Result = 0. + private pragma SPARK_Mode (Off); @@ -629,4 +672,7 @@ private Error_Want_Write : constant Error_Code := Error_Code (Get_WolfSSL_Error_Want_Write); + type Opaque_Sha256 is limited null record; + type SHA256_Type is access Opaque_Sha256 with Convention => C; + end WolfSSL; From e25db30cfb92ff5400971461ec8d175e9e1b79be Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Sun, 7 Dec 2025 18:00:54 +0100 Subject: [PATCH 03/51] Saving work in progress on RSA signature verification. --- wrapper/Ada/ada_binding.c | 33 ++- wrapper/Ada/default.gpr | 4 +- wrapper/Ada/examples.gpr | 3 +- wrapper/Ada/rsa_verify_main.adb | 226 +++++++++++++++++ wrapper/Ada/sha256_main.adb | 8 +- wrapper/Ada/wolfssl.adb | 434 +++++++++++++++++++++++--------- wrapper/Ada/wolfssl.ads | 95 ++++++- 7 files changed, 658 insertions(+), 145 deletions(-) create mode 100644 wrapper/Ada/rsa_verify_main.adb diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index d4ad911b451..dba03f9e626 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -28,9 +28,11 @@ #include #include #include +#include -#define WOLFSSL_RSA_INSTANCES 2 +#define WOLFSSL_RSA_INSTANCES 2 #define WOLFSSL_SHA256_INSTANCES 2 +#define WOLFSSL_AES_INSTANCES 2 /* These functions give access to the integer values of the enumeration constants used in WolfSSL. These functions make it possible @@ -53,11 +55,14 @@ extern int get_wolfssl_filetype_asn1(void); extern int get_wolfssl_filetype_pem(void); extern int get_wolfssl_filetype_default(void); -extern int get_wolfssl_rsa_instances(void); -extern int ada_RsaPublicKeyDecode(const byte *input, word32 *inOutIdx, - uint32_t key, word32 inSz); +extern int get_wolfssl_rsa_instances (void); +extern void* ada_new_rsa (int index); -extern void* ada_new_sha256 (int index); +extern void *ada_new_sha256 (int index); +extern int get_wolfssl_sha256_instances(void); + +extern void* ada_new_aes (int index); +extern int get_wolfssl_aes_instances(void); extern int get_wolfssl_error_want_read(void) { return WOLFSSL_ERROR_WANT_READ; @@ -125,12 +130,9 @@ extern int get_wolfssl_rsa_instances(void) { RsaKey preAllocatedRSAKeys[WOLFSSL_RSA_INSTANCES]; -extern int -ada_RsaPublicKeyDecode(const byte *input, word32 *inOutIdx, - uint32_t key, word32 inSz) +extern void* ada_new_rsa (int index) { - return wc_RsaPublicKeyDecode (input, inOutIdx, - &preAllocatedRSAKeys[key], inSz); + return &preAllocatedRSAKeys[index]; } wc_Sha256 preAllocatedSHA256[WOLFSSL_SHA256_INSTANCES]; @@ -143,3 +145,14 @@ extern void* ada_new_sha256 (int index) extern int get_wolfssl_sha256_instances(void) { return WOLFSSL_SHA256_INSTANCES; } + +Aes preAllocatedAes[WOLFSSL_AES_INSTANCES]; + +extern void* ada_new_aes (int index) +{ + return &preAllocatedAes[index]; +} + +extern int get_wolfssl_aes_instances(void) { + return WOLFSSL_AES_INSTANCES; +} diff --git a/wrapper/Ada/default.gpr b/wrapper/Ada/default.gpr index 16809601bc4..1909f317b1e 100644 --- a/wrapper/Ada/default.gpr +++ b/wrapper/Ada/default.gpr @@ -20,7 +20,9 @@ project Default is "tls_client.adb", "tls_server_main.adb", "tls_server.ads", - "tls_server.adb"); + "tls_server.adb", + "sha256_main.adb", + "rsa_verify_main.adb"); for Object_Dir use "obj"; diff --git a/wrapper/Ada/examples.gpr b/wrapper/Ada/examples.gpr index 35e0c46fba1..72ccfed913e 100644 --- a/wrapper/Ada/examples.gpr +++ b/wrapper/Ada/examples.gpr @@ -14,7 +14,8 @@ project Examples is for Main use ("tls_server_main.adb", "tls_client_main.adb", - "sha256_main.adb"); + "sha256_main.adb", + "rsa_verify_main.adb"); package Naming is for Spec_Suffix ("C") use ".h"; diff --git a/wrapper/Ada/rsa_verify_main.adb b/wrapper/Ada/rsa_verify_main.adb new file mode 100644 index 00000000000..f7dcbc9ab89 --- /dev/null +++ b/wrapper/Ada/rsa_verify_main.adb @@ -0,0 +1,226 @@ +with Ada.Integer_Text_IO; +with Ada.Text_IO; +with WolfSSL; + +procedure Rsa_Verify_Main is + + type Unsigned_8 is mod 2 ** 8; + + function To_C (Value : Unsigned_8) return WolfSSL.Byte_Type is + begin + return WolfSSL.Byte_Type'Val (Value); + end To_C; + + -- RSA public key to verify with. + Rsa_Public_key_2048 : constant WolfSSL.Byte_Array := + (To_C (16#C3#), To_C (16#03#), To_C (16#D1#), To_C (16#2B#), + To_C (16#FE#), To_C (16#39#), To_C (16#A4#), To_C (16#32#), + To_C (16#45#), To_C (16#3B#), To_C (16#53#), To_C (16#C8#), + To_C (16#84#), To_C (16#2B#), To_C (16#2A#), To_C (16#7C#), + To_C (16#74#), To_C (16#9A#), To_C (16#BD#), To_C (16#AA#), + To_C (16#2A#), To_C (16#52#), To_C (16#07#), To_C (16#47#), + To_C (16#D6#), To_C (16#A6#), To_C (16#36#), To_C (16#B2#), + To_C (16#07#), To_C (16#32#), To_C (16#8E#), To_C (16#D0#), + To_C (16#BA#), To_C (16#69#), To_C (16#7B#), To_C (16#C6#), + To_C (16#C3#), To_C (16#44#), To_C (16#9E#), To_C (16#D4#), + To_C (16#81#), To_C (16#48#), To_C (16#FD#), To_C (16#2D#), + To_C (16#68#), To_C (16#A2#), To_C (16#8B#), To_C (16#67#), + To_C (16#BB#), To_C (16#A1#), To_C (16#75#), To_C (16#C8#), + To_C (16#36#), To_C (16#2C#), To_C (16#4A#), To_C (16#D2#), + To_C (16#1B#), To_C (16#F7#), To_C (16#8B#), To_C (16#BA#), + To_C (16#CF#), To_C (16#0D#), To_C (16#F9#), To_C (16#EF#), + To_C (16#EC#), To_C (16#F1#), To_C (16#81#), To_C (16#1E#), + To_C (16#7B#), To_C (16#9B#), To_C (16#03#), To_C (16#47#), + To_C (16#9A#), To_C (16#BF#), To_C (16#65#), To_C (16#CC#), + To_C (16#7F#), To_C (16#65#), To_C (16#24#), To_C (16#69#), + To_C (16#A6#), To_C (16#E8#), To_C (16#14#), To_C (16#89#), + To_C (16#5B#), To_C (16#E4#), To_C (16#34#), To_C (16#F7#), + To_C (16#C5#), To_C (16#B0#), To_C (16#14#), To_C (16#93#), + To_C (16#F5#), To_C (16#67#), To_C (16#7B#), To_C (16#3A#), + To_C (16#7A#), To_C (16#78#), To_C (16#E1#), To_C (16#01#), + To_C (16#56#), To_C (16#56#), To_C (16#91#), To_C (16#A6#), + To_C (16#13#), To_C (16#42#), To_C (16#8D#), To_C (16#D2#), + To_C (16#3C#), To_C (16#40#), To_C (16#9C#), To_C (16#4C#), + To_C (16#EF#), To_C (16#D1#), To_C (16#86#), To_C (16#DF#), + To_C (16#37#), To_C (16#51#), To_C (16#1B#), To_C (16#0C#), + To_C (16#A1#), To_C (16#3B#), To_C (16#F5#), To_C (16#F1#), + To_C (16#A3#), To_C (16#4A#), To_C (16#35#), To_C (16#E4#), + To_C (16#E1#), To_C (16#CE#), To_C (16#96#), To_C (16#DF#), + To_C (16#1B#), To_C (16#7E#), To_C (16#BF#), To_C (16#4E#), + To_C (16#97#), To_C (16#D0#), To_C (16#10#), To_C (16#E8#), + To_C (16#A8#), To_C (16#08#), To_C (16#30#), To_C (16#81#), + To_C (16#AF#), To_C (16#20#), To_C (16#0B#), To_C (16#43#), + To_C (16#14#), To_C (16#C5#), To_C (16#74#), To_C (16#67#), + To_C (16#B4#), To_C (16#32#), To_C (16#82#), To_C (16#6F#), + To_C (16#8D#), To_C (16#86#), To_C (16#C2#), To_C (16#88#), + To_C (16#40#), To_C (16#99#), To_C (16#36#), To_C (16#83#), + To_C (16#BA#), To_C (16#1E#), To_C (16#40#), To_C (16#72#), + To_C (16#22#), To_C (16#17#), To_C (16#D7#), To_C (16#52#), + To_C (16#65#), To_C (16#24#), To_C (16#73#), To_C (16#B0#), + To_C (16#CE#), To_C (16#EF#), To_C (16#19#), To_C (16#CD#), + To_C (16#AE#), To_C (16#FF#), To_C (16#78#), To_C (16#6C#), + To_C (16#7B#), To_C (16#C0#), To_C (16#12#), To_C (16#03#), + To_C (16#D4#), To_C (16#4E#), To_C (16#72#), To_C (16#0D#), + To_C (16#50#), To_C (16#6D#), To_C (16#3B#), To_C (16#A3#), + To_C (16#3B#), To_C (16#A3#), To_C (16#99#), To_C (16#5E#), + To_C (16#9D#), To_C (16#C8#), To_C (16#D9#), To_C (16#0C#), + To_C (16#85#), To_C (16#B3#), To_C (16#D9#), To_C (16#8A#), + To_C (16#D9#), To_C (16#54#), To_C (16#26#), To_C (16#DB#), + To_C (16#6D#), To_C (16#FA#), To_C (16#AC#), To_C (16#BB#), + To_C (16#FF#), To_C (16#25#), To_C (16#4C#), To_C (16#C4#), + To_C (16#D1#), To_C (16#79#), To_C (16#F4#), To_C (16#71#), + To_C (16#D3#), To_C (16#86#), To_C (16#40#), To_C (16#18#), + To_C (16#13#), To_C (16#B0#), To_C (16#63#), To_C (16#B5#), + To_C (16#72#), To_C (16#4E#), To_C (16#30#), To_C (16#C4#), + To_C (16#97#), To_C (16#84#), To_C (16#86#), To_C (16#2D#), + To_C (16#56#), To_C (16#2F#), To_C (16#D7#), To_C (16#15#), + To_C (16#F7#), To_C (16#7F#), To_C (16#C0#), To_C (16#AE#), + To_C (16#F5#), To_C (16#FC#), To_C (16#5B#), To_C (16#E5#), + To_C (16#FB#), To_C (16#A1#), To_C (16#BA#), To_C (16#D3#)); + + Message : constant WolfSSL.Byte_Array := + (To_C (16#54#), To_C (16#68#), To_C (16#69#), To_C (16#73#), + To_C (16#20#), To_C (16#69#), To_C (16#73#), To_C (16#20#), + To_C (16#74#), To_C (16#68#), To_C (16#65#), To_C (16#20#), + To_C (16#6d#), To_C (16#65#), To_C (16#73#), To_C (16#73#), + To_C (16#61#), To_C (16#67#), To_C (16#65#)); + + + RSA_Signature : constant WolfSSL.Byte_Array := + (To_C (16#41#), To_C (16#eb#), To_C (16#f5#), To_C (16#5e#), + To_C (16#97#), To_C (16#43#), To_C (16#f4#), To_C (16#d1#), + To_C (16#da#), To_C (16#b6#), To_C (16#5c#), To_C (16#75#), + To_C (16#57#), To_C (16#2c#), To_C (16#e1#), To_C (16#01#), + To_C (16#07#), To_C (16#dc#), To_C (16#42#), To_C (16#c4#), + To_C (16#2d#), To_C (16#e2#), To_C (16#b5#), To_C (16#c8#), + To_C (16#63#), To_C (16#e8#), To_C (16#45#), To_C (16#9a#), + To_C (16#4a#), To_C (16#fa#), To_C (16#df#), To_C (16#5e#), + To_C (16#a6#), To_C (16#08#), To_C (16#0a#), To_C (16#26#), + To_C (16#2e#), To_C (16#ca#), To_C (16#2c#), To_C (16#10#), + To_C (16#7a#), To_C (16#15#), To_C (16#8d#), To_C (16#c1#), + To_C (16#55#), To_C (16#cc#), To_C (16#33#), To_C (16#db#), + To_C (16#b2#), To_C (16#ef#), To_C (16#8b#), To_C (16#a6#), + To_C (16#4b#), To_C (16#ef#), To_C (16#a1#), To_C (16#cf#), + To_C (16#d3#), To_C (16#e2#), To_C (16#5d#), To_C (16#ac#), + To_C (16#88#), To_C (16#86#), To_C (16#62#), To_C (16#67#), + To_C (16#8b#), To_C (16#8c#), To_C (16#45#), To_C (16#7f#), + To_C (16#10#), To_C (16#ad#), To_C (16#fa#), To_C (16#27#), + To_C (16#7a#), To_C (16#35#), To_C (16#5a#), To_C (16#f9#), + To_C (16#09#), To_C (16#78#), To_C (16#83#), To_C (16#ba#), + To_C (16#18#), To_C (16#cb#), To_C (16#3e#), To_C (16#8e#), + To_C (16#08#), To_C (16#be#), To_C (16#36#), To_C (16#de#), + To_C (16#ac#), To_C (16#c1#), To_C (16#77#), To_C (16#44#), + To_C (16#e8#), To_C (16#43#), To_C (16#db#), To_C (16#52#), + To_C (16#23#), To_C (16#08#), To_C (16#36#), To_C (16#8f#), + To_C (16#74#), To_C (16#4a#), To_C (16#bd#), To_C (16#a3#), + To_C (16#3f#), To_C (16#c1#), To_C (16#fb#), To_C (16#d6#), + To_C (16#45#), To_C (16#25#), To_C (16#61#), To_C (16#e2#), + To_C (16#19#), To_C (16#cb#), To_C (16#0b#), To_C (16#28#), + To_C (16#ef#), To_C (16#ca#), To_C (16#0a#), To_C (16#3b#), + To_C (16#7b#), To_C (16#3d#), To_C (16#e3#), To_C (16#47#), + To_C (16#46#), To_C (16#07#), To_C (16#1a#), To_C (16#7f#), + To_C (16#ff#), To_C (16#38#), To_C (16#fd#), To_C (16#59#), + To_C (16#94#), To_C (16#0b#), To_C (16#eb#), To_C (16#00#), + To_C (16#ab#), To_C (16#cc#), To_C (16#8c#), To_C (16#48#), + To_C (16#7b#), To_C (16#d6#), To_C (16#87#), To_C (16#b8#), + To_C (16#54#), To_C (16#b0#), To_C (16#2a#), To_C (16#07#), + To_C (16#cf#), To_C (16#44#), To_C (16#11#), To_C (16#d4#), + To_C (16#b6#), To_C (16#9a#), To_C (16#4e#), To_C (16#6d#), + To_C (16#5c#), To_C (16#1a#), To_C (16#e3#), To_C (16#c7#), + To_C (16#f3#), To_C (16#c7#), To_C (16#cb#), To_C (16#8e#), + To_C (16#82#), To_C (16#7d#), To_C (16#c8#), To_C (16#77#), + To_C (16#f0#), To_C (16#b6#), To_C (16#d0#), To_C (16#85#), + To_C (16#cb#), To_C (16#db#), To_C (16#d0#), To_C (16#b0#), + To_C (16#e0#), To_C (16#cf#), To_C (16#ca#), To_C (16#3f#), + To_C (16#17#), To_C (16#46#), To_C (16#84#), To_C (16#cb#), + To_C (16#5b#), To_C (16#fe#), To_C (16#51#), To_C (16#3a#), + To_C (16#aa#), To_C (16#71#), To_C (16#ad#), To_C (16#eb#), + To_C (16#f1#), To_C (16#ed#), To_C (16#3f#), To_C (16#f8#), + To_C (16#de#), To_C (16#b4#), To_C (16#a1#), To_C (16#26#), + To_C (16#db#), To_C (16#c6#), To_C (16#8e#), To_C (16#70#), + To_C (16#d4#), To_C (16#58#), To_C (16#a8#), To_C (16#31#), + To_C (16#d8#), To_C (16#db#), To_C (16#cf#), To_C (16#64#), + To_C (16#4a#), To_C (16#5f#), To_C (16#1b#), To_C (16#89#), + To_C (16#22#), To_C (16#03#), To_C (16#3f#), To_C (16#ab#), + To_C (16#b5#), To_C (16#6d#), To_C (16#2a#), To_C (16#63#), + To_C (16#2f#), To_C (16#4e#), To_C (16#7a#), To_C (16#e1#), + To_C (16#89#), To_C (16#b4#), To_C (16#f0#), To_C (16#9a#), + To_C (16#b7#), To_C (16#d3#), To_C (16#d6#), To_C (16#0a#), + To_C (16#10#), To_C (16#67#), To_C (16#28#), To_C (16#25#), + To_C (16#6d#), To_C (16#da#), To_C (16#92#), To_C (16#99#), + To_C (16#3f#), To_C (16#64#), To_C (16#a7#), To_C (16#ea#), + To_C (16#e0#), To_C (16#dc#), To_C (16#7c#), To_C (16#e8#), + To_C (16#41#), To_C (16#b0#), To_C (16#eb#), To_C (16#45#)); + + procedure Put (Text : String) renames Ada.Text_IO.Put; + + procedure Put (Value : Integer) is + begin + Ada.Integer_Text_IO.Put (Value); + end Put; + + procedure New_Line is + begin + Ada.Text_IO.New_Line; + end New_Line; + + use type WolfSSL.Subprogram_Result; + + Hash : WolfSSL.SHA256_Hash; + SHA256 : WolfSSL.SHA256_Type; + R : Integer; + S : WolfSSL.SHA256_As_String; + + Key : WolfSSL.RSA_Key_Type; + Index : WolfSSL.Byte_Index; +begin + WolfSSL.Create_SHA256 (Index => 0, SHA256 => SHA256, Result => R); + if R /= 0 then + Put ("SHA256 instance creation failed"); + New_Line; + return; + end if; + WolfSSL.Update_SHA256 (SHA256 => SHA256, Byte => Message, Result => R); + if R /= 0 then + Put ("Update of SHA256 instance failed"); + New_Line; + return; + end if; + WolfSSL.Finalize_SHA256 (SHA256 => SHA256, + Hash => Hash, + Text => S, + Result => R); + if R = 0 then + Put (S); + New_Line; + else + Put ("Finalization of SHA256 instance failed"); + New_Line; + return; + end if; + + WolfSSL.Create_RSA (Index => 0, + Key => Key, + Result => R); + if R /= 0 then + Put ("Attaining RSA key instance failed"); + New_Line; + return; + end if; + + Index := Rsa_Public_key_2048'First; + Put (WolfSSL.Is_Valid (Key)'Image); + + WolfSSL.Rsa_Public_Key_Decode (Input => Rsa_Public_key_2048, + Index => Index, + Key => Key, + Size => Rsa_Public_key_2048'Length, + Result => R); + Put (Integer (Index)); + if R /= 0 then + Put ("Loading RSA key failed with DER encoded key"); + Put (R); + New_Line; + return; + end if; +end Rsa_Verify_Main; diff --git a/wrapper/Ada/sha256_main.adb b/wrapper/Ada/sha256_main.adb index 56dffce79cc..355109d9045 100644 --- a/wrapper/Ada/sha256_main.adb +++ b/wrapper/Ada/sha256_main.adb @@ -11,6 +11,7 @@ procedure SHA256_Main is use type WolfSSL.Subprogram_Result; + Hash : WolfSSL.SHA256_Hash; B : WolfSSL.Byte_Array := (1 => 'a', 2 => 's', 3 => 'd', @@ -31,7 +32,10 @@ begin New_Line; return; end if; - WolfSSL.Finalize_SHA256 (SHA256 => SHA256, Hash => S, Result => R); + WolfSSL.Finalize_SHA256 (SHA256 => SHA256, + Hash => Hash, + Text => S, + Result => R); if R = 0 then Put (S); New_Line; @@ -39,5 +43,5 @@ begin Put ("Finalization of SHA256 instance failed"); New_Line; return; - end if; + end if; end SHA256_Main; diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index d6e35d3705f..d17edf93deb 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -20,7 +20,6 @@ -- with Ada.Unchecked_Conversion; -with Interfaces.C.Strings; with WolfSSL; package body WolfSSL is @@ -30,6 +29,94 @@ package body WolfSSL is subtype long is Interfaces.C.long; subtype unsigned_long is Interfaces.C.unsigned_long; + nul : constant Byte_Type := Byte_Type'First; + + -- Convert String to char_array (procedure form) + -- This subprogram originates from the full Ada run-time + -- but is not present on the Zero Footprint run-time, + -- therefore it is included here. + procedure To_C + (Item : String; + Target : out Byte_Array; + Count : out size_t; + Append_Nul : Boolean := True) + is + To : size_t; + begin + if Target'Length < Item'Length then + raise Constraint_Error; + else + To := Target'First; + for From in Item'Range loop + Target (To) := Byte_Type (Item (From)); + To := To + 1; + end loop; + + if Append_Nul then + if To > Target'Last then + raise Constraint_Error; + else + Target (To) := nul; + Count := Item'Length + 1; + end if; + else + Count := Item'Length; + end if; + end if; + end To_C; + + -- Convert char_array to String (procedure form) + -- This subprogram originates from the full Ada run-time + -- but is not present on the Zero Footprint run-time, + -- therefore it is included here. + procedure To_Ada + (Item : Byte_Array; + Target : out String; + Count : out Natural; + Trim_Nul : Boolean := True) + is + use type Byte_Type; + + From : size_t; + To : Integer; + begin + if Trim_Nul then + From := Item'First; + loop + if From > Item'Last then + raise Terminator_Error; + elsif Item (From) = nul then + exit; + else + From := From + 1; + end if; + end loop; + + Count := Natural (From - Item'First); + + else + Count := Item'Length; + end if; + + if Count > Target'Length then + raise Constraint_Error; + + else + From := Item'First; + To := Target'First; + + for J in 1 .. Count loop + Target (To) := Character (Item (From)); + -- Avoid possible overflow when incrementing To in the last + -- iteration of the loop. + exit when J = Count; + + From := From + 1; + To := To + 1; + end loop; + end if; + end To_Ada; + WOLFSSL_SUCCESS : constant int := Get_WolfSSL_Success; function Initialize_WolfSSL return int with @@ -243,10 +330,10 @@ package body WolfSSL is F : Byte_Array (1 .. File'Length + 1); Result : int; begin - Interfaces.C.To_C (Item => File, - Target => F, - Count => C, - Append_Nul => True); + To_C (Item => File, + Target => F, + Count => C, + Append_Nul => True); Result := Use_Certificate_File (Ctx, F (1 .. C), int (Format)); return Subprogram_Result (Result); end Use_Certificate_File; @@ -256,9 +343,9 @@ package body WolfSSL is Size : long; Format : int) return int with - Convention => C, - External_Name => "wolfSSL_CTX_use_certificate_buffer", - Import => True; + Convention => C, + External_Name => "wolfSSL_CTX_use_certificate_buffer", + Import => True; function Use_Certificate_Buffer (Context : Context_Type; Input : Byte_Array; @@ -288,10 +375,10 @@ package body WolfSSL is F : Byte_Array (1 .. File'Length + 1); Result : int; begin - Interfaces.C.To_C (Item => File, - Target => F, - Count => C, - Append_Nul => True); + To_C (Item => File, + Target => F, + Count => C, + Append_Nul => True); Result := Use_Private_Key_File (Ctx, F (1 .. C), int (Format)); return Subprogram_Result (Result); end Use_Private_Key_File; @@ -317,12 +404,12 @@ package body WolfSSL is end Use_Private_Key_Buffer; function Load_Verify_Locations1 - (Context : Context_Type; - File : Byte_Array; - Path : Byte_Array) return int with - Convention => C, - External_Name => "wolfSSL_CTX_load_verify_locations", - Import => True; + (Context : Context_Type; + File : Byte_Array; + Path : Byte_Array) return int with + Convention => C, + External_Name => "wolfSSL_CTX_load_verify_locations", + Import => True; -- This function loads PEM-formatted CA certificate files into -- the SSL context (WOLFSSL_CTX). These certificates will be treated -- as trusted root certificates and used to verify certs received @@ -340,28 +427,28 @@ package body WolfSSL is -- PEM formatted CERT_TYPE file with header "--BEGIN CERTIFICATE--". function Load_Verify_Locations2 - (Context : Context_Type; - File : Byte_Array; - Path : access Interfaces.C.char) return int with - Convention => C, - External_Name => "wolfSSL_CTX_load_verify_locations", - Import => True; + (Context : Context_Type; + File : Byte_Array; + Path : access Interfaces.C.char) return int with + Convention => C, + External_Name => "wolfSSL_CTX_load_verify_locations", + Import => True; function Load_Verify_Locations3 - (Context : Context_Type; - File : access Interfaces.C.char; - Path : Byte_Array) return int with - Convention => C, - External_Name => "wolfSSL_CTX_load_verify_locations", - Import => True; + (Context : Context_Type; + File : access Interfaces.C.char; + Path : Byte_Array) return int with + Convention => C, + External_Name => "wolfSSL_CTX_load_verify_locations", + Import => True; function Load_Verify_Locations4 - (Context : Context_Type; - File : access Interfaces.C.char; - Path : access Interfaces.C.char) return int with - Convention => C, - External_Name => "wolfSSL_CTX_load_verify_locations", - Import => True; + (Context : Context_Type; + File : access Interfaces.C.char; + Path : access Interfaces.C.char) return int with + Convention => C, + External_Name => "wolfSSL_CTX_load_verify_locations", + Import => True; function Load_Verify_Locations (Context : Context_Type; File : String; @@ -380,28 +467,28 @@ package body WolfSSL is if Path = "" then Result := Load_Verify_Locations4 (Ctx, null, null); else - Interfaces.C.To_C (Item => Path, - Target => P, - Count => PC, - Append_Nul => True); + To_C (Item => Path, + Target => P, + Count => PC, + Append_Nul => True); Result := Load_Verify_Locations3 (Ctx, null, P); end if; else - Interfaces.C.To_C (Item => File, - Target => F, - Count => FC, - Append_Nul => True); + To_C (Item => File, + Target => F, + Count => FC, + Append_Nul => True); if Path = "" then Result := Load_Verify_Locations2 (Ctx, F, null); else - Interfaces.C.To_C (Item => Path, - Target => P, - Count => PC, - Append_Nul => True); - Interfaces.C.To_C (Item => Path, - Target => P, - Count => PC, - Append_Nul => True); + To_C (Item => Path, + Target => P, + Count => PC, + Append_Nul => True); + To_C (Item => Path, + Target => P, + Count => PC, + Append_Nul => True); Result := Load_Verify_Locations1 (Context => Ctx, File => F, Path => P); @@ -411,13 +498,13 @@ package body WolfSSL is end Load_Verify_Locations; function Load_Verify_Buffer - (Context : Context_Type; - Input : Byte_Array; - Size : int; - Format : int) return int with - Convention => C, - External_Name => "wolfSSL_CTX_load_verify_buffer", - Import => True; + (Context : Context_Type; + Input : Byte_Array; + Size : int; + Format : int) return int with + Convention => C, + External_Name => "wolfSSL_CTX_load_verify_buffer", + Import => True; function Load_Verify_Buffer (Context : Context_Type; Input : Byte_Array; @@ -426,9 +513,9 @@ package body WolfSSL is Result : int; begin Result := Load_Verify_Buffer (Context => Context, - Input => Input, - Size => Input'Length, - Format => int(Format)); + Input => Input, + Size => Input'Length, + Format => int(Format)); return Subprogram_Result (Result); end Load_Verify_Buffer; @@ -465,10 +552,10 @@ package body WolfSSL is F : Byte_Array (1 .. File'Length + 1); Result : int; begin - Interfaces.C.To_C (Item => File, - Target => F, - Count => C, - Append_Nul => True); + To_C (Item => File, + Target => F, + Count => C, + Append_Nul => True); Result := Use_Certificate_File (Ssl, F (1 .. C), int (Format)); return Subprogram_Result (Result); end Use_Certificate_File; @@ -478,9 +565,9 @@ package body WolfSSL is Size : long; Format : int) return int with - Convention => C, - External_Name => "wolfSSL_use_certificate_buffer", - Import => True; + Convention => C, + External_Name => "wolfSSL_use_certificate_buffer", + Import => True; function Use_Certificate_Buffer (Ssl : WolfSSL_Type; Input : Byte_Array; @@ -496,10 +583,10 @@ package body WolfSSL is function Use_Private_Key_File (Ssl : WolfSSL_Type; File : Byte_Array; Format : int) - return int with - Convention => C, - External_Name => "wolfSSL_use_PrivateKey_file", - Import => True; + return int with + Convention => C, + External_Name => "wolfSSL_use_PrivateKey_file", + Import => True; function Use_Private_Key_File (Ssl : WolfSSL_Type; File : String; @@ -509,10 +596,10 @@ package body WolfSSL is F : Byte_Array (1 .. File'Length + 1); Result : int; begin - Interfaces.C.To_C (Item => File, - Target => F, - Count => C, - Append_Nul => True); + To_C (Item => File, + Target => F, + Count => C, + Append_Nul => True); Result := Use_Private_Key_File (Ssl, F (1 .. C), int (Format)); return Subprogram_Result (Result); end Use_Private_Key_File; @@ -551,9 +638,9 @@ package body WolfSSL is end Attach; procedure WolfSSL_Keep_Arrays (Ssl : WolfSSL_Type) with - Convention => C, - External_Name => "wolfSSL_KeepArrays", - Import => True; + Convention => C, + External_Name => "wolfSSL_KeepArrays", + Import => True; procedure Keep_Arrays (Ssl : WolfSSL_Type) is begin @@ -667,9 +754,9 @@ package body WolfSSL is end Shutdown; function WolfSSL_Connect (Ssl : WolfSSL_Type) return int with - Convention => C, - External_Name => "wolfSSL_connect", - Import => True; + Convention => C, + External_Name => "wolfSSL_connect", + Import => True; function Connect (Ssl : WolfSSL_Type) return Subprogram_Result is Result : constant int := WolfSSL_Connect (Ssl); @@ -678,9 +765,9 @@ package body WolfSSL is end Connect; procedure WolfSSL_Free (Ssl : WolfSSL_Type) with - Convention => C, - External_Name => "wolfSSL_free", - Import => True; + Convention => C, + External_Name => "wolfSSL_free", + Import => True; procedure Free (Ssl : in out WolfSSL_Type) is begin @@ -692,9 +779,9 @@ package body WolfSSL is function WolfSSL_Get_Error (Ssl : WolfSSL_Type; Ret : int) return int with - Convention => C, - External_Name => "wolfSSL_get_error", - Import => True; + Convention => C, + External_Name => "wolfSSL_get_error", + Import => True; function Get_Error (Ssl : WolfSSL_Type; Result : Subprogram_Result) return Error_Code is @@ -705,9 +792,9 @@ package body WolfSSL is procedure WolfSSL_Error_String (Error : unsigned_long; Data : out Byte_Array; Size : unsigned_long) with - Convention => C, - External_Name => "wolfSSL_ERR_error_string_n", - Import => True; + Convention => C, + External_Name => "wolfSSL_ERR_error_string_n", + Import => True; function Error (Code : Error_Code) return Error_Message is S : String (1 .. Error_Message_Index'Last); @@ -716,16 +803,16 @@ package body WolfSSL is -- Use unchecked conversion instead of type conversion to mimic C style -- conversion from int to unsigned long, avoiding the Ada overflow check. function To_Unsigned_Long is new Ada.Unchecked_Conversion - (Source => long, - Target => unsigned_long); + (Source => long, + Target => unsigned_long); begin WolfSSL_Error_String (Error => To_Unsigned_Long (long (Code)), Data => B, Size => To_Unsigned_Long (long (B'Last))); - Interfaces.C.To_Ada (Item => B, - Target => S, - Count => C, - Trim_Nul => True); + To_Ada (Item => B, + Target => S, + Count => C, + Trim_Nul => True); return (Last => C, Text => S (1 .. C)); end Error; @@ -740,22 +827,52 @@ package body WolfSSL is return Natural (Get_WolfSSL_Max_Error_Size); end Max_Error_Size; - function Ada_RSA_Public_Key_Decode (Input : Byte_Array; - Index : in out Integer; - Key : RSA_Key_Index; - Size : Integer) return int with + function Is_Valid (Key : RSA_Key_Type) return Boolean is + begin + return Key /= null; + end Is_Valid; + + function Ada_New_RSA (Index : int) + return RSA_Key_Type with + Convention => C, + External_Name => "ada_new_rsa", + Import => True; + + function Init_RSA_Key (Key : not null RSA_Key_Type; + Heap : access Byte_Type) return int with + Convention => C, + External_Name => "wc_InitRsaKey", + Import => True; + + procedure Create_RSA (Index : RSA_Key_Index; + Key : in out RSA_Key_Type; + Result : out Integer) is + R : int; + begin + Key := Ada_New_RSA (int (Index)); + R := Init_RSA_Key (Key, null); + Result := Integer (R); + end Create_RSA; + + function RSA_Public_Key_Decode (Input : Byte_Array; + Index : in out int; + Key : not null RSA_Key_Type; + Size : int) return int with Convention => C, - External_Name => "ada_RsaPublicKeyDecode", + External_Name => "wc_RsaPublicKeyDecode", Import => True; procedure Rsa_Public_Key_Decode (Input : Byte_Array; - Index : in out Integer; - Key : RSA_Key_Index; + Index : in out Byte_Index; + Key : in out RSA_Key_Type; Size : Integer; - Result : out Subprogram_Result) is - R : constant int := Ada_RSA_Public_Key_Decode (Input, Index, Key, Size); + Result : out Integer) is + I : aliased int := int (Index); + R : constant int := + RSA_Public_Key_Decode (Input, I, Key, int (Size)); begin - Result := Subprogram_Result (R); + Index := WolfSSL.Byte_Index (I); + Result := Integer (R); end Rsa_Public_Key_Decode; function Init_SHA256 (SHA256 : not null Sha256_Type) return int with @@ -790,7 +907,7 @@ package body WolfSSL is procedure Create_SHA256 (Index : SHA256_Index; SHA256 : in out SHA256_Type; Result : out Integer) is - R : int; + R : int; begin SHA256 := Ada_New_SHA256 (Index); R := Init_SHA256 (SHA256); @@ -800,38 +917,46 @@ package body WolfSSL is procedure Update_SHA256 (SHA256 : in out SHA256_Type; Byte : Byte_Array; Result : out Integer) is - R : int; + R : int; begin R := SHA256_Update (SHA256, Byte, Byte'Length); Result := Integer (R); end Update_SHA256; procedure Finalize_SHA256 (SHA256 : in out SHA256_Type; - Hash : out SHA256_As_String; + Hash : out SHA256_Hash; + Text : out SHA256_As_String; Result : out Integer) is subtype Unsigned_8 is Interfaces.Unsigned_8; use type Unsigned_8; R : int; - H : Byte_Array (1 .. 32) := (others => '#'); Hex_Chars : constant array (Unsigned_8 range 0 .. 15) of Character := "0123456789ABCDEF"; I : Integer; C : Integer; begin - R := SHA256_Final (SHA256, H); + R := SHA256_Final (SHA256, Hash); Result := Integer (R); for Index in Positive range 1 .. 32 loop I := 2 * (Index - 1) + 1; - C := Interfaces.C.char'Pos (H (size_t (Index))); - Hash (I+0) := Hex_Chars ((Unsigned_8 (C) and 16#F0#) / 16); - Hash (I+1) := Hex_Chars (Unsigned_8 (C) and 16#0F#); + C := Interfaces.C.char'Pos (Hash (size_t (Index))); + Text (I+0) := Hex_Chars ((Unsigned_8 (C) and 16#F0#) / 16); + Text (I+1) := Hex_Chars (Unsigned_8 (C) and 16#0F#); end loop; end Finalize_SHA256; - type Opaque_AES is limited null record; - type AES_Type is access Opaque_AES with Convention => C; + function Is_Valid (AES : AES_Type) return Boolean is + begin + return AES /= null; + end Is_Valid; + + function Ada_New_AES (Index : AES_Index) + return AES_Type with + Convention => C, + External_Name => "ada_new_aes", + Import => True; function AES_Init (AES : not null AES_Type; Heap : access Byte_Type; @@ -840,6 +965,17 @@ package body WolfSSL is External_Name => "wc_AesInit", Import => True; + procedure Create_AES (Index : AES_Index; + Device : Integer; + AES : in out AES_Type; + Result : out Integer) is + R : int; + begin + AES := Ada_New_AES (Index); + R := AES_Init (AES, null, int (Device)); + Result := Integer (R); + end Create_AES; + function AES_Set_Key (AES : not null AES_Type; Key : Byte_Array; Length : int; @@ -849,12 +985,33 @@ package body WolfSSL is External_Name => "wc_AesSetKey", Import => True; + procedure AES_Set_Key (AES : AES_Type; + Key : Byte_Array; + Length : Integer; + IV : Byte_Array; + Dir : Integer; + Result : out Integer) is + R : int; + begin + R := AES_Set_Key (AES, Key, int (Length), IV, int (Dir)); + Result := Integer (R); + end AES_Set_Key; + function AES_Set_IV (AES : not null AES_Type; - IV : Byte_Array) return int with + IV : Byte_Array) return int with Convention => C, External_Name => "wc_AesSetIV", Import => True; + procedure AES_Set_IV (AES : AES_Type; + IV : Byte_Array; + Result : out Integer) is + R : int; + begin + R := AES_Set_IV (AES, IV); + Result := Integer (R); + end AES_Set_IV; + function AES_Set_Cbc_Encrypt (AES : not null AES_Type; Output : out Byte_Array; Input : Byte_Array; @@ -863,6 +1020,17 @@ package body WolfSSL is External_Name => "wc_AesCbcEncrypt", Import => True; + procedure AES_Set_Cbc_Encrypt (AES : AES_Type; + Output : out Byte_Array; + Input : Byte_Array; + Size : Integer; + Result : out Integer) is + R : int; + begin + R := AES_Set_Cbc_Encrypt (AES, Output, Input, int (Size)); + Result := Integer (R); + end AES_Set_Cbc_Encrypt; + function AES_Set_Cbc_Decrypt (AES : not null AES_Type; Output : out Byte_Array; Input : Byte_Array; @@ -871,11 +1039,33 @@ package body WolfSSL is External_Name => "wc_AesCbcDecrypt", Import => True; + procedure AES_Set_Cbc_Decrypt (AES : AES_Type; + Output : out Byte_Array; + Input : Byte_Array; + Size : Integer; + Result : out Integer) is + R : int; + begin + R := AES_Set_Cbc_Decrypt (AES, Output, Input, int (Size)); + Result := Integer (R); + end AES_Set_Cbc_Decrypt; + function AES_Free (AES : not null AES_Type) return int with Convention => C, External_Name => "wc_AesFree", Import => True; + procedure AES_Free (AES : in out AES_Type; + Result : out Integer) is + R : int; + begin + R := AES_Free (AES); + Result := Integer (R); + if Result = 0 then + AES := null; + end if; + end AES_Free; + function Get_WolfSSL_RSA_Instances return int with Convention => C, External_Name => "get_wolfssl_rsa_instances", @@ -886,7 +1076,13 @@ package body WolfSSL is External_Name => "get_wolfssl_sha256_instances", Import => True; + function Get_WolfSSL_AES_Instances return int with + Convention => C, + External_Name => "get_wolfssl_aes_instances", + Import => True; + begin pragma Assert (RSA_INSTANCES = Get_WolfSSL_RSA_Instances); pragma Assert (SHA256_INSTANCES = Get_WolfSSL_SHA256_Instances); + pragma Assert (AES_INSTANCES = Get_WolfSSL_AES_Instances); end WolfSSL; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 33bd1ed2a83..3a079d3916c 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -25,6 +25,8 @@ with Interfaces.C; -- the API of this package is used correctly. package WolfSSL with SPARK_Mode is + Terminator_Error : exception; + type Subprogram_Result is new Integer; Success : constant Subprogram_Result; Failure : constant Subprogram_Result; @@ -487,19 +489,31 @@ package WolfSSL with SPARK_Mode is RSA_INSTANCES : constant := 2; type RSA_Key_Index is range 0 .. RSA_INSTANCES - 1; + + type RSA_Key_Type is limited private; + + function Is_Valid (Key : RSA_Key_Type) return Boolean; + -- Indicates if the RSA has successfully been initialized. + + procedure Create_RSA (Index : RSA_Key_Index; + Key : in out RSA_Key_Type; + Result : out Integer) with + Pre => not Is_Valid (Key), + Post => (if Result = 0 then Is_Valid (Key)); + -- If successful Result = 0. procedure Rsa_Public_Key_Decode (Input : Byte_Array; - Index : in out Integer; - Key : RSA_Key_Index; + Index : in out Byte_Index; + Key : in out RSA_Key_Type; Size : Integer; - Result : out Subprogram_Result); + Result : out Integer) with + Pre => Is_Valid (Key); -- This function parses a DER-formatted RSA public key, -- extracts the public key and stores it in the RsaKey structure -- specified by the Key input argument. It also sets the distance -- parsed in Index. - SHA256_INSTANCES : constant := 2; - + SHA256_INSTANCES : constant := 2; type SHA256_Index is range 0 .. SHA256_INSTANCES - 1; type SHA256_Type is limited private; @@ -510,8 +524,9 @@ package WolfSSL with SPARK_Mode is procedure Create_SHA256 (Index : SHA256_Index; SHA256 : in out SHA256_Type; Result : out Integer) with - Pre => not Is_Valid (SHA256); - -- If successful Is_Valid (SSHA256) = True, and Result = 0. + Pre => not Is_Valid (SHA256), + Post => (if Result = 0 then Is_Valid (SHA256)); + -- If successful Result = 0. procedure Update_SHA256 (SHA256 : in out SHA256_Type; Byte : Byte_Array; @@ -519,14 +534,64 @@ package WolfSSL with SPARK_Mode is Pre => Is_Valid (SHA256); -- If successful Result = 0. - subtype SHA256_As_String is String (1 .. 64); + subtype SHA256_As_String is String (1 .. 64); + + subtype SHA256_Hash is Byte_Array (1 .. 32); procedure Finalize_SHA256 (SHA256 : in out SHA256_Type; - Hash : out SHA256_As_String; + Hash : out SHA256_Hash; + Text : out SHA256_As_String; Result : out Integer) with Pre => Is_Valid (SHA256); -- If successful Result = 0. + AES_INSTANCES : constant := 2; + type AES_Index is range 0 .. AES_INSTANCES - 1; + + type AES_Type is limited private; + + function Is_Valid (AES : AES_Type) return Boolean; + -- Indicates if the AES has successfully been initialized. + + procedure Create_AES (Index : AES_Index; + Device : Integer; + AES : in out AES_Type; + Result : out Integer) with + Pre => not Is_Valid (AES); + -- If successful Is_Valid (AES) = True, and Result = 0. + + procedure AES_Set_Key (AES : AES_Type; + Key : Byte_Array; + Length : Integer; + IV : Byte_Array; + Dir : Integer; + Result : out Integer) with + Pre => Is_Valid (AES); + + procedure AES_Set_IV (AES : AES_Type; + IV : Byte_Array; + Result : out Integer) with + Pre => Is_Valid (AES); + + procedure AES_Set_Cbc_Encrypt (AES : AES_Type; + Output : out Byte_Array; + Input : Byte_Array; + Size : Integer; + Result : out Integer) with + Pre => Is_Valid (AES); + + procedure AES_Set_Cbc_Decrypt (AES : AES_Type; + Output : out Byte_Array; + Input : Byte_Array; + Size : Integer; + Result : out Integer) with + Pre => Is_Valid (AES); + + procedure AES_Free (AES : in out AES_Type; + Result : out Integer) with + Pre => Is_Valid (AES), + Post => (if Result = 0 then not Is_Valid (AES)); + private pragma SPARK_Mode (Off); @@ -670,9 +735,15 @@ private Error_Code (Get_WolfSSL_Error_Want_Read); Error_Want_Write : constant Error_Code := - Error_Code (Get_WolfSSL_Error_Want_Write); - + Error_Code (Get_WolfSSL_Error_Want_Write); + + type Opaque_RSA is limited null record; + type RSA_Key_Type is access Opaque_RSA with Convention => C; + type Opaque_Sha256 is limited null record; - type SHA256_Type is access Opaque_Sha256 with Convention => C; + type SHA256_Type is access Opaque_Sha256 with Convention => C; + + type Opaque_AES is limited null record; + type AES_Type is access Opaque_AES with Convention => C; end WolfSSL; From 714deb4e2da68ff33c1dd76286f40ae03c3174f4 Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Wed, 10 Dec 2025 00:59:56 +0100 Subject: [PATCH 04/51] Removed errors resulting from violation of restriction No Secondary Stack. --- wrapper/Ada/tls_client.adb | 7 +++--- wrapper/Ada/tls_server.adb | 9 ++++---- wrapper/Ada/wolfssl.adb | 45 ++++++++++++++++++++------------------ wrapper/Ada/wolfssl.ads | 11 ++++++---- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/wrapper/Ada/tls_client.adb b/wrapper/Ada/tls_client.adb index 30686ef6108..b00f49f1779 100644 --- a/wrapper/Ada/tls_client.adb +++ b/wrapper/Ada/tls_client.adb @@ -396,8 +396,9 @@ package body Tls_Client with SPARK_Mode is SPARK_Sockets.To_C (Item => Text (1 .. Last), Target => D, Count => Count); - Output := WolfSSL.Write (Ssl => Ssl, - Data => D (1 .. Count)); + WolfSSL.Write (Ssl => Ssl, + Data => D (1 .. Count), + Result => Output); if not Output.Success then Put ("ERROR: write failure"); New_Line; @@ -421,7 +422,7 @@ package body Tls_Client with SPARK_Mode is return; end if; - Input := WolfSSL.Read (Ssl); + WolfSSL.Read (Ssl => Ssl, Result => Input); if not Input.Success then Put_Line ("Read error."); Set (Exit_Status_Failure); diff --git a/wrapper/Ada/tls_server.adb b/wrapper/Ada/tls_server.adb index beebd685171..27fb6d40fbd 100644 --- a/wrapper/Ada/tls_server.adb +++ b/wrapper/Ada/tls_server.adb @@ -349,9 +349,10 @@ package body Tls_Server with SPARK_Mode is if not WolfSSL.Is_Valid (Ssl) then Put_Line ("ERROR: failed to create WOLFSSL object."); declare - Error_Message : constant WolfSSL.Error_Message := - WolfSSL.Error (WolfSSL.Get_Error (Ssl, Result)); + Error_Message : WolfSSL.Error_Message; begin + WolfSSL.Error (WolfSSL.Get_Error (Ssl, Result), + Message => Error_Message); if Result = Success then Put_Line (Error_Message.Text (1 .. Error_Message.Last)); end if; @@ -403,7 +404,7 @@ package body Tls_Server with SPARK_Mode is Put_Line ("Client connected successfully."); - Input := WolfSSL.Read (Ssl); + WolfSSL.Read (Ssl => Ssl, Result => Input); if not Input.Success then Put_Line ("Read error."); WolfSSL.Free (Ssl); @@ -438,7 +439,7 @@ package body Tls_Server with SPARK_Mode is end if; end if; - Output := WolfSSL.Write (Ssl, Reply); + WolfSSL.Write (Ssl, Reply, Result => Output); if not Output.Success then Put_Line ("ERROR: write failure."); elsif Output.Bytes_Written /= Reply'Length then diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index d17edf93deb..931d43912c8 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -117,7 +117,7 @@ package body WolfSSL is end if; end To_Ada; - WOLFSSL_SUCCESS : constant int := Get_WolfSSL_Success; + -- WOLFSSL_SUCCESS : constant int := Get_WolfSSL_Success; function Initialize_WolfSSL return int with Convention => C, @@ -632,7 +632,7 @@ package body WolfSSL is function Attach (Ssl : WolfSSL_Type; Socket : Integer) return Subprogram_Result is - Result : int := WolfSSL_Set_Fd (Ssl, int (Socket)); + Result : constant int := WolfSSL_Set_Fd (Ssl, int (Socket)); begin return Subprogram_Result (Result); end Attach; @@ -654,7 +654,7 @@ package body WolfSSL is function Accept_Connection (Ssl : WolfSSL_Type) return Subprogram_Result is - Result : int := WolfSSL_Accept (Ssl); + Result : constant int := WolfSSL_Accept (Ssl); begin return Subprogram_Result (Result); end Accept_Connection; @@ -705,19 +705,20 @@ package body WolfSSL is -- and and the application needs to call wolfSSL_read() again. -- Use wolfSSL_get_error() to get a specific error code. - function Read (Ssl : WolfSSL_Type) return Read_Result is + procedure Read (Ssl : WolfSSL_Type; + Result : out Read_Result) is Data : Byte_Array (1 .. Byte_Index'Last); Size : int; begin Size := WolfSSL_Read (Ssl, Data, int (Byte_Index'Last)); if Size <= 0 then - return (Success => False, - Last => 0, - Code => Subprogram_Result (Size)); + Result := (Success => False, + Last => 0, + Code => Subprogram_Result (Size)); else - return (Success => True, - Last => Byte_Index (Size), - Buffer => Data (1 .. Byte_Index (Size))); + Result := (Success => True, + Last => Byte_Index (Size), + Buffer => Data (1 .. Byte_Index (Size))); end if; end Read; @@ -728,17 +729,18 @@ package body WolfSSL is External_Name => "wolfSSL_write", Import => True; - function Write (Ssl : WolfSSL_Type; - Data : Byte_Array) return Write_Result is + procedure Write (Ssl : WolfSSL_Type; + Data : Byte_Array; + Result : out Write_Result) is Size : constant int := Data'Length; - Result : int; + R : int; begin - Result := WolfSSL_Write (Ssl, Data, Size); - if Result > 0 then - return (Success => True, - Bytes_Written => Byte_Index (Result)); + R := WolfSSL_Write (Ssl, Data, Size); + if R > 0 then + Result := (Success => True, + Bytes_Written => Byte_Index (R)); else - return (Success => False, Code => Subprogram_Result (Result)); + Result := (Success => False, Code => Subprogram_Result (R)); end if; end Write; @@ -796,7 +798,8 @@ package body WolfSSL is External_Name => "wolfSSL_ERR_error_string_n", Import => True; - function Error (Code : Error_Code) return Error_Message is + procedure Error (Code : in Error_Code; + Message : out Error_Message) is S : String (1 .. Error_Message_Index'Last); B : Byte_Array (1 .. size_t (Error_Message_Index'Last)); C : Natural; @@ -813,8 +816,8 @@ package body WolfSSL is Target => S, Count => C, Trim_Nul => True); - return (Last => C, - Text => S (1 .. C)); + Message := (Last => C, + Text => S (1 .. C)); end Error; function Get_WolfSSL_Max_Error_Size return int with diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 3a079d3916c..e35e90cf6f5 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -354,7 +354,8 @@ package WolfSSL with SPARK_Mode is end case; end record; - function Read (Ssl : WolfSSL_Type) return Read_Result with + procedure Read (Ssl : WolfSSL_Type; + Result : out Read_Result) with Pre => Is_Valid (Ssl); -- This function reads a number of bytes from the SSL session (ssl) -- internal read buffer into the buffer data. The bytes read are @@ -382,8 +383,9 @@ package WolfSSL with SPARK_Mode is end case; end record; - function Write (Ssl : WolfSSL_Type; - Data : Byte_Array) return Write_Result with + procedure Write (Ssl : WolfSSL_Type; + Data : Byte_Array; + Result : out Write_Result) with Pre => Is_Valid (Ssl); -- The number of bytes written is returned. -- This function writes bytes from the buffer, Data, @@ -475,7 +477,8 @@ package WolfSSL with SPARK_Mode is Text : String (1 .. Last); end record; - function Error (Code : Error_Code) return Error_Message; + procedure Error (Code : in Error_Code; + Message : out Error_Message); -- This function converts an error code returned by Get_Error(..) -- into a more human readable error string. Code is the error code -- returned by Get_error(). The maximum length of error strings is From a175045f2fadbda22d38d35693b56ecd0f24bf30 Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Thu, 11 Dec 2025 02:34:41 +0100 Subject: [PATCH 05/51] Silenced many warnings related to no exception propagation for zero footprint run-time. --- wrapper/Ada/rsa_verify_main.adb | 191 ++++++---- wrapper/Ada/wolfssl-full_runtime.adb | 4 +- wrapper/Ada/wolfssl.adb | 515 +++++++++++++++------------ wrapper/Ada/wolfssl.ads | 36 +- 4 files changed, 444 insertions(+), 302 deletions(-) diff --git a/wrapper/Ada/rsa_verify_main.adb b/wrapper/Ada/rsa_verify_main.adb index f7dcbc9ab89..2e1dacd97d9 100644 --- a/wrapper/Ada/rsa_verify_main.adb +++ b/wrapper/Ada/rsa_verify_main.adb @@ -13,70 +13,130 @@ procedure Rsa_Verify_Main is -- RSA public key to verify with. Rsa_Public_key_2048 : constant WolfSSL.Byte_Array := - (To_C (16#C3#), To_C (16#03#), To_C (16#D1#), To_C (16#2B#), - To_C (16#FE#), To_C (16#39#), To_C (16#A4#), To_C (16#32#), - To_C (16#45#), To_C (16#3B#), To_C (16#53#), To_C (16#C8#), - To_C (16#84#), To_C (16#2B#), To_C (16#2A#), To_C (16#7C#), - To_C (16#74#), To_C (16#9A#), To_C (16#BD#), To_C (16#AA#), - To_C (16#2A#), To_C (16#52#), To_C (16#07#), To_C (16#47#), - To_C (16#D6#), To_C (16#A6#), To_C (16#36#), To_C (16#B2#), - To_C (16#07#), To_C (16#32#), To_C (16#8E#), To_C (16#D0#), - To_C (16#BA#), To_C (16#69#), To_C (16#7B#), To_C (16#C6#), - To_C (16#C3#), To_C (16#44#), To_C (16#9E#), To_C (16#D4#), - To_C (16#81#), To_C (16#48#), To_C (16#FD#), To_C (16#2D#), - To_C (16#68#), To_C (16#A2#), To_C (16#8B#), To_C (16#67#), - To_C (16#BB#), To_C (16#A1#), To_C (16#75#), To_C (16#C8#), - To_C (16#36#), To_C (16#2C#), To_C (16#4A#), To_C (16#D2#), - To_C (16#1B#), To_C (16#F7#), To_C (16#8B#), To_C (16#BA#), - To_C (16#CF#), To_C (16#0D#), To_C (16#F9#), To_C (16#EF#), - To_C (16#EC#), To_C (16#F1#), To_C (16#81#), To_C (16#1E#), - To_C (16#7B#), To_C (16#9B#), To_C (16#03#), To_C (16#47#), - To_C (16#9A#), To_C (16#BF#), To_C (16#65#), To_C (16#CC#), - To_C (16#7F#), To_C (16#65#), To_C (16#24#), To_C (16#69#), - To_C (16#A6#), To_C (16#E8#), To_C (16#14#), To_C (16#89#), - To_C (16#5B#), To_C (16#E4#), To_C (16#34#), To_C (16#F7#), - To_C (16#C5#), To_C (16#B0#), To_C (16#14#), To_C (16#93#), - To_C (16#F5#), To_C (16#67#), To_C (16#7B#), To_C (16#3A#), - To_C (16#7A#), To_C (16#78#), To_C (16#E1#), To_C (16#01#), - To_C (16#56#), To_C (16#56#), To_C (16#91#), To_C (16#A6#), - To_C (16#13#), To_C (16#42#), To_C (16#8D#), To_C (16#D2#), - To_C (16#3C#), To_C (16#40#), To_C (16#9C#), To_C (16#4C#), - To_C (16#EF#), To_C (16#D1#), To_C (16#86#), To_C (16#DF#), - To_C (16#37#), To_C (16#51#), To_C (16#1B#), To_C (16#0C#), - To_C (16#A1#), To_C (16#3B#), To_C (16#F5#), To_C (16#F1#), - To_C (16#A3#), To_C (16#4A#), To_C (16#35#), To_C (16#E4#), - To_C (16#E1#), To_C (16#CE#), To_C (16#96#), To_C (16#DF#), - To_C (16#1B#), To_C (16#7E#), To_C (16#BF#), To_C (16#4E#), - To_C (16#97#), To_C (16#D0#), To_C (16#10#), To_C (16#E8#), - To_C (16#A8#), To_C (16#08#), To_C (16#30#), To_C (16#81#), - To_C (16#AF#), To_C (16#20#), To_C (16#0B#), To_C (16#43#), - To_C (16#14#), To_C (16#C5#), To_C (16#74#), To_C (16#67#), - To_C (16#B4#), To_C (16#32#), To_C (16#82#), To_C (16#6F#), - To_C (16#8D#), To_C (16#86#), To_C (16#C2#), To_C (16#88#), - To_C (16#40#), To_C (16#99#), To_C (16#36#), To_C (16#83#), - To_C (16#BA#), To_C (16#1E#), To_C (16#40#), To_C (16#72#), - To_C (16#22#), To_C (16#17#), To_C (16#D7#), To_C (16#52#), - To_C (16#65#), To_C (16#24#), To_C (16#73#), To_C (16#B0#), - To_C (16#CE#), To_C (16#EF#), To_C (16#19#), To_C (16#CD#), - To_C (16#AE#), To_C (16#FF#), To_C (16#78#), To_C (16#6C#), - To_C (16#7B#), To_C (16#C0#), To_C (16#12#), To_C (16#03#), - To_C (16#D4#), To_C (16#4E#), To_C (16#72#), To_C (16#0D#), - To_C (16#50#), To_C (16#6D#), To_C (16#3B#), To_C (16#A3#), - To_C (16#3B#), To_C (16#A3#), To_C (16#99#), To_C (16#5E#), - To_C (16#9D#), To_C (16#C8#), To_C (16#D9#), To_C (16#0C#), - To_C (16#85#), To_C (16#B3#), To_C (16#D9#), To_C (16#8A#), - To_C (16#D9#), To_C (16#54#), To_C (16#26#), To_C (16#DB#), - To_C (16#6D#), To_C (16#FA#), To_C (16#AC#), To_C (16#BB#), - To_C (16#FF#), To_C (16#25#), To_C (16#4C#), To_C (16#C4#), - To_C (16#D1#), To_C (16#79#), To_C (16#F4#), To_C (16#71#), - To_C (16#D3#), To_C (16#86#), To_C (16#40#), To_C (16#18#), - To_C (16#13#), To_C (16#B0#), To_C (16#63#), To_C (16#B5#), - To_C (16#72#), To_C (16#4E#), To_C (16#30#), To_C (16#C4#), - To_C (16#97#), To_C (16#84#), To_C (16#86#), To_C (16#2D#), - To_C (16#56#), To_C (16#2F#), To_C (16#D7#), To_C (16#15#), - To_C (16#F7#), To_C (16#7F#), To_C (16#C0#), To_C (16#AE#), - To_C (16#F5#), To_C (16#FC#), To_C (16#5B#), To_C (16#E5#), - To_C (16#FB#), To_C (16#A1#), To_C (16#BA#), To_C (16#D3#)); + (To_C (16#30#), To_C (16#82#), To_C (16#01#), To_C (16#22#), To_C (16#30#), + To_C (16#0D#), To_C (16#06#), To_C (16#09#), To_C (16#2A#), To_C (16#86#), + To_C (16#48#), To_C (16#86#), To_C (16#F7#), To_C (16#0D#), To_C (16#01#), + To_C (16#01#), To_C (16#01#), To_C (16#05#), To_C (16#00#), To_C (16#03#), + To_C (16#82#), To_C (16#01#), To_C (16#0F#), To_C (16#00#), To_C (16#30#), + To_C (16#82#), To_C (16#01#), To_C (16#0A#), To_C (16#02#), To_C (16#82#), + To_C (16#01#), To_C (16#01#), To_C (16#00#), To_C (16#C3#), To_C (16#03#), + To_C (16#D1#), To_C (16#2B#), To_C (16#FE#), To_C (16#39#), To_C (16#A4#), + To_C (16#32#), To_C (16#45#), To_C (16#3B#), To_C (16#53#), To_C (16#C8#), + To_C (16#84#), To_C (16#2B#), To_C (16#2A#), To_C (16#7C#), To_C (16#74#), + To_C (16#9A#), To_C (16#BD#), To_C (16#AA#), To_C (16#2A#), To_C (16#52#), + To_C (16#07#), To_C (16#47#), To_C (16#D6#), To_C (16#A6#), To_C (16#36#), + To_C (16#B2#), To_C (16#07#), To_C (16#32#), To_C (16#8E#), To_C (16#D0#), + To_C (16#BA#), To_C (16#69#), To_C (16#7B#), To_C (16#C6#), To_C (16#C3#), + To_C (16#44#), To_C (16#9E#), To_C (16#D4#), To_C (16#81#), To_C (16#48#), + To_C (16#FD#), To_C (16#2D#), To_C (16#68#), To_C (16#A2#), To_C (16#8B#), + To_C (16#67#), To_C (16#BB#), To_C (16#A1#), To_C (16#75#), To_C (16#C8#), + To_C (16#36#), To_C (16#2C#), To_C (16#4A#), To_C (16#D2#), To_C (16#1B#), + To_C (16#F7#), To_C (16#8B#), To_C (16#BA#), To_C (16#CF#), To_C (16#0D#), + To_C (16#F9#), To_C (16#EF#), To_C (16#EC#), To_C (16#F1#), To_C (16#81#), + To_C (16#1E#), To_C (16#7B#), To_C (16#9B#), To_C (16#03#), To_C (16#47#), + To_C (16#9A#), To_C (16#BF#), To_C (16#65#), To_C (16#CC#), To_C (16#7F#), + To_C (16#65#), To_C (16#24#), To_C (16#69#), To_C (16#A6#), To_C (16#E8#), + To_C (16#14#), To_C (16#89#), To_C (16#5B#), To_C (16#E4#), To_C (16#34#), + To_C (16#F7#), To_C (16#C5#), To_C (16#B0#), To_C (16#14#), To_C (16#93#), + To_C (16#F5#), To_C (16#67#), To_C (16#7B#), To_C (16#3A#), To_C (16#7A#), + To_C (16#78#), To_C (16#E1#), To_C (16#01#), To_C (16#56#), To_C (16#56#), + To_C (16#91#), To_C (16#A6#), To_C (16#13#), To_C (16#42#), To_C (16#8D#), + To_C (16#D2#), To_C (16#3C#), To_C (16#40#), To_C (16#9C#), To_C (16#4C#), + To_C (16#EF#), To_C (16#D1#), To_C (16#86#), To_C (16#DF#), To_C (16#37#), + To_C (16#51#), To_C (16#1B#), To_C (16#0C#), To_C (16#A1#), To_C (16#3B#), + To_C (16#F5#), To_C (16#F1#), To_C (16#A3#), To_C (16#4A#), To_C (16#35#), + To_C (16#E4#), To_C (16#E1#), To_C (16#CE#), To_C (16#96#), To_C (16#DF#), + To_C (16#1B#), To_C (16#7E#), To_C (16#BF#), To_C (16#4E#), To_C (16#97#), + To_C (16#D0#), To_C (16#10#), To_C (16#E8#), To_C (16#A8#), To_C (16#08#), + To_C (16#30#), To_C (16#81#), To_C (16#AF#), To_C (16#20#), To_C (16#0B#), + To_C (16#43#), To_C (16#14#), To_C (16#C5#), To_C (16#74#), To_C (16#67#), + To_C (16#B4#), To_C (16#32#), To_C (16#82#), To_C (16#6F#), To_C (16#8D#), + To_C (16#86#), To_C (16#C2#), To_C (16#88#), To_C (16#40#), To_C (16#99#), + To_C (16#36#), To_C (16#83#), To_C (16#BA#), To_C (16#1E#), To_C (16#40#), + To_C (16#72#), To_C (16#22#), To_C (16#17#), To_C (16#D7#), To_C (16#52#), + To_C (16#65#), To_C (16#24#), To_C (16#73#), To_C (16#B0#), To_C (16#CE#), + To_C (16#EF#), To_C (16#19#), To_C (16#CD#), To_C (16#AE#), To_C (16#FF#), + To_C (16#78#), To_C (16#6C#), To_C (16#7B#), To_C (16#C0#), To_C (16#12#), + To_C (16#03#), To_C (16#D4#), To_C (16#4E#), To_C (16#72#), To_C (16#0D#), + To_C (16#50#), To_C (16#6D#), To_C (16#3B#), To_C (16#A3#), To_C (16#3B#), + To_C (16#A3#), To_C (16#99#), To_C (16#5E#), To_C (16#9D#), To_C (16#C8#), + To_C (16#D9#), To_C (16#0C#), To_C (16#85#), To_C (16#B3#), To_C (16#D9#), + To_C (16#8A#), To_C (16#D9#), To_C (16#54#), To_C (16#26#), To_C (16#DB#), + To_C (16#6D#), To_C (16#FA#), To_C (16#AC#), To_C (16#BB#), To_C (16#FF#), + To_C (16#25#), To_C (16#4C#), To_C (16#C4#), To_C (16#D1#), To_C (16#79#), + To_C (16#F4#), To_C (16#71#), To_C (16#D3#), To_C (16#86#), To_C (16#40#), + To_C (16#18#), To_C (16#13#), To_C (16#B0#), To_C (16#63#), To_C (16#B5#), + To_C (16#72#), To_C (16#4E#), To_C (16#30#), To_C (16#C4#), To_C (16#97#), + To_C (16#84#), To_C (16#86#), To_C (16#2D#), To_C (16#56#), To_C (16#2F#), + To_C (16#D7#), To_C (16#15#), To_C (16#F7#), To_C (16#7F#), To_C (16#C0#), + To_C (16#AE#), To_C (16#F5#), To_C (16#FC#), To_C (16#5B#), To_C (16#E5#), + To_C (16#FB#), To_C (16#A1#), To_C (16#BA#), To_C (16#D3#), To_C (16#02#), + To_C (16#03#), To_C (16#01#), To_C (16#00#), To_C (16#01#)); + + -- (To_C (16#C3#), To_C (16#03#), To_C (16#D1#), To_C (16#2B#), + -- To_C (16#FE#), To_C (16#39#), To_C (16#A4#), To_C (16#32#), + -- To_C (16#45#), To_C (16#3B#), To_C (16#53#), To_C (16#C8#), + -- To_C (16#84#), To_C (16#2B#), To_C (16#2A#), To_C (16#7C#), + -- To_C (16#74#), To_C (16#9A#), To_C (16#BD#), To_C (16#AA#), + -- To_C (16#2A#), To_C (16#52#), To_C (16#07#), To_C (16#47#), + -- To_C (16#D6#), To_C (16#A6#), To_C (16#36#), To_C (16#B2#), + -- To_C (16#07#), To_C (16#32#), To_C (16#8E#), To_C (16#D0#), + -- To_C (16#BA#), To_C (16#69#), To_C (16#7B#), To_C (16#C6#), + -- To_C (16#C3#), To_C (16#44#), To_C (16#9E#), To_C (16#D4#), + -- To_C (16#81#), To_C (16#48#), To_C (16#FD#), To_C (16#2D#), + -- To_C (16#68#), To_C (16#A2#), To_C (16#8B#), To_C (16#67#), + -- To_C (16#BB#), To_C (16#A1#), To_C (16#75#), To_C (16#C8#), + -- To_C (16#36#), To_C (16#2C#), To_C (16#4A#), To_C (16#D2#), + -- To_C (16#1B#), To_C (16#F7#), To_C (16#8B#), To_C (16#BA#), + -- To_C (16#CF#), To_C (16#0D#), To_C (16#F9#), To_C (16#EF#), + -- To_C (16#EC#), To_C (16#F1#), To_C (16#81#), To_C (16#1E#), + -- To_C (16#7B#), To_C (16#9B#), To_C (16#03#), To_C (16#47#), + -- To_C (16#9A#), To_C (16#BF#), To_C (16#65#), To_C (16#CC#), + -- To_C (16#7F#), To_C (16#65#), To_C (16#24#), To_C (16#69#), + -- To_C (16#A6#), To_C (16#E8#), To_C (16#14#), To_C (16#89#), + -- To_C (16#5B#), To_C (16#E4#), To_C (16#34#), To_C (16#F7#), + -- To_C (16#C5#), To_C (16#B0#), To_C (16#14#), To_C (16#93#), + -- To_C (16#F5#), To_C (16#67#), To_C (16#7B#), To_C (16#3A#), + -- To_C (16#7A#), To_C (16#78#), To_C (16#E1#), To_C (16#01#), + -- To_C (16#56#), To_C (16#56#), To_C (16#91#), To_C (16#A6#), + -- To_C (16#13#), To_C (16#42#), To_C (16#8D#), To_C (16#D2#), + -- To_C (16#3C#), To_C (16#40#), To_C (16#9C#), To_C (16#4C#), + -- To_C (16#EF#), To_C (16#D1#), To_C (16#86#), To_C (16#DF#), + -- To_C (16#37#), To_C (16#51#), To_C (16#1B#), To_C (16#0C#), + -- To_C (16#A1#), To_C (16#3B#), To_C (16#F5#), To_C (16#F1#), + -- To_C (16#A3#), To_C (16#4A#), To_C (16#35#), To_C (16#E4#), + -- To_C (16#E1#), To_C (16#CE#), To_C (16#96#), To_C (16#DF#), + -- To_C (16#1B#), To_C (16#7E#), To_C (16#BF#), To_C (16#4E#), + -- To_C (16#97#), To_C (16#D0#), To_C (16#10#), To_C (16#E8#), + -- To_C (16#A8#), To_C (16#08#), To_C (16#30#), To_C (16#81#), + -- To_C (16#AF#), To_C (16#20#), To_C (16#0B#), To_C (16#43#), + -- To_C (16#14#), To_C (16#C5#), To_C (16#74#), To_C (16#67#), + -- To_C (16#B4#), To_C (16#32#), To_C (16#82#), To_C (16#6F#), + -- To_C (16#8D#), To_C (16#86#), To_C (16#C2#), To_C (16#88#), + -- To_C (16#40#), To_C (16#99#), To_C (16#36#), To_C (16#83#), + -- To_C (16#BA#), To_C (16#1E#), To_C (16#40#), To_C (16#72#), + -- To_C (16#22#), To_C (16#17#), To_C (16#D7#), To_C (16#52#), + -- To_C (16#65#), To_C (16#24#), To_C (16#73#), To_C (16#B0#), + -- To_C (16#CE#), To_C (16#EF#), To_C (16#19#), To_C (16#CD#), + -- To_C (16#AE#), To_C (16#FF#), To_C (16#78#), To_C (16#6C#), + -- To_C (16#7B#), To_C (16#C0#), To_C (16#12#), To_C (16#03#), + -- To_C (16#D4#), To_C (16#4E#), To_C (16#72#), To_C (16#0D#), + -- To_C (16#50#), To_C (16#6D#), To_C (16#3B#), To_C (16#A3#), + -- To_C (16#3B#), To_C (16#A3#), To_C (16#99#), To_C (16#5E#), + -- To_C (16#9D#), To_C (16#C8#), To_C (16#D9#), To_C (16#0C#), + -- To_C (16#85#), To_C (16#B3#), To_C (16#D9#), To_C (16#8A#), + -- To_C (16#D9#), To_C (16#54#), To_C (16#26#), To_C (16#DB#), + -- To_C (16#6D#), To_C (16#FA#), To_C (16#AC#), To_C (16#BB#), + -- To_C (16#FF#), To_C (16#25#), To_C (16#4C#), To_C (16#C4#), + -- To_C (16#D1#), To_C (16#79#), To_C (16#F4#), To_C (16#71#), + -- To_C (16#D3#), To_C (16#86#), To_C (16#40#), To_C (16#18#), + -- To_C (16#13#), To_C (16#B0#), To_C (16#63#), To_C (16#B5#), + -- To_C (16#72#), To_C (16#4E#), To_C (16#30#), To_C (16#C4#), + -- To_C (16#97#), To_C (16#84#), To_C (16#86#), To_C (16#2D#), + -- To_C (16#56#), To_C (16#2F#), To_C (16#D7#), To_C (16#15#), + -- To_C (16#F7#), To_C (16#7F#), To_C (16#C0#), To_C (16#AE#), + -- To_C (16#F5#), To_C (16#FC#), To_C (16#5B#), To_C (16#E5#), + -- To_C (16#FB#), To_C (16#A1#), To_C (16#BA#), To_C (16#D3#)); Message : constant WolfSSL.Byte_Array := (To_C (16#54#), To_C (16#68#), To_C (16#69#), To_C (16#73#), @@ -223,4 +283,7 @@ begin New_Line; return; end if; + New_Line; + Put (WolfSSL.Failure'Image); + New_Line; end Rsa_Verify_Main; diff --git a/wrapper/Ada/wolfssl-full_runtime.adb b/wrapper/Ada/wolfssl-full_runtime.adb index 4e88f3a008f..3f154ae0958 100644 --- a/wrapper/Ada/wolfssl-full_runtime.adb +++ b/wrapper/Ada/wolfssl-full_runtime.adb @@ -36,7 +36,9 @@ package body WolfSSL.Full_Runtime is (ssl => Ssl, peer => Sin'Unchecked_Access, peerSz => Interfaces.C.unsigned (Length))); - + exception + when others => + return Exception_Error; end DTLS_Set_Peer; procedure WolfSSL_Set_Psk_Client_Callback diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index 931d43912c8..1a013fa708d 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -31,92 +31,6 @@ package body WolfSSL is nul : constant Byte_Type := Byte_Type'First; - -- Convert String to char_array (procedure form) - -- This subprogram originates from the full Ada run-time - -- but is not present on the Zero Footprint run-time, - -- therefore it is included here. - procedure To_C - (Item : String; - Target : out Byte_Array; - Count : out size_t; - Append_Nul : Boolean := True) - is - To : size_t; - begin - if Target'Length < Item'Length then - raise Constraint_Error; - else - To := Target'First; - for From in Item'Range loop - Target (To) := Byte_Type (Item (From)); - To := To + 1; - end loop; - - if Append_Nul then - if To > Target'Last then - raise Constraint_Error; - else - Target (To) := nul; - Count := Item'Length + 1; - end if; - else - Count := Item'Length; - end if; - end if; - end To_C; - - -- Convert char_array to String (procedure form) - -- This subprogram originates from the full Ada run-time - -- but is not present on the Zero Footprint run-time, - -- therefore it is included here. - procedure To_Ada - (Item : Byte_Array; - Target : out String; - Count : out Natural; - Trim_Nul : Boolean := True) - is - use type Byte_Type; - - From : size_t; - To : Integer; - begin - if Trim_Nul then - From := Item'First; - loop - if From > Item'Last then - raise Terminator_Error; - elsif Item (From) = nul then - exit; - else - From := From + 1; - end if; - end loop; - - Count := Natural (From - Item'First); - - else - Count := Item'Length; - end if; - - if Count > Target'Length then - raise Constraint_Error; - - else - From := Item'First; - To := Target'First; - - for J in 1 .. Count loop - Target (To) := Character (Item (From)); - -- Avoid possible overflow when incrementing To in the last - -- iteration of the loop. - exit when J = Count; - - From := From + 1; - To := To + 1; - end loop; - end if; - end To_Ada; - -- WOLFSSL_SUCCESS : constant int := Get_WolfSSL_Success; function Initialize_WolfSSL return int with @@ -297,20 +211,28 @@ package body WolfSSL is procedure Set_Verify (Context : Context_Type; Mode : Mode_Type) is + pragma Warnings (Off, "pragma Restrictions (No_Exception_Propagation)"); + -- The values that Set_Verify may be called with have first + -- been int values, then converted into Mode_Type values and + -- here they are converted back to int. This can never fail + -- unless there is hardware failure or cosmic radiation has + -- done a bit flip. + V : constant int := int (Mode); + pragma Warnings (On, "pragma Restrictions (No_Exception_Propagation)"); begin WolfSSL_CTX_Set_Verify (Context => Context, - Mode => int (Mode), + Mode => V, Callback => null); end Set_Verify; - function WolfSSL_Get_Verify(Context : Context_Type) return int with + function WolfSSL_Get_Verify (Context : Context_Type) return int with Convention => C, External_Name => "wolfSSL_CTX_get_verify_mode", Import => True; function Get_Verify (Context : Context_Type) return Mode_Type is begin - return Mode_Type (WolfSSL_Get_Verify(Context)); + return Mode_Type (WolfSSL_Get_Verify (Context)); end Get_Verify; function Use_Certificate_File (Context : Context_Type; @@ -325,17 +247,22 @@ package body WolfSSL is File : String; Format : File_Format) return Subprogram_Result is - Ctx : constant Context_Type := Context; - C : size_t; - F : Byte_Array (1 .. File'Length + 1); - Result : int; begin - To_C (Item => File, - Target => F, - Count => C, - Append_Nul => True); - Result := Use_Certificate_File (Ctx, F (1 .. C), int (Format)); - return Subprogram_Result (Result); + declare + Ctx : constant Context_Type := Context; + F : Byte_Array (1 .. File'Length + 1); + Result : int; + begin + for I in File'Range loop + F (F'First + Byte_Index (I - File'First)) := Byte_Type (File (I)); + end loop; + F (F'Last) := nul; + Result := Use_Certificate_File (Ctx, F, int (Format)); + return Subprogram_Result (Result); + end; + exception + when others => + return Exception_Error; end Use_Certificate_File; function Use_Certificate_Buffer (Context : Context_Type; @@ -356,6 +283,9 @@ package body WolfSSL is Result := Use_Certificate_Buffer (Context, Input, Input'Length, int (Format)); return Subprogram_Result (Result); + exception + when others => + return Exception_Error; end Use_Certificate_Buffer; function Use_Private_Key_File (Context : Context_Type; @@ -370,17 +300,22 @@ package body WolfSSL is File : String; Format : File_Format) return Subprogram_Result is - Ctx : constant Context_Type := Context; - C : size_t; - F : Byte_Array (1 .. File'Length + 1); - Result : int; begin - To_C (Item => File, - Target => F, - Count => C, - Append_Nul => True); - Result := Use_Private_Key_File (Ctx, F (1 .. C), int (Format)); - return Subprogram_Result (Result); + declare + Ctx : constant Context_Type := Context; + F : Byte_Array (1 .. File'Length + 1); + Result : int; + begin + for I in File'Range loop + F (F'First + Byte_Index (I - File'First)) := Byte_Type (File (I)); + end loop; + F (F'Last) := Byte_Type'Val (0); + Result := Use_Private_Key_File (Ctx, F, int (Format)); + return Subprogram_Result (Result); + end; + exception + when others => + return Exception_Error; end Use_Private_Key_File; function Use_Private_Key_Buffer (Context : Context_Type; @@ -401,6 +336,9 @@ package body WolfSSL is Result := Use_Private_Key_Buffer (Context, Input, Input'Length, int (Format)); return Subprogram_Result (Result); + exception + when others => + return Exception_Error; end Use_Private_Key_Buffer; function Load_Verify_Locations1 @@ -454,47 +392,48 @@ package body WolfSSL is File : String; Path : String) return Subprogram_Result is - Ctx : constant Context_Type := Context; - FC : size_t; -- File Count, specifies the characters used in F. - F : aliased Byte_Array := (1 .. File'Length + 1 => '#'); - - PC : size_t; -- Path Count, specifies the characters used in P. - P : aliased Byte_Array := (1 .. Path'Length + 1 => '#'); - - Result : int; begin - if File = "" then - if Path = "" then - Result := Load_Verify_Locations4 (Ctx, null, null); - else - To_C (Item => Path, - Target => P, - Count => PC, - Append_Nul => True); - Result := Load_Verify_Locations3 (Ctx, null, P); - end if; - else - To_C (Item => File, - Target => F, - Count => FC, - Append_Nul => True); - if Path = "" then - Result := Load_Verify_Locations2 (Ctx, F, null); + declare + Ctx : constant Context_Type := Context; + F : aliased Byte_Array := (1 .. File'Length + 1 => '#'); + P : aliased Byte_Array := (1 .. Path'Length + 1 => '#'); + Result : int; + begin + if File = "" then + if Path = "" then + Result := Load_Verify_Locations4 (Ctx, null, null); + else + for I in Path'Range loop + P (P'First + Byte_Index (I - Path'First)) := + Byte_Type (Path (I)); + end loop; + P (P'Last) := nul; + Result := Load_Verify_Locations3 (Ctx, null, P); + end if; else - To_C (Item => Path, - Target => P, - Count => PC, - Append_Nul => True); - To_C (Item => Path, - Target => P, - Count => PC, - Append_Nul => True); - Result := Load_Verify_Locations1 (Context => Ctx, - File => F, - Path => P); + for I in File'Range loop + F (F'First + Byte_Index (I - File'First)) := + Byte_Type (File (I)); + end loop; + F (F'Last) := nul; + if Path = "" then + Result := Load_Verify_Locations2 (Ctx, F, null); + else + for I in Path'Range loop + P (P'First + Byte_Index (I - Path'First)) := + Byte_Type (Path (I)); + end loop; + P (P'Last) := nul; + Result := Load_Verify_Locations1 (Context => Ctx, + File => F, + Path => P); + end if; end if; - end if; - return Subprogram_Result (Result); + return Subprogram_Result (Result); + end; + exception + when others => + return Exception_Error; end Load_Verify_Locations; function Load_Verify_Buffer @@ -517,6 +456,9 @@ package body WolfSSL is Size => Input'Length, Format => int(Format)); return Subprogram_Result (Result); + exception + when others => + return Exception_Error; end Load_Verify_Buffer; function Is_Valid (Ssl : WolfSSL_Type) return Boolean is @@ -548,16 +490,22 @@ package body WolfSSL is File : String; Format : File_Format) return Subprogram_Result is - C : size_t; - F : Byte_Array (1 .. File'Length + 1); - Result : int; begin - To_C (Item => File, - Target => F, - Count => C, - Append_Nul => True); - Result := Use_Certificate_File (Ssl, F (1 .. C), int (Format)); - return Subprogram_Result (Result); + declare + F : Byte_Array (1 .. File'Length + 1); + Result : int; + begin + for I in File'Range loop + F (F'First + Byte_Index (I - File'First)) := + Byte_Type (File (I)); + end loop; + F (F'Last) := nul; + Result := Use_Certificate_File (Ssl, F, int (Format)); + return Subprogram_Result (Result); + end; + exception + when others => + return Exception_Error; end Use_Certificate_File; function Use_Certificate_Buffer (Ssl : WolfSSL_Type; @@ -578,6 +526,9 @@ package body WolfSSL is Result := Use_Certificate_Buffer (Ssl, Input, Input'Length, int (Format)); return Subprogram_Result (Result); + exception + when others => + return Exception_Error; end Use_Certificate_Buffer; function Use_Private_Key_File (Ssl : WolfSSL_Type; @@ -592,16 +543,21 @@ package body WolfSSL is File : String; Format : File_Format) return Subprogram_Result is - C : size_t; - F : Byte_Array (1 .. File'Length + 1); - Result : int; begin - To_C (Item => File, - Target => F, - Count => C, - Append_Nul => True); - Result := Use_Private_Key_File (Ssl, F (1 .. C), int (Format)); - return Subprogram_Result (Result); + declare + F : Byte_Array (1 .. File'Length + 1); + Result : int; + begin + for I in File'Range loop + F (F'First + Byte_Index (I - File'First)) := Byte_Type (File (I)); + end loop; + F (F'Last) := nul; + Result := Use_Private_Key_File (Ssl, F, int (Format)); + return Subprogram_Result (Result); + end; + exception + when others => + return Exception_Error; end Use_Private_Key_File; function Use_Private_Key_Buffer (Ssl : WolfSSL_Type; @@ -622,6 +578,9 @@ package body WolfSSL is Result := Use_Private_Key_Buffer (Ssl, Input, Input'Length, int (Format)); return Subprogram_Result (Result); + exception + when others => + return Exception_Error; end Use_Private_Key_Buffer; function WolfSSL_Set_Fd (Ssl : WolfSSL_Type; Fd : int) return int with @@ -707,19 +666,28 @@ package body WolfSSL is procedure Read (Ssl : WolfSSL_Type; Result : out Read_Result) is - Data : Byte_Array (1 .. Byte_Index'Last); - Size : int; begin - Size := WolfSSL_Read (Ssl, Data, int (Byte_Index'Last)); - if Size <= 0 then - Result := (Success => False, - Last => 0, - Code => Subprogram_Result (Size)); - else - Result := (Success => True, - Last => Byte_Index (Size), - Buffer => Data (1 .. Byte_Index (Size))); - end if; + Result := (Success => False, -- In case of exception. + Last => 0, + Code => Subprogram_Result (Exception_Error)); + declare + Data : Byte_Array (1 .. Byte_Index'Last); + Size : int; + begin + Size := WolfSSL_Read (Ssl, Data, int (Byte_Index'Last)); + if Size <= 0 then + Result := (Success => False, + Last => 0, + Code => Subprogram_Result (Size)); + else + Result := (Success => True, + Last => Byte_Index (Size), + Buffer => Data (1 .. Byte_Index (Size))); + end if; + end; + exception + when others => + null; end Read; function WolfSSL_Write (Ssl : WolfSSL_Type; @@ -732,16 +700,24 @@ package body WolfSSL is procedure Write (Ssl : WolfSSL_Type; Data : Byte_Array; Result : out Write_Result) is - Size : constant int := Data'Length; - R : int; begin - R := WolfSSL_Write (Ssl, Data, Size); - if R > 0 then - Result := (Success => True, - Bytes_Written => Byte_Index (R)); - else - Result := (Success => False, Code => Subprogram_Result (R)); - end if; + Result := (Success => False, + Code => Subprogram_Result (Exception_Error)); + declare + Size : constant int := Data'Length; + R : int; + begin + R := WolfSSL_Write (Ssl, Data, Size); + if R > 0 then + Result := (Success => True, + Bytes_Written => Byte_Index (R)); + else + Result := (Success => False, Code => Subprogram_Result (R)); + end if; + end; + exception + when others => + null; end Write; function WolfSSL_Shutdown (Ssl : WolfSSL_Type) return int with @@ -799,25 +775,38 @@ package body WolfSSL is Import => True; procedure Error (Code : in Error_Code; - Message : out Error_Message) is - S : String (1 .. Error_Message_Index'Last); - B : Byte_Array (1 .. size_t (Error_Message_Index'Last)); - C : Natural; + Message : in out Error_Message) is + use type Byte_Type; -- Use unchecked conversion instead of type conversion to mimic C style -- conversion from int to unsigned long, avoiding the Ada overflow check. function To_Unsigned_Long is new Ada.Unchecked_Conversion (Source => long, Target => unsigned_long); begin - WolfSSL_Error_String (Error => To_Unsigned_Long (long (Code)), - Data => B, - Size => To_Unsigned_Long (long (B'Last))); - To_Ada (Item => B, - Target => S, - Count => C, - Trim_Nul => True); - Message := (Last => C, - Text => S (1 .. C)); + declare + S : String (1 .. Error_Message_Index'Last); + B : Byte_Array (1 .. size_t (Error_Message_Index'Last)); + L : Positive; + begin + WolfSSL_Error_String (Error => To_Unsigned_Long (long (Code)), + Data => B, + Size => To_Unsigned_Long (long (B'Last))); + for I in B'Range loop + L := S'First + Natural (I - B'First); + S (L) := Character (B (I)); + exit when B (I) = nul; + end loop; + if S (L) = Character (nul) then + Message := (Last => L - 1, + Text => S (1 .. L - 1)); + else + Message := (Last => L, + Text => S (1 .. L)); + end if; + end; + exception + when others => + null; end Error; function Get_WolfSSL_Max_Error_Size return int with @@ -855,6 +844,9 @@ package body WolfSSL is Key := Ada_New_RSA (int (Index)); R := Init_RSA_Key (Key, null); Result := Integer (R); + exception + when others => + Result := Exception_Error; end Create_RSA; function RSA_Public_Key_Decode (Input : Byte_Array; @@ -870,12 +862,18 @@ package body WolfSSL is Key : in out RSA_Key_Type; Size : Integer; Result : out Integer) is - I : aliased int := int (Index); - R : constant int := - RSA_Public_Key_Decode (Input, I, Key, int (Size)); begin - Index := WolfSSL.Byte_Index (I); - Result := Integer (R); + declare + I : aliased int := int (Index); + R : constant int := + RSA_Public_Key_Decode (Input, I, Key, int (Size)); + begin + Index := WolfSSL.Byte_Index (I); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; end Rsa_Public_Key_Decode; function Init_SHA256 (SHA256 : not null Sha256_Type) return int with @@ -910,20 +908,32 @@ package body WolfSSL is procedure Create_SHA256 (Index : SHA256_Index; SHA256 : in out SHA256_Type; Result : out Integer) is - R : int; begin - SHA256 := Ada_New_SHA256 (Index); - R := Init_SHA256 (SHA256); - Result := Integer (R); + declare + R : int; + begin + SHA256 := Ada_New_SHA256 (Index); + R := Init_SHA256 (SHA256); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; end Create_SHA256; procedure Update_SHA256 (SHA256 : in out SHA256_Type; Byte : Byte_Array; Result : out Integer) is - R : int; begin - R := SHA256_Update (SHA256, Byte, Byte'Length); - Result := Integer (R); + declare + R : int; + begin + R := SHA256_Update (SHA256, Byte, Byte'Length); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; end Update_SHA256; procedure Finalize_SHA256 (SHA256 : in out SHA256_Type; @@ -948,6 +958,9 @@ package body WolfSSL is Text (I+0) := Hex_Chars ((Unsigned_8 (C) and 16#F0#) / 16); Text (I+1) := Hex_Chars (Unsigned_8 (C) and 16#0F#); end loop; + exception + when others => + Result := Exception_Error; end Finalize_SHA256; function Is_Valid (AES : AES_Type) return Boolean is @@ -972,11 +985,17 @@ package body WolfSSL is Device : Integer; AES : in out AES_Type; Result : out Integer) is - R : int; begin - AES := Ada_New_AES (Index); - R := AES_Init (AES, null, int (Device)); - Result := Integer (R); + declare + R : int; + begin + AES := Ada_New_AES (Index); + R := AES_Init (AES, null, int (Device)); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; end Create_AES; function AES_Set_Key (AES : not null AES_Type; @@ -994,10 +1013,16 @@ package body WolfSSL is IV : Byte_Array; Dir : Integer; Result : out Integer) is - R : int; begin - R := AES_Set_Key (AES, Key, int (Length), IV, int (Dir)); - Result := Integer (R); + declare + R : int; + begin + R := AES_Set_Key (AES, Key, int (Length), IV, int (Dir)); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; end AES_Set_Key; function AES_Set_IV (AES : not null AES_Type; @@ -1009,10 +1034,16 @@ package body WolfSSL is procedure AES_Set_IV (AES : AES_Type; IV : Byte_Array; Result : out Integer) is - R : int; begin - R := AES_Set_IV (AES, IV); - Result := Integer (R); + declare + R : int; + begin + R := AES_Set_IV (AES, IV); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; end AES_Set_IV; function AES_Set_Cbc_Encrypt (AES : not null AES_Type; @@ -1028,10 +1059,16 @@ package body WolfSSL is Input : Byte_Array; Size : Integer; Result : out Integer) is - R : int; begin - R := AES_Set_Cbc_Encrypt (AES, Output, Input, int (Size)); - Result := Integer (R); + declare + R : int; + begin + R := AES_Set_Cbc_Encrypt (AES, Output, Input, int (Size)); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; end AES_Set_Cbc_Encrypt; function AES_Set_Cbc_Decrypt (AES : not null AES_Type; @@ -1047,10 +1084,16 @@ package body WolfSSL is Input : Byte_Array; Size : Integer; Result : out Integer) is - R : int; begin - R := AES_Set_Cbc_Decrypt (AES, Output, Input, int (Size)); - Result := Integer (R); + declare + R : int; + begin + R := AES_Set_Cbc_Decrypt (AES, Output, Input, int (Size)); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; end AES_Set_Cbc_Decrypt; function AES_Free (AES : not null AES_Type) return int with @@ -1060,13 +1103,19 @@ package body WolfSSL is procedure AES_Free (AES : in out AES_Type; Result : out Integer) is - R : int; begin - R := AES_Free (AES); - Result := Integer (R); - if Result = 0 then - AES := null; - end if; + declare + R : int; + begin + R := AES_Free (AES); + Result := Integer (R); + if Result = 0 then + AES := null; + end if; + end; + exception + when others => + Result := Exception_Error; end AES_Free; function Get_WolfSSL_RSA_Instances return int with diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index e35e90cf6f5..de0d504e79e 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -29,8 +29,16 @@ package WolfSSL with SPARK_Mode is type Subprogram_Result is new Integer; Success : constant Subprogram_Result; + -- Indicates success for some functions. + -- Do not use, unless you know what you do. + Failure : constant Subprogram_Result; + -- Indicates failure for some functions. + -- Do not use, unless you know what you do. + Exception_Error : constant := -1234567; + -- Indicates an exception was raised during a subprogram call. + function Initialize return Subprogram_Result; -- Initializes the wolfSSL library for use. Must be called once per -- application and before any other call to the library. @@ -478,12 +486,15 @@ package WolfSSL with SPARK_Mode is end record; procedure Error (Code : in Error_Code; - Message : out Error_Message); + Message : in out Error_Message); -- This function converts an error code returned by Get_Error(..) -- into a more human readable error string. Code is the error code -- returned by Get_error(). The maximum length of error strings is -- 80 characters by default, as defined by MAX_ERROR_SZ -- is wolfssl/wolfcrypt/error.h. + -- + -- If Message has not been updated with a text, it may be because + -- an exception was raised during the execution of the subprogram. function Max_Error_Size return Natural; -- Returns the value of the defined MAX_ERROR_SZ integer @@ -664,6 +675,13 @@ private External_Name => "get_wolfssl_verify_default", Import => True; + pragma Warnings (Off, "pragma Restrictions (No_Exception_Propagation)"); + -- The compiler may check for warnings related to no exception + -- propagation if this code is compiled with the Zero + -- Footprint run-time. The constants exposed here in the Ada binding + -- have valid values defined in the WolfSSL library but the compiler + -- cannot know this since the values become known during run-time. + Verify_None : constant Mode_Type := Mode_Type (WolfSSL_Verify_None); Verify_Peer : constant Mode_Type := Mode_Type (WolfSSL_Verify_Peer); @@ -681,6 +699,7 @@ private Verify_Default : constant Mode_Type := Mode_Type (WolfSSL_Verify_Default); + pragma Warnings (On, "pragma Restrictions (No_Exception_Propagation)"); type File_Format is new Unsigned_32; @@ -699,6 +718,12 @@ private External_Name => "get_wolfssl_filetype_default", Import => True; + pragma Warnings (Off, "pragma Restrictions (No_Exception_Propagation)"); + -- The compiler may check for warnings related to no exception + -- propagation if this code is compiled with the Zero + -- Footprint run-time. The constants exposed here in the Ada binding + -- have valid values defined in the WolfSSL library but the compiler + -- cannot know this since the values become known during run-time. Format_Asn1 : constant File_Format := File_Format (WolfSSL_Filetype_Asn1); @@ -707,7 +732,8 @@ private Format_Default : constant File_Format := File_Format (WolfSSL_Filetype_Default); - + pragma Warnings (On, "pragma Restrictions (No_Exception_Propagation)"); + function Get_WolfSSL_Success return int with Convention => C, External_Name => "get_wolfssl_success", @@ -720,10 +746,12 @@ private Success : constant Subprogram_Result := Subprogram_Result (Get_WolfSSL_Success); + -- Indicates success for some functions. + -- Do not use, unless you know what you do. Failure : constant Subprogram_Result := - Subprogram_Result (Get_WolfSSL_Failure); - + Subprogram_Result (Get_WolfSSL_Failure); + function Get_WolfSSL_Error_Want_Read return int with Convention => C, External_Name => "get_wolfssl_error_want_read", From 7237743c8e3d27ffb976436341a9d713e5ccd7bc Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Wed, 17 Dec 2025 10:52:44 +0100 Subject: [PATCH 06/51] Saving work in progress on RSA example. --- wrapper/Ada/ada_binding.c | 26 ++- wrapper/Ada/rsa_verify_main.adb | 373 +++++++++++++++++++++++++------- wrapper/Ada/wolfssl.adb | 107 +++++++++ wrapper/Ada/wolfssl.ads | 53 ++++- 4 files changed, 480 insertions(+), 79 deletions(-) diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index dba03f9e626..bbb05482512 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -33,7 +33,7 @@ #define WOLFSSL_RSA_INSTANCES 2 #define WOLFSSL_SHA256_INSTANCES 2 #define WOLFSSL_AES_INSTANCES 2 - +#define WOLFSSL_RNG_INSTANCES 2 /* These functions give access to the integer values of the enumeration constants used in WolfSSL. These functions make it possible for the WolfSSL implementation to change the values of the constants @@ -64,6 +64,10 @@ extern int get_wolfssl_sha256_instances(void); extern void* ada_new_aes (int index); extern int get_wolfssl_aes_instances(void); +extern void* ada_new_rng (int index); +extern int get_wolfssl_rng_instances(void); +extern int ada_RsaSetRNG (RsaKey* key, WC_RNG* rng); + extern int get_wolfssl_error_want_read(void) { return WOLFSSL_ERROR_WANT_READ; } @@ -156,3 +160,23 @@ extern void* ada_new_aes (int index) extern int get_wolfssl_aes_instances(void) { return WOLFSSL_AES_INSTANCES; } + +WC_RNG preAllocatedRNG[WOLFSSL_RNG_INSTANCES]; + +extern void* ada_new_rng (int index) +{ + return &preAllocatedRNG[index]; +} + +extern int get_wolfssl_rng_instances(void) { + return WOLFSSL_RNG_INSTANCES; +} + +extern int ada_RsaSetRNG(RsaKey* key, WC_RNG* rng) +{ + int r = 0; +#ifdef WC_RSA_BLINDING /* HIGHLY RECOMMENDED! */ + r = wc_RsaSetRNG(key, rng); +#endif + return r; +} diff --git a/wrapper/Ada/rsa_verify_main.adb b/wrapper/Ada/rsa_verify_main.adb index 2e1dacd97d9..e390339c539 100644 --- a/wrapper/Ada/rsa_verify_main.adb +++ b/wrapper/Ada/rsa_verify_main.adb @@ -73,71 +73,248 @@ procedure Rsa_Verify_Main is To_C (16#FB#), To_C (16#A1#), To_C (16#BA#), To_C (16#D3#), To_C (16#02#), To_C (16#03#), To_C (16#01#), To_C (16#00#), To_C (16#01#)); - -- (To_C (16#C3#), To_C (16#03#), To_C (16#D1#), To_C (16#2B#), - -- To_C (16#FE#), To_C (16#39#), To_C (16#A4#), To_C (16#32#), - -- To_C (16#45#), To_C (16#3B#), To_C (16#53#), To_C (16#C8#), - -- To_C (16#84#), To_C (16#2B#), To_C (16#2A#), To_C (16#7C#), - -- To_C (16#74#), To_C (16#9A#), To_C (16#BD#), To_C (16#AA#), - -- To_C (16#2A#), To_C (16#52#), To_C (16#07#), To_C (16#47#), - -- To_C (16#D6#), To_C (16#A6#), To_C (16#36#), To_C (16#B2#), - -- To_C (16#07#), To_C (16#32#), To_C (16#8E#), To_C (16#D0#), - -- To_C (16#BA#), To_C (16#69#), To_C (16#7B#), To_C (16#C6#), - -- To_C (16#C3#), To_C (16#44#), To_C (16#9E#), To_C (16#D4#), - -- To_C (16#81#), To_C (16#48#), To_C (16#FD#), To_C (16#2D#), - -- To_C (16#68#), To_C (16#A2#), To_C (16#8B#), To_C (16#67#), - -- To_C (16#BB#), To_C (16#A1#), To_C (16#75#), To_C (16#C8#), - -- To_C (16#36#), To_C (16#2C#), To_C (16#4A#), To_C (16#D2#), - -- To_C (16#1B#), To_C (16#F7#), To_C (16#8B#), To_C (16#BA#), - -- To_C (16#CF#), To_C (16#0D#), To_C (16#F9#), To_C (16#EF#), - -- To_C (16#EC#), To_C (16#F1#), To_C (16#81#), To_C (16#1E#), - -- To_C (16#7B#), To_C (16#9B#), To_C (16#03#), To_C (16#47#), - -- To_C (16#9A#), To_C (16#BF#), To_C (16#65#), To_C (16#CC#), - -- To_C (16#7F#), To_C (16#65#), To_C (16#24#), To_C (16#69#), - -- To_C (16#A6#), To_C (16#E8#), To_C (16#14#), To_C (16#89#), - -- To_C (16#5B#), To_C (16#E4#), To_C (16#34#), To_C (16#F7#), - -- To_C (16#C5#), To_C (16#B0#), To_C (16#14#), To_C (16#93#), - -- To_C (16#F5#), To_C (16#67#), To_C (16#7B#), To_C (16#3A#), - -- To_C (16#7A#), To_C (16#78#), To_C (16#E1#), To_C (16#01#), - -- To_C (16#56#), To_C (16#56#), To_C (16#91#), To_C (16#A6#), - -- To_C (16#13#), To_C (16#42#), To_C (16#8D#), To_C (16#D2#), - -- To_C (16#3C#), To_C (16#40#), To_C (16#9C#), To_C (16#4C#), - -- To_C (16#EF#), To_C (16#D1#), To_C (16#86#), To_C (16#DF#), - -- To_C (16#37#), To_C (16#51#), To_C (16#1B#), To_C (16#0C#), - -- To_C (16#A1#), To_C (16#3B#), To_C (16#F5#), To_C (16#F1#), - -- To_C (16#A3#), To_C (16#4A#), To_C (16#35#), To_C (16#E4#), - -- To_C (16#E1#), To_C (16#CE#), To_C (16#96#), To_C (16#DF#), - -- To_C (16#1B#), To_C (16#7E#), To_C (16#BF#), To_C (16#4E#), - -- To_C (16#97#), To_C (16#D0#), To_C (16#10#), To_C (16#E8#), - -- To_C (16#A8#), To_C (16#08#), To_C (16#30#), To_C (16#81#), - -- To_C (16#AF#), To_C (16#20#), To_C (16#0B#), To_C (16#43#), - -- To_C (16#14#), To_C (16#C5#), To_C (16#74#), To_C (16#67#), - -- To_C (16#B4#), To_C (16#32#), To_C (16#82#), To_C (16#6F#), - -- To_C (16#8D#), To_C (16#86#), To_C (16#C2#), To_C (16#88#), - -- To_C (16#40#), To_C (16#99#), To_C (16#36#), To_C (16#83#), - -- To_C (16#BA#), To_C (16#1E#), To_C (16#40#), To_C (16#72#), - -- To_C (16#22#), To_C (16#17#), To_C (16#D7#), To_C (16#52#), - -- To_C (16#65#), To_C (16#24#), To_C (16#73#), To_C (16#B0#), - -- To_C (16#CE#), To_C (16#EF#), To_C (16#19#), To_C (16#CD#), - -- To_C (16#AE#), To_C (16#FF#), To_C (16#78#), To_C (16#6C#), - -- To_C (16#7B#), To_C (16#C0#), To_C (16#12#), To_C (16#03#), - -- To_C (16#D4#), To_C (16#4E#), To_C (16#72#), To_C (16#0D#), - -- To_C (16#50#), To_C (16#6D#), To_C (16#3B#), To_C (16#A3#), - -- To_C (16#3B#), To_C (16#A3#), To_C (16#99#), To_C (16#5E#), - -- To_C (16#9D#), To_C (16#C8#), To_C (16#D9#), To_C (16#0C#), - -- To_C (16#85#), To_C (16#B3#), To_C (16#D9#), To_C (16#8A#), - -- To_C (16#D9#), To_C (16#54#), To_C (16#26#), To_C (16#DB#), - -- To_C (16#6D#), To_C (16#FA#), To_C (16#AC#), To_C (16#BB#), - -- To_C (16#FF#), To_C (16#25#), To_C (16#4C#), To_C (16#C4#), - -- To_C (16#D1#), To_C (16#79#), To_C (16#F4#), To_C (16#71#), - -- To_C (16#D3#), To_C (16#86#), To_C (16#40#), To_C (16#18#), - -- To_C (16#13#), To_C (16#B0#), To_C (16#63#), To_C (16#B5#), - -- To_C (16#72#), To_C (16#4E#), To_C (16#30#), To_C (16#C4#), - -- To_C (16#97#), To_C (16#84#), To_C (16#86#), To_C (16#2D#), - -- To_C (16#56#), To_C (16#2F#), To_C (16#D7#), To_C (16#15#), - -- To_C (16#F7#), To_C (16#7F#), To_C (16#C0#), To_C (16#AE#), - -- To_C (16#F5#), To_C (16#FC#), To_C (16#5B#), To_C (16#E5#), - -- To_C (16#FB#), To_C (16#A1#), To_C (16#BA#), To_C (16#D3#)); - + -- DER-formatted key. + Client_Private_Key_2048 : constant WolfSSL.Byte_Array := + (To_C (16#30#), To_C (16#82#), To_C (16#04#), To_C (16#A4#), To_C (16#02#), + To_C (16#01#), To_C (16#00#), To_C (16#02#), To_C (16#82#), To_C (16#01#), + To_C (16#01#), To_C (16#00#), To_C (16#C3#), To_C (16#03#), To_C (16#D1#), + To_C (16#2B#), To_C (16#FE#), To_C (16#39#), To_C (16#A4#), To_C (16#32#), + To_C (16#45#), To_C (16#3B#), To_C (16#53#), To_C (16#C8#), To_C (16#84#), + To_C (16#2B#), To_C (16#2A#), To_C (16#7C#), To_C (16#74#), To_C (16#9A#), + To_C (16#BD#), To_C (16#AA#), To_C (16#2A#), To_C (16#52#), To_C (16#07#), + To_C (16#47#), To_C (16#D6#), To_C (16#A6#), To_C (16#36#), To_C (16#B2#), + To_C (16#07#), To_C (16#32#), To_C (16#8E#), To_C (16#D0#), To_C (16#BA#), + To_C (16#69#), To_C (16#7B#), To_C (16#C6#), To_C (16#C3#), To_C (16#44#), + To_C (16#9E#), To_C (16#D4#), To_C (16#81#), To_C (16#48#), To_C (16#FD#), + To_C (16#2D#), To_C (16#68#), To_C (16#A2#), To_C (16#8B#), To_C (16#67#), + To_C (16#BB#), To_C (16#A1#), To_C (16#75#), To_C (16#C8#), To_C (16#36#), + To_C (16#2C#), To_C (16#4A#), To_C (16#D2#), To_C (16#1B#), To_C (16#F7#), + To_C (16#8B#), To_C (16#BA#), To_C (16#CF#), To_C (16#0D#), To_C (16#F9#), + To_C (16#EF#), To_C (16#EC#), To_C (16#F1#), To_C (16#81#), To_C (16#1E#), + To_C (16#7B#), To_C (16#9B#), To_C (16#03#), To_C (16#47#), To_C (16#9A#), + To_C (16#BF#), To_C (16#65#), To_C (16#CC#), To_C (16#7F#), To_C (16#65#), + To_C (16#24#), To_C (16#69#), To_C (16#A6#), To_C (16#E8#), To_C (16#14#), + To_C (16#89#), To_C (16#5B#), To_C (16#E4#), To_C (16#34#), To_C (16#F7#), + To_C (16#C5#), To_C (16#B0#), To_C (16#14#), To_C (16#93#), To_C (16#F5#), + To_C (16#67#), To_C (16#7B#), To_C (16#3A#), To_C (16#7A#), To_C (16#78#), + To_C (16#E1#), To_C (16#01#), To_C (16#56#), To_C (16#56#), To_C (16#91#), + To_C (16#A6#), To_C (16#13#), To_C (16#42#), To_C (16#8D#), To_C (16#D2#), + To_C (16#3C#), To_C (16#40#), To_C (16#9C#), To_C (16#4C#), To_C (16#EF#), + To_C (16#D1#), To_C (16#86#), To_C (16#DF#), To_C (16#37#), To_C (16#51#), + To_C (16#1B#), To_C (16#0C#), To_C (16#A1#), To_C (16#3B#), To_C (16#F5#), + To_C (16#F1#), To_C (16#A3#), To_C (16#4A#), To_C (16#35#), To_C (16#E4#), + To_C (16#E1#), To_C (16#CE#), To_C (16#96#), To_C (16#DF#), To_C (16#1B#), + To_C (16#7E#), To_C (16#BF#), To_C (16#4E#), To_C (16#97#), To_C (16#D0#), + To_C (16#10#), To_C (16#E8#), To_C (16#A8#), To_C (16#08#), To_C (16#30#), + To_C (16#81#), To_C (16#AF#), To_C (16#20#), To_C (16#0B#), To_C (16#43#), + To_C (16#14#), To_C (16#C5#), To_C (16#74#), To_C (16#67#), To_C (16#B4#), + To_C (16#32#), To_C (16#82#), To_C (16#6F#), To_C (16#8D#), To_C (16#86#), + To_C (16#C2#), To_C (16#88#), To_C (16#40#), To_C (16#99#), To_C (16#36#), + To_C (16#83#), To_C (16#BA#), To_C (16#1E#), To_C (16#40#), To_C (16#72#), + To_C (16#22#), To_C (16#17#), To_C (16#D7#), To_C (16#52#), To_C (16#65#), + To_C (16#24#), To_C (16#73#), To_C (16#B0#), To_C (16#CE#), To_C (16#EF#), + To_C (16#19#), To_C (16#CD#), To_C (16#AE#), To_C (16#FF#), To_C (16#78#), + To_C (16#6C#), To_C (16#7B#), To_C (16#C0#), To_C (16#12#), To_C (16#03#), + To_C (16#D4#), To_C (16#4E#), To_C (16#72#), To_C (16#0D#), To_C (16#50#), + To_C (16#6D#), To_C (16#3B#), To_C (16#A3#), To_C (16#3B#), To_C (16#A3#), + To_C (16#99#), To_C (16#5E#), To_C (16#9D#), To_C (16#C8#), To_C (16#D9#), + To_C (16#0C#), To_C (16#85#), To_C (16#B3#), To_C (16#D9#), To_C (16#8A#), + To_C (16#D9#), To_C (16#54#), To_C (16#26#), To_C (16#DB#), To_C (16#6D#), + To_C (16#FA#), To_C (16#AC#), To_C (16#BB#), To_C (16#FF#), To_C (16#25#), + To_C (16#4C#), To_C (16#C4#), To_C (16#D1#), To_C (16#79#), To_C (16#F4#), + To_C (16#71#), To_C (16#D3#), To_C (16#86#), To_C (16#40#), To_C (16#18#), + To_C (16#13#), To_C (16#B0#), To_C (16#63#), To_C (16#B5#), To_C (16#72#), + To_C (16#4E#), To_C (16#30#), To_C (16#C4#), To_C (16#97#), To_C (16#84#), + To_C (16#86#), To_C (16#2D#), To_C (16#56#), To_C (16#2F#), To_C (16#D7#), + To_C (16#15#), To_C (16#F7#), To_C (16#7F#), To_C (16#C0#), To_C (16#AE#), + To_C (16#F5#), To_C (16#FC#), To_C (16#5B#), To_C (16#E5#), To_C (16#FB#), + To_C (16#A1#), To_C (16#BA#), To_C (16#D3#), To_C (16#02#), To_C (16#03#), + To_C (16#01#), To_C (16#00#), To_C (16#01#), To_C (16#02#), To_C (16#82#), + To_C (16#01#), To_C (16#01#), To_C (16#00#), To_C (16#A2#), To_C (16#E6#), + To_C (16#D8#), To_C (16#5F#), To_C (16#10#), To_C (16#71#), To_C (16#64#), + To_C (16#08#), To_C (16#9E#), To_C (16#2E#), To_C (16#6D#), To_C (16#D1#), + To_C (16#6D#), To_C (16#1E#), To_C (16#85#), To_C (16#D2#), To_C (16#0A#), + To_C (16#B1#), To_C (16#8C#), To_C (16#47#), To_C (16#CE#), To_C (16#2C#), + To_C (16#51#), To_C (16#6A#), To_C (16#A0#), To_C (16#12#), To_C (16#9E#), + To_C (16#53#), To_C (16#DE#), To_C (16#91#), To_C (16#4C#), To_C (16#1D#), + To_C (16#6D#), To_C (16#EA#), To_C (16#59#), To_C (16#7B#), To_C (16#F2#), + To_C (16#77#), To_C (16#AA#), To_C (16#D9#), To_C (16#C6#), To_C (16#D9#), + To_C (16#8A#), To_C (16#AB#), To_C (16#D8#), To_C (16#E1#), To_C (16#16#), + To_C (16#E4#), To_C (16#63#), To_C (16#26#), To_C (16#FF#), To_C (16#B5#), + To_C (16#6C#), To_C (16#13#), To_C (16#59#), To_C (16#B8#), To_C (16#E3#), + To_C (16#A5#), To_C (16#C8#), To_C (16#72#), To_C (16#17#), To_C (16#2E#), + To_C (16#0C#), To_C (16#9F#), To_C (16#6F#), To_C (16#E5#), To_C (16#59#), + To_C (16#3F#), To_C (16#76#), To_C (16#6F#), To_C (16#49#), To_C (16#B1#), + To_C (16#11#), To_C (16#C2#), To_C (16#5A#), To_C (16#2E#), To_C (16#16#), + To_C (16#29#), To_C (16#0D#), To_C (16#DE#), To_C (16#B7#), To_C (16#8E#), + To_C (16#DC#), To_C (16#40#), To_C (16#D5#), To_C (16#A2#), To_C (16#EE#), + To_C (16#E0#), To_C (16#1E#), To_C (16#A1#), To_C (16#F4#), To_C (16#BE#), + To_C (16#97#), To_C (16#DB#), To_C (16#86#), To_C (16#63#), To_C (16#96#), + To_C (16#14#), To_C (16#CD#), To_C (16#98#), To_C (16#09#), To_C (16#60#), + To_C (16#2D#), To_C (16#30#), To_C (16#76#), To_C (16#9C#), To_C (16#3C#), + To_C (16#CD#), To_C (16#E6#), To_C (16#88#), To_C (16#EE#), To_C (16#47#), + To_C (16#92#), To_C (16#79#), To_C (16#0B#), To_C (16#5A#), To_C (16#00#), + To_C (16#E2#), To_C (16#5E#), To_C (16#5F#), To_C (16#11#), To_C (16#7C#), + To_C (16#7D#), To_C (16#F9#), To_C (16#08#), To_C (16#B7#), To_C (16#20#), + To_C (16#06#), To_C (16#89#), To_C (16#2A#), To_C (16#5D#), To_C (16#FD#), + To_C (16#00#), To_C (16#AB#), To_C (16#22#), To_C (16#E1#), To_C (16#F0#), + To_C (16#B3#), To_C (16#BC#), To_C (16#24#), To_C (16#A9#), To_C (16#5E#), + To_C (16#26#), To_C (16#0E#), To_C (16#1F#), To_C (16#00#), To_C (16#2D#), + To_C (16#FE#), To_C (16#21#), To_C (16#9A#), To_C (16#53#), To_C (16#5B#), + To_C (16#6D#), To_C (16#D3#), To_C (16#2B#), To_C (16#AB#), To_C (16#94#), + To_C (16#82#), To_C (16#68#), To_C (16#43#), To_C (16#36#), To_C (16#D8#), + To_C (16#F6#), To_C (16#2F#), To_C (16#C6#), To_C (16#22#), To_C (16#FC#), + To_C (16#B5#), To_C (16#41#), To_C (16#5D#), To_C (16#0D#), To_C (16#33#), + To_C (16#60#), To_C (16#EA#), To_C (16#A4#), To_C (16#7D#), To_C (16#7E#), + To_C (16#E8#), To_C (16#4B#), To_C (16#55#), To_C (16#91#), To_C (16#56#), + To_C (16#D3#), To_C (16#5C#), To_C (16#57#), To_C (16#8F#), To_C (16#1F#), + To_C (16#94#), To_C (16#17#), To_C (16#2F#), To_C (16#AA#), To_C (16#DE#), + To_C (16#E9#), To_C (16#9E#), To_C (16#A8#), To_C (16#F4#), To_C (16#CF#), + To_C (16#8A#), To_C (16#4C#), To_C (16#8E#), To_C (16#A0#), To_C (16#E4#), + To_C (16#56#), To_C (16#73#), To_C (16#B2#), To_C (16#CF#), To_C (16#4F#), + To_C (16#86#), To_C (16#C5#), To_C (16#69#), To_C (16#3C#), To_C (16#F3#), + To_C (16#24#), To_C (16#20#), To_C (16#8B#), To_C (16#5C#), To_C (16#96#), + To_C (16#0C#), To_C (16#FA#), To_C (16#6B#), To_C (16#12#), To_C (16#3B#), + To_C (16#9A#), To_C (16#67#), To_C (16#C1#), To_C (16#DF#), To_C (16#C6#), + To_C (16#96#), To_C (16#B2#), To_C (16#A5#), To_C (16#D5#), To_C (16#92#), + To_C (16#0D#), To_C (16#9B#), To_C (16#09#), To_C (16#42#), To_C (16#68#), + To_C (16#24#), To_C (16#10#), To_C (16#45#), To_C (16#D4#), To_C (16#50#), + To_C (16#E4#), To_C (16#17#), To_C (16#39#), To_C (16#48#), To_C (16#D0#), + To_C (16#35#), To_C (16#8B#), To_C (16#94#), To_C (16#6D#), To_C (16#11#), + To_C (16#DE#), To_C (16#8F#), To_C (16#CA#), To_C (16#59#), To_C (16#02#), + To_C (16#81#), To_C (16#81#), To_C (16#00#), To_C (16#EA#), To_C (16#24#), + To_C (16#A7#), To_C (16#F9#), To_C (16#69#), To_C (16#33#), To_C (16#E9#), + To_C (16#71#), To_C (16#DC#), To_C (16#52#), To_C (16#7D#), To_C (16#88#), + To_C (16#21#), To_C (16#28#), To_C (16#2F#), To_C (16#49#), To_C (16#DE#), + To_C (16#BA#), To_C (16#72#), To_C (16#16#), To_C (16#E9#), To_C (16#CC#), + To_C (16#47#), To_C (16#7A#), To_C (16#88#), To_C (16#0D#), To_C (16#94#), + To_C (16#57#), To_C (16#84#), To_C (16#58#), To_C (16#16#), To_C (16#3A#), + To_C (16#81#), To_C (16#B0#), To_C (16#3F#), To_C (16#A2#), To_C (16#CF#), + To_C (16#A6#), To_C (16#6C#), To_C (16#1E#), To_C (16#B0#), To_C (16#06#), + To_C (16#29#), To_C (16#00#), To_C (16#8F#), To_C (16#E7#), To_C (16#77#), + To_C (16#76#), To_C (16#AC#), To_C (16#DB#), To_C (16#CA#), To_C (16#C7#), + To_C (16#D9#), To_C (16#5E#), To_C (16#9B#), To_C (16#3F#), To_C (16#26#), + To_C (16#90#), To_C (16#52#), To_C (16#AE#), To_C (16#FC#), To_C (16#38#), + To_C (16#90#), To_C (16#00#), To_C (16#14#), To_C (16#BB#), To_C (16#B4#), + To_C (16#0F#), To_C (16#58#), To_C (16#94#), To_C (16#E7#), To_C (16#2F#), + To_C (16#6A#), To_C (16#7E#), To_C (16#1C#), To_C (16#4F#), To_C (16#41#), + To_C (16#21#), To_C (16#D4#), To_C (16#31#), To_C (16#59#), To_C (16#1F#), + To_C (16#4E#), To_C (16#8A#), To_C (16#1A#), To_C (16#8D#), To_C (16#A7#), + To_C (16#57#), To_C (16#6C#), To_C (16#22#), To_C (16#D8#), To_C (16#E5#), + To_C (16#F4#), To_C (16#7E#), To_C (16#32#), To_C (16#A6#), To_C (16#10#), + To_C (16#CB#), To_C (16#64#), To_C (16#A5#), To_C (16#55#), To_C (16#03#), + To_C (16#87#), To_C (16#A6#), To_C (16#27#), To_C (16#05#), To_C (16#8C#), + To_C (16#C3#), To_C (16#D7#), To_C (16#B6#), To_C (16#27#), To_C (16#B2#), + To_C (16#4D#), To_C (16#BA#), To_C (16#30#), To_C (16#DA#), To_C (16#47#), + To_C (16#8F#), To_C (16#54#), To_C (16#D3#), To_C (16#3D#), To_C (16#8B#), + To_C (16#84#), To_C (16#8D#), To_C (16#94#), To_C (16#98#), To_C (16#58#), + To_C (16#A5#), To_C (16#02#), To_C (16#81#), To_C (16#81#), To_C (16#00#), + To_C (16#D5#), To_C (16#38#), To_C (16#1B#), To_C (16#C3#), To_C (16#8F#), + To_C (16#C5#), To_C (16#93#), To_C (16#0C#), To_C (16#47#), To_C (16#0B#), + To_C (16#6F#), To_C (16#35#), To_C (16#92#), To_C (16#C5#), To_C (16#B0#), + To_C (16#8D#), To_C (16#46#), To_C (16#C8#), To_C (16#92#), To_C (16#18#), + To_C (16#8F#), To_C (16#F5#), To_C (16#80#), To_C (16#0A#), To_C (16#F7#), + To_C (16#EF#), To_C (16#A1#), To_C (16#FE#), To_C (16#80#), To_C (16#B9#), + To_C (16#B5#), To_C (16#2A#), To_C (16#BA#), To_C (16#CA#), To_C (16#18#), + To_C (16#B0#), To_C (16#5D#), To_C (16#A5#), To_C (16#07#), To_C (16#D0#), + To_C (16#93#), To_C (16#8D#), To_C (16#D8#), To_C (16#9C#), To_C (16#04#), + To_C (16#1C#), To_C (16#D4#), To_C (16#62#), To_C (16#8E#), To_C (16#A6#), + To_C (16#26#), To_C (16#81#), To_C (16#01#), To_C (16#FF#), To_C (16#CE#), + To_C (16#8A#), To_C (16#2A#), To_C (16#63#), To_C (16#34#), To_C (16#35#), + To_C (16#40#), To_C (16#AA#), To_C (16#6D#), To_C (16#80#), To_C (16#DE#), + To_C (16#89#), To_C (16#23#), To_C (16#6A#), To_C (16#57#), To_C (16#4D#), + To_C (16#9E#), To_C (16#6E#), To_C (16#AD#), To_C (16#93#), To_C (16#4E#), + To_C (16#56#), To_C (16#90#), To_C (16#0B#), To_C (16#6D#), To_C (16#9D#), + To_C (16#73#), To_C (16#8B#), To_C (16#0C#), To_C (16#AE#), To_C (16#27#), + To_C (16#3D#), To_C (16#DE#), To_C (16#4E#), To_C (16#F0#), To_C (16#AA#), + To_C (16#C5#), To_C (16#6C#), To_C (16#78#), To_C (16#67#), To_C (16#6C#), + To_C (16#94#), To_C (16#52#), To_C (16#9C#), To_C (16#37#), To_C (16#67#), + To_C (16#6C#), To_C (16#2D#), To_C (16#EF#), To_C (16#BB#), To_C (16#AF#), + To_C (16#DF#), To_C (16#A6#), To_C (16#90#), To_C (16#3C#), To_C (16#C4#), + To_C (16#47#), To_C (16#CF#), To_C (16#8D#), To_C (16#96#), To_C (16#9E#), + To_C (16#98#), To_C (16#A9#), To_C (16#B4#), To_C (16#9F#), To_C (16#C5#), + To_C (16#A6#), To_C (16#50#), To_C (16#DC#), To_C (16#B3#), To_C (16#F0#), + To_C (16#FB#), To_C (16#74#), To_C (16#17#), To_C (16#02#), To_C (16#81#), + To_C (16#80#), To_C (16#5E#), To_C (16#83#), To_C (16#09#), To_C (16#62#), + To_C (16#BD#), To_C (16#BA#), To_C (16#7C#), To_C (16#A2#), To_C (16#BF#), + To_C (16#42#), To_C (16#74#), To_C (16#F5#), To_C (16#7C#), To_C (16#1C#), + To_C (16#D2#), To_C (16#69#), To_C (16#C9#), To_C (16#04#), To_C (16#0D#), + To_C (16#85#), To_C (16#7E#), To_C (16#3E#), To_C (16#3D#), To_C (16#24#), + To_C (16#12#), To_C (16#C3#), To_C (16#18#), To_C (16#7B#), To_C (16#F3#), + To_C (16#29#), To_C (16#F3#), To_C (16#5F#), To_C (16#0E#), To_C (16#76#), + To_C (16#6C#), To_C (16#59#), To_C (16#75#), To_C (16#E4#), To_C (16#41#), + To_C (16#84#), To_C (16#69#), To_C (16#9D#), To_C (16#32#), To_C (16#F3#), + To_C (16#CD#), To_C (16#22#), To_C (16#AB#), To_C (16#B0#), To_C (16#35#), + To_C (16#BA#), To_C (16#4A#), To_C (16#B2#), To_C (16#3C#), To_C (16#E5#), + To_C (16#D9#), To_C (16#58#), To_C (16#B6#), To_C (16#62#), To_C (16#4F#), + To_C (16#5D#), To_C (16#DE#), To_C (16#E5#), To_C (16#9E#), To_C (16#0A#), + To_C (16#CA#), To_C (16#53#), To_C (16#B2#), To_C (16#2C#), To_C (16#F7#), + To_C (16#9E#), To_C (16#B3#), To_C (16#6B#), To_C (16#0A#), To_C (16#5B#), + To_C (16#79#), To_C (16#65#), To_C (16#EC#), To_C (16#6E#), To_C (16#91#), + To_C (16#4E#), To_C (16#92#), To_C (16#20#), To_C (16#F6#), To_C (16#FC#), + To_C (16#FC#), To_C (16#16#), To_C (16#ED#), To_C (16#D3#), To_C (16#76#), + To_C (16#0C#), To_C (16#E2#), To_C (16#EC#), To_C (16#7F#), To_C (16#B2#), + To_C (16#69#), To_C (16#13#), To_C (16#6B#), To_C (16#78#), To_C (16#0E#), + To_C (16#5A#), To_C (16#46#), To_C (16#64#), To_C (16#B4#), To_C (16#5E#), + To_C (16#B7#), To_C (16#25#), To_C (16#A0#), To_C (16#5A#), To_C (16#75#), + To_C (16#3A#), To_C (16#4B#), To_C (16#EF#), To_C (16#C7#), To_C (16#3C#), + To_C (16#3E#), To_C (16#F7#), To_C (16#FD#), To_C (16#26#), To_C (16#B8#), + To_C (16#20#), To_C (16#C4#), To_C (16#99#), To_C (16#0A#), To_C (16#9A#), + To_C (16#73#), To_C (16#BE#), To_C (16#C3#), To_C (16#19#), To_C (16#02#), + To_C (16#81#), To_C (16#81#), To_C (16#00#), To_C (16#BA#), To_C (16#44#), + To_C (16#93#), To_C (16#14#), To_C (16#AC#), To_C (16#34#), To_C (16#19#), + To_C (16#3B#), To_C (16#5F#), To_C (16#91#), To_C (16#60#), To_C (16#AC#), + To_C (16#F7#), To_C (16#B4#), To_C (16#D6#), To_C (16#81#), To_C (16#05#), + To_C (16#36#), To_C (16#51#), To_C (16#53#), To_C (16#3D#), To_C (16#E8#), + To_C (16#65#), To_C (16#DC#), To_C (16#AF#), To_C (16#2E#), To_C (16#DC#), + To_C (16#61#), To_C (16#3E#), To_C (16#C9#), To_C (16#7D#), To_C (16#B8#), + To_C (16#7F#), To_C (16#87#), To_C (16#F0#), To_C (16#3B#), To_C (16#9B#), + To_C (16#03#), To_C (16#82#), To_C (16#29#), To_C (16#37#), To_C (16#CE#), + To_C (16#72#), To_C (16#4E#), To_C (16#11#), To_C (16#D5#), To_C (16#B1#), + To_C (16#C1#), To_C (16#0C#), To_C (16#07#), To_C (16#A0#), To_C (16#99#), + To_C (16#91#), To_C (16#4A#), To_C (16#8D#), To_C (16#7F#), To_C (16#EC#), + To_C (16#79#), To_C (16#CF#), To_C (16#F1#), To_C (16#39#), To_C (16#B5#), + To_C (16#E9#), To_C (16#85#), To_C (16#EC#), To_C (16#62#), To_C (16#F7#), + To_C (16#DA#), To_C (16#7D#), To_C (16#BC#), To_C (16#64#), To_C (16#4D#), + To_C (16#22#), To_C (16#3C#), To_C (16#0E#), To_C (16#F2#), To_C (16#D6#), + To_C (16#51#), To_C (16#F5#), To_C (16#87#), To_C (16#D8#), To_C (16#99#), + To_C (16#C0#), To_C (16#11#), To_C (16#20#), To_C (16#5D#), To_C (16#0F#), + To_C (16#29#), To_C (16#FD#), To_C (16#5B#), To_C (16#E2#), To_C (16#AE#), + To_C (16#D9#), To_C (16#1C#), To_C (16#D9#), To_C (16#21#), To_C (16#56#), + To_C (16#6D#), To_C (16#FC#), To_C (16#84#), To_C (16#D0#), To_C (16#5F#), + To_C (16#ED#), To_C (16#10#), To_C (16#15#), To_C (16#1C#), To_C (16#18#), + To_C (16#21#), To_C (16#E7#), To_C (16#C4#), To_C (16#3D#), To_C (16#4B#), + To_C (16#D7#), To_C (16#D0#), To_C (16#9E#), To_C (16#6A#), To_C (16#95#), + To_C (16#CF#), To_C (16#22#), To_C (16#C9#), To_C (16#03#), To_C (16#7B#), + To_C (16#9E#), To_C (16#E3#), To_C (16#60#), To_C (16#01#), To_C (16#FC#), + To_C (16#2F#), To_C (16#02#), To_C (16#81#), To_C (16#80#), To_C (16#11#), + To_C (16#D0#), To_C (16#4B#), To_C (16#CF#), To_C (16#1B#), To_C (16#67#), + To_C (16#B9#), To_C (16#9F#), To_C (16#10#), To_C (16#75#), To_C (16#47#), + To_C (16#86#), To_C (16#65#), To_C (16#AE#), To_C (16#31#), To_C (16#C2#), + To_C (16#C6#), To_C (16#30#), To_C (16#AC#), To_C (16#59#), To_C (16#06#), + To_C (16#50#), To_C (16#D9#), To_C (16#0F#), To_C (16#B5#), To_C (16#70#), + To_C (16#06#), To_C (16#F7#), To_C (16#F0#), To_C (16#D3#), To_C (16#C8#), + To_C (16#62#), To_C (16#7C#), To_C (16#A8#), To_C (16#DA#), To_C (16#6E#), + To_C (16#F6#), To_C (16#21#), To_C (16#3F#), To_C (16#D3#), To_C (16#7F#), + To_C (16#5F#), To_C (16#EA#), To_C (16#8A#), To_C (16#AB#), To_C (16#3F#), + To_C (16#D9#), To_C (16#2A#), To_C (16#5E#), To_C (16#F3#), To_C (16#51#), + To_C (16#D2#), To_C (16#C2#), To_C (16#30#), To_C (16#37#), To_C (16#E3#), + To_C (16#2D#), To_C (16#A3#), To_C (16#75#), To_C (16#0D#), To_C (16#1E#), + To_C (16#4D#), To_C (16#21#), To_C (16#34#), To_C (16#D5#), To_C (16#57#), + To_C (16#70#), To_C (16#5C#), To_C (16#89#), To_C (16#BF#), To_C (16#72#), + To_C (16#EC#), To_C (16#4A#), To_C (16#6E#), To_C (16#68#), To_C (16#D5#), + To_C (16#CD#), To_C (16#18#), To_C (16#74#), To_C (16#33#), To_C (16#4E#), + To_C (16#8C#), To_C (16#3A#), To_C (16#45#), To_C (16#8F#), To_C (16#E6#), + To_C (16#96#), To_C (16#40#), To_C (16#EB#), To_C (16#63#), To_C (16#F9#), + To_C (16#19#), To_C (16#86#), To_C (16#3A#), To_C (16#51#), To_C (16#DD#), + To_C (16#89#), To_C (16#4B#), To_C (16#B0#), To_C (16#F3#), To_C (16#F9#), + To_C (16#9F#), To_C (16#5D#), To_C (16#28#), To_C (16#95#), To_C (16#38#), + To_C (16#BE#), To_C (16#35#), To_C (16#AB#), To_C (16#CA#), To_C (16#5C#), + To_C (16#E7#), To_C (16#93#), To_C (16#53#), To_C (16#34#), To_C (16#A1#), + To_C (16#45#), To_C (16#5D#), To_C (16#13#), To_C (16#39#), To_C (16#65#), + To_C (16#42#), To_C (16#46#), To_C (16#A1#), To_C (16#9F#), To_C (16#CD#), + To_C (16#F5#), To_C (16#BF#)); + Message : constant WolfSSL.Byte_Array := (To_C (16#54#), To_C (16#68#), To_C (16#69#), To_C (16#73#), To_C (16#20#), To_C (16#69#), To_C (16#73#), To_C (16#20#), @@ -210,7 +387,7 @@ procedure Rsa_Verify_Main is To_C (16#6d#), To_C (16#da#), To_C (16#92#), To_C (16#99#), To_C (16#3f#), To_C (16#64#), To_C (16#a7#), To_C (16#ea#), To_C (16#e0#), To_C (16#dc#), To_C (16#7c#), To_C (16#e8#), - To_C (16#41#), To_C (16#b0#), To_C (16#eb#), To_C (16#45#)); + To_C (16#41#), To_C (16#b0#), To_C (16#eb#), To_C (16#45#)); procedure Put (Text : String) renames Ada.Text_IO.Put; @@ -226,12 +403,19 @@ procedure Rsa_Verify_Main is use type WolfSSL.Subprogram_Result; + Original_AES_Key : constant WolfSSL.Byte_Array (1 .. 32) := + "Thisismyfakeaeskeythatis32bytes!"; + + Digital_Signature_Of_AES_Key : WolfSSL.Byte_Array (1 .. 256); + Hash : WolfSSL.SHA256_Hash; SHA256 : WolfSSL.SHA256_Type; R : Integer; S : WolfSSL.SHA256_As_String; + + RNG : WolfSSL.RNG_Key_Type; - Key : WolfSSL.RSA_Key_Type; + RSA_Key : WolfSSL.RSA_Key_Type; Index : WolfSSL.Byte_Index; begin WolfSSL.Create_SHA256 (Index => 0, SHA256 => SHA256, Result => R); @@ -258,32 +442,69 @@ begin New_Line; return; end if; + + WolfSSL.Create_RNG (Index => 0, + Key => RNG, + Result => R); + if R /= 0 then + Put ("Attaining RNG key instance failed"); + New_Line; + return; + end if; WolfSSL.Create_RSA (Index => 0, - Key => Key, + Key => RSA_Key, Result => R); if R /= 0 then Put ("Attaining RSA key instance failed"); New_Line; return; end if; - + + WolfSSL.Rsa_Set_RNG (Key => RSA_Key, + RNG => RNG, + Result => R); + if R /= 0 then + Put ("Associating RSA key with random number generator failed"); + New_Line; + return; + end if; + + Index := Client_Private_Key_2048'First; + WolfSSL.Rsa_Private_Key_Decode (Input => Client_Private_Key_2048, + Index => Index, + Key => RSA_Key, + Size => Client_Private_Key_2048'Length, + Result => R); + if R /= 0 then + Put ("Loading RSA private key failed with error code "); + Put (R); + New_Line; + return; + end if; + Index := Rsa_Public_key_2048'First; - Put (WolfSSL.Is_Valid (Key)'Image); - WolfSSL.Rsa_Public_Key_Decode (Input => Rsa_Public_key_2048, Index => Index, - Key => Key, + Key => RSA_Key, Size => Rsa_Public_key_2048'Length, Result => R); - Put (Integer (Index)); if R /= 0 then Put ("Loading RSA key failed with DER encoded key"); Put (R); New_Line; return; end if; - New_Line; - Put (WolfSSL.Failure'Image); - New_Line; + + WolfSSL.Rsa_SSL_Sign (Input => Original_AES_Key, + Output => Digital_Signature_Of_AES_Key, + RSA => RSA_Key, + RNG => RNG, + Result => R); + if R < 0 then + Put ("Creating digital signature using RSA private key failed"); + Put (R); + New_Line; + return; + end if; end Rsa_Verify_Main; diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index 1a013fa708d..d3f22c30dbc 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -819,6 +819,53 @@ package body WolfSSL is return Natural (Get_WolfSSL_Max_Error_Size); end Max_Error_Size; + function Is_Valid (Key : RNG_Key_Type) return Boolean is + begin + return Key /= null; + end Is_Valid; + + function Ada_New_RNG (Index : int) + return RNG_Key_Type with + Convention => C, + External_Name => "ada_new_rng", + Import => True; + + function Init_RNG_Key (Key : not null RNG_Key_Type) return int with + Convention => C, + External_Name => "wc_InitRng", + Import => True; + + procedure Create_RNG (Index : RNG_Key_Index; + Key : in out RNG_Key_Type; + Result : out Integer) is + R : int; + begin + Key := Ada_New_RNG (int (Index)); + R := Init_RNG_Key (Key); + Result := Integer (R); + exception + when others => + Result := Exception_Error; + end Create_RNG; + + function Ada_RSA_Set_RNG (Key : not null RSA_Key_Type; + RNG : not null RNG_Key_Type) return int with + Convention => C, + External_Name => "ada_RsaSetRNG", + Import => True; + + procedure Rsa_Set_RNG (Key : in out Rsa_Key_Type; + RNG : in out RNG_Key_Type; + Result : out Integer) is + R : int; + begin + R := Ada_RSA_Set_RNG (Key, RNG); + Result := Integer (R); + exception + when others => + Result := Exception_Error; + end Rsa_Set_RNG; + function Is_Valid (Key : RSA_Key_Type) return Boolean is begin return Key /= null; @@ -876,6 +923,66 @@ package body WolfSSL is Result := Exception_Error; end Rsa_Public_Key_Decode; + function RSA_Private_Key_Decode (Input : Byte_Array; + Index : in out int; + Key : not null RSA_Key_Type; + Size : int) return int with + Convention => C, + External_Name => "wc_RsaPrivateKeyDecode", + Import => True; + + procedure Rsa_Private_Key_Decode (Input : Byte_Array; + Index : in out Byte_Index; + Key : in out RSA_Key_Type; + Size : Integer; + Result : out Integer) is + begin + declare + I : aliased int := int (Index); + R : constant int := + RSA_Private_Key_Decode (Input, I, Key, int (Size)); + begin + Index := WolfSSL.Byte_Index (I); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; + end Rsa_Private_Key_Decode; + + function RSA_SSL_Sign (Input : Byte_Array; + In_Length : int; + Output : in out Byte_Array; + Out_Length : int; + RSA : not null RSA_Key_Type; + RNG : not null RNG_Key_Type) + return int with + Convention => C, + External_Name => "wc_RsaSSL_Sign", + Import => True; + + procedure Rsa_SSL_Sign (Input : Byte_Array; + Output : in out Byte_Array; + RSA : in out RSA_Key_Type; + RNG : in out RNG_Key_Type; + Result : out Integer) is + begin + declare + R : constant int := + RSA_SSL_Sign (Input, + Input'Length, + Output, + Output'Length, + RSA, + RNG); + begin + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; + end Rsa_SSL_Sign; + function Init_SHA256 (SHA256 : not null Sha256_Type) return int with Convention => C, External_Name => "wc_InitSha256", diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index de0d504e79e..ce019f28f0b 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -500,6 +500,22 @@ package WolfSSL with SPARK_Mode is -- Returns the value of the defined MAX_ERROR_SZ integer -- in wolfssl/wolfcrypt/error.h. + RNG_INSTANCES : constant := 2; + + type RNG_Key_Index is range 0 .. RNG_INSTANCES - 1; + + type RNG_Key_Type is limited private; + + function Is_Valid (Key : RNG_Key_Type) return Boolean; + -- Indicates if the RSA has successfully been initialized. + + procedure Create_RNG (Index : RNG_Key_Index; + Key : in out RNG_Key_Type; + Result : out Integer) with + Pre => not Is_Valid (Key), + Post => (if Result = 0 then Is_Valid (Key)); + -- If successful Result = 0. + RSA_INSTANCES : constant := 2; type RSA_Key_Index is range 0 .. RSA_INSTANCES - 1; @@ -526,7 +542,37 @@ package WolfSSL with SPARK_Mode is -- extracts the public key and stores it in the RsaKey structure -- specified by the Key input argument. It also sets the distance -- parsed in Index. - + -- Note: A RsaKey structure contains two parts, + -- one public and one private key. + + procedure Rsa_Private_Key_Decode (Input : Byte_Array; + Index : in out Byte_Index; + Key : in out RSA_Key_Type; + Size : Integer; + Result : out Integer) with + Pre => Is_Valid (Key); + -- This function parses a DER-formatted RSA private key, + -- extracts the private key and stores it in the RsaKey structure + -- specified by the Key input argument. It also sets the distance + -- parsed in Index. + -- Note: A RsaKey structure contains two parts, + -- one public and one private key. + + procedure Rsa_Set_RNG (Key : in out Rsa_Key_Type; + RNG : in out RNG_Key_Type; + Result : out Integer); + + procedure Rsa_SSL_Sign (Input : Byte_Array; + Output : in out Byte_Array; + RSA : in out RSA_Key_Type; + RNG : in out RNG_Key_Type; + Result : out Integer) with + Pre => Is_Valid (RSA) and Is_Valid (RNG); + -- The Output buffer must have the same size as the RSA key. + -- If successful Result = 0. + -- If Result < 0, then failure. + -- If Result > 0, then Success and is the size of the RSA key in bytes. + SHA256_INSTANCES : constant := 2; type SHA256_Index is range 0 .. SHA256_INSTANCES - 1; @@ -767,9 +813,12 @@ private Error_Want_Write : constant Error_Code := Error_Code (Get_WolfSSL_Error_Want_Write); + + type Opaque_RNG is limited null record; + type RNG_Key_Type is access Opaque_RNG with Convention => C; type Opaque_RSA is limited null record; - type RSA_Key_Type is access Opaque_RSA with Convention => C; + type RSA_Key_Type is access Opaque_RSA with Convention => C; type Opaque_Sha256 is limited null record; type SHA256_Type is access Opaque_Sha256 with Convention => C; From f756214f479e8fcb9e3d8bc9f238aa379e39fcad Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Fri, 19 Dec 2025 19:01:11 +0100 Subject: [PATCH 07/51] Rsa example can now digitaly sign and verify digital signatures. --- wrapper/Ada/rsa_verify_main.adb | 154 +++++++++----------------------- wrapper/Ada/wolfssl.adb | 103 +++++++++++++++++++++ wrapper/Ada/wolfssl.ads | 29 ++++++ 3 files changed, 172 insertions(+), 114 deletions(-) diff --git a/wrapper/Ada/rsa_verify_main.adb b/wrapper/Ada/rsa_verify_main.adb index e390339c539..e4e940e70e7 100644 --- a/wrapper/Ada/rsa_verify_main.adb +++ b/wrapper/Ada/rsa_verify_main.adb @@ -314,80 +314,6 @@ procedure Rsa_Verify_Main is To_C (16#45#), To_C (16#5D#), To_C (16#13#), To_C (16#39#), To_C (16#65#), To_C (16#42#), To_C (16#46#), To_C (16#A1#), To_C (16#9F#), To_C (16#CD#), To_C (16#F5#), To_C (16#BF#)); - - Message : constant WolfSSL.Byte_Array := - (To_C (16#54#), To_C (16#68#), To_C (16#69#), To_C (16#73#), - To_C (16#20#), To_C (16#69#), To_C (16#73#), To_C (16#20#), - To_C (16#74#), To_C (16#68#), To_C (16#65#), To_C (16#20#), - To_C (16#6d#), To_C (16#65#), To_C (16#73#), To_C (16#73#), - To_C (16#61#), To_C (16#67#), To_C (16#65#)); - - - RSA_Signature : constant WolfSSL.Byte_Array := - (To_C (16#41#), To_C (16#eb#), To_C (16#f5#), To_C (16#5e#), - To_C (16#97#), To_C (16#43#), To_C (16#f4#), To_C (16#d1#), - To_C (16#da#), To_C (16#b6#), To_C (16#5c#), To_C (16#75#), - To_C (16#57#), To_C (16#2c#), To_C (16#e1#), To_C (16#01#), - To_C (16#07#), To_C (16#dc#), To_C (16#42#), To_C (16#c4#), - To_C (16#2d#), To_C (16#e2#), To_C (16#b5#), To_C (16#c8#), - To_C (16#63#), To_C (16#e8#), To_C (16#45#), To_C (16#9a#), - To_C (16#4a#), To_C (16#fa#), To_C (16#df#), To_C (16#5e#), - To_C (16#a6#), To_C (16#08#), To_C (16#0a#), To_C (16#26#), - To_C (16#2e#), To_C (16#ca#), To_C (16#2c#), To_C (16#10#), - To_C (16#7a#), To_C (16#15#), To_C (16#8d#), To_C (16#c1#), - To_C (16#55#), To_C (16#cc#), To_C (16#33#), To_C (16#db#), - To_C (16#b2#), To_C (16#ef#), To_C (16#8b#), To_C (16#a6#), - To_C (16#4b#), To_C (16#ef#), To_C (16#a1#), To_C (16#cf#), - To_C (16#d3#), To_C (16#e2#), To_C (16#5d#), To_C (16#ac#), - To_C (16#88#), To_C (16#86#), To_C (16#62#), To_C (16#67#), - To_C (16#8b#), To_C (16#8c#), To_C (16#45#), To_C (16#7f#), - To_C (16#10#), To_C (16#ad#), To_C (16#fa#), To_C (16#27#), - To_C (16#7a#), To_C (16#35#), To_C (16#5a#), To_C (16#f9#), - To_C (16#09#), To_C (16#78#), To_C (16#83#), To_C (16#ba#), - To_C (16#18#), To_C (16#cb#), To_C (16#3e#), To_C (16#8e#), - To_C (16#08#), To_C (16#be#), To_C (16#36#), To_C (16#de#), - To_C (16#ac#), To_C (16#c1#), To_C (16#77#), To_C (16#44#), - To_C (16#e8#), To_C (16#43#), To_C (16#db#), To_C (16#52#), - To_C (16#23#), To_C (16#08#), To_C (16#36#), To_C (16#8f#), - To_C (16#74#), To_C (16#4a#), To_C (16#bd#), To_C (16#a3#), - To_C (16#3f#), To_C (16#c1#), To_C (16#fb#), To_C (16#d6#), - To_C (16#45#), To_C (16#25#), To_C (16#61#), To_C (16#e2#), - To_C (16#19#), To_C (16#cb#), To_C (16#0b#), To_C (16#28#), - To_C (16#ef#), To_C (16#ca#), To_C (16#0a#), To_C (16#3b#), - To_C (16#7b#), To_C (16#3d#), To_C (16#e3#), To_C (16#47#), - To_C (16#46#), To_C (16#07#), To_C (16#1a#), To_C (16#7f#), - To_C (16#ff#), To_C (16#38#), To_C (16#fd#), To_C (16#59#), - To_C (16#94#), To_C (16#0b#), To_C (16#eb#), To_C (16#00#), - To_C (16#ab#), To_C (16#cc#), To_C (16#8c#), To_C (16#48#), - To_C (16#7b#), To_C (16#d6#), To_C (16#87#), To_C (16#b8#), - To_C (16#54#), To_C (16#b0#), To_C (16#2a#), To_C (16#07#), - To_C (16#cf#), To_C (16#44#), To_C (16#11#), To_C (16#d4#), - To_C (16#b6#), To_C (16#9a#), To_C (16#4e#), To_C (16#6d#), - To_C (16#5c#), To_C (16#1a#), To_C (16#e3#), To_C (16#c7#), - To_C (16#f3#), To_C (16#c7#), To_C (16#cb#), To_C (16#8e#), - To_C (16#82#), To_C (16#7d#), To_C (16#c8#), To_C (16#77#), - To_C (16#f0#), To_C (16#b6#), To_C (16#d0#), To_C (16#85#), - To_C (16#cb#), To_C (16#db#), To_C (16#d0#), To_C (16#b0#), - To_C (16#e0#), To_C (16#cf#), To_C (16#ca#), To_C (16#3f#), - To_C (16#17#), To_C (16#46#), To_C (16#84#), To_C (16#cb#), - To_C (16#5b#), To_C (16#fe#), To_C (16#51#), To_C (16#3a#), - To_C (16#aa#), To_C (16#71#), To_C (16#ad#), To_C (16#eb#), - To_C (16#f1#), To_C (16#ed#), To_C (16#3f#), To_C (16#f8#), - To_C (16#de#), To_C (16#b4#), To_C (16#a1#), To_C (16#26#), - To_C (16#db#), To_C (16#c6#), To_C (16#8e#), To_C (16#70#), - To_C (16#d4#), To_C (16#58#), To_C (16#a8#), To_C (16#31#), - To_C (16#d8#), To_C (16#db#), To_C (16#cf#), To_C (16#64#), - To_C (16#4a#), To_C (16#5f#), To_C (16#1b#), To_C (16#89#), - To_C (16#22#), To_C (16#03#), To_C (16#3f#), To_C (16#ab#), - To_C (16#b5#), To_C (16#6d#), To_C (16#2a#), To_C (16#63#), - To_C (16#2f#), To_C (16#4e#), To_C (16#7a#), To_C (16#e1#), - To_C (16#89#), To_C (16#b4#), To_C (16#f0#), To_C (16#9a#), - To_C (16#b7#), To_C (16#d3#), To_C (16#d6#), To_C (16#0a#), - To_C (16#10#), To_C (16#67#), To_C (16#28#), To_C (16#25#), - To_C (16#6d#), To_C (16#da#), To_C (16#92#), To_C (16#99#), - To_C (16#3f#), To_C (16#64#), To_C (16#a7#), To_C (16#ea#), - To_C (16#e0#), To_C (16#dc#), To_C (16#7c#), To_C (16#e8#), - To_C (16#41#), To_C (16#b0#), To_C (16#eb#), To_C (16#45#)); procedure Put (Text : String) renames Ada.Text_IO.Put; @@ -407,42 +333,19 @@ procedure Rsa_Verify_Main is "Thisismyfakeaeskeythatis32bytes!"; Digital_Signature_Of_AES_Key : WolfSSL.Byte_Array (1 .. 256); + + Decrypted_Digital_Signature : WolfSSL.Byte_Array (1 .. 256); Hash : WolfSSL.SHA256_Hash; SHA256 : WolfSSL.SHA256_Type; R : Integer; - S : WolfSSL.SHA256_As_String; RNG : WolfSSL.RNG_Key_Type; - RSA_Key : WolfSSL.RSA_Key_Type; + RSA_Encrypt_Key : WolfSSL.RSA_Key_Type; + RSA_Decrypt_Key : WolfSSL.RSA_Key_Type; Index : WolfSSL.Byte_Index; begin - WolfSSL.Create_SHA256 (Index => 0, SHA256 => SHA256, Result => R); - if R /= 0 then - Put ("SHA256 instance creation failed"); - New_Line; - return; - end if; - WolfSSL.Update_SHA256 (SHA256 => SHA256, Byte => Message, Result => R); - if R /= 0 then - Put ("Update of SHA256 instance failed"); - New_Line; - return; - end if; - WolfSSL.Finalize_SHA256 (SHA256 => SHA256, - Hash => Hash, - Text => S, - Result => R); - if R = 0 then - Put (S); - New_Line; - else - Put ("Finalization of SHA256 instance failed"); - New_Line; - return; - end if; - WolfSSL.Create_RNG (Index => 0, Key => RNG, Result => R); @@ -453,7 +356,7 @@ begin end if; WolfSSL.Create_RSA (Index => 0, - Key => RSA_Key, + Key => RSA_Encrypt_Key, Result => R); if R /= 0 then Put ("Attaining RSA key instance failed"); @@ -461,7 +364,7 @@ begin return; end if; - WolfSSL.Rsa_Set_RNG (Key => RSA_Key, + WolfSSL.Rsa_Set_RNG (Key => RSA_Encrypt_Key, RNG => RNG, Result => R); if R /= 0 then @@ -473,38 +376,61 @@ begin Index := Client_Private_Key_2048'First; WolfSSL.Rsa_Private_Key_Decode (Input => Client_Private_Key_2048, Index => Index, - Key => RSA_Key, + Key => RSA_Encrypt_Key, Size => Client_Private_Key_2048'Length, Result => R); if R /= 0 then - Put ("Loading RSA private key failed with error code "); + Put ("Loading private RSA key failed with error code "); + Put (R); + New_Line; + return; + end if; + + WolfSSL.Rsa_SSL_Sign (Input => Original_AES_Key, + Output => Digital_Signature_Of_AES_Key, + RSA => RSA_Encrypt_Key, + RNG => RNG, + Result => R); + if R < 0 then + Put ("Creating digital signature using RSA private key failed"); Put (R); New_Line; return; end if; + WolfSSL.Create_RSA (Index => 1, + Key => RSA_Decrypt_Key, + Result => R); + if R /= 0 then + Put ("Attaining RSA key instance failed"); + New_Line; + return; + end if; + Index := Rsa_Public_key_2048'First; WolfSSL.Rsa_Public_Key_Decode (Input => Rsa_Public_key_2048, Index => Index, - Key => RSA_Key, + Key => RSA_Decrypt_Key, Size => Rsa_Public_key_2048'Length, Result => R); if R /= 0 then - Put ("Loading RSA key failed with DER encoded key"); + Put ("Loading public RSA key failed with DER encoded key"); Put (R); New_Line; return; end if; - WolfSSL.Rsa_SSL_Sign (Input => Original_AES_Key, - Output => Digital_Signature_Of_AES_Key, - RSA => RSA_Key, - RNG => RNG, - Result => R); + WolfSSL.Rsa_SSL_Verify + (Input => Digital_Signature_Of_AES_Key, + Output => Decrypted_Digital_Signature, + RSA => RSA_Decrypt_Key, + Result => R); if R < 0 then - Put ("Creating digital signature using RSA private key failed"); + Put ("Verify digital signature failed"); Put (R); New_Line; return; - end if; + end if; + Put ("Successful verification of RSA based digital signature."); + New_Line; end Rsa_Verify_Main; diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index d3f22c30dbc..c358d247aa4 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -983,6 +983,109 @@ package body WolfSSL is Result := Exception_Error; end Rsa_SSL_Sign; + function WC_RSA_SSL_Verify (Input : Byte_Array; + In_Length : int; + Output : in out Byte_Array; + Out_Length : int; + RSA : not null RSA_Key_Type) + return int with + Convention => C, + External_Name => "wc_RsaSSL_Verify", + Import => True; + + procedure Rsa_SSL_Verify (Input : Byte_Array; + Output : in out Byte_Array; + RSA : in out RSA_Key_Type; + Result : out Integer) is + begin + declare + R : constant int := + WC_RSA_SSL_Verify (Input, + Input'Length, + Output, + Output'Length, + RSA); + begin + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; + end Rsa_SSL_Verify; + + function WC_RSA_Public_Encrypt (Input : Byte_Array; + In_Length : int; + Output : in out Byte_Array; + Out_Length : int; + RSA : not null RSA_Key_Type; + RNG : not null RNG_Key_Type) + return int with + Convention => C, + External_Name => "wc_RsaPublicEncrypt", + Import => True; + + procedure RSA_Public_Encrypt (Input : Byte_Array; + Output : in out Byte_Array; + Index : out Byte_Index; + RSA : in out RSA_Key_Type; + RNG : in out RNG_Key_Type; + Result : out Integer) is + begin + Index := 0; + declare + R : constant int := + WC_RSA_Public_Encrypt (Input, + Input'Length, + Output, + Output'Length, + RSA, + RNG); + begin + Result := Integer (R); + if Result >= 0 then + Index := Byte_Index (Result); + end if; + end; + exception + when others => + Result := Exception_Error; + end RSA_Public_Encrypt; + + function WC_RSA_Private_Decrypt (Input : Byte_Array; + In_Length : int; + Output : in out Byte_Array; + Out_Length : int; + RSA : not null RSA_Key_Type) + return int with + Convention => C, + External_Name => "wc_RsaPrivateDecrypt", + Import => True; + + procedure RSA_Private_Decrypt (Input : Byte_Array; + Output : in out Byte_Array; + Index : out Byte_Index; + RSA : in out RSA_Key_Type; + Result : out Integer) is + begin + Index := 0; + declare + R : constant int := + WC_RSA_Private_Decrypt (Input, + Input'Length, + Output, + Output'Length, + RSA); + begin + Result := Integer (R); + if Result >= 0 then + Index := Byte_Index (Result); + end if; + end; + exception + when others => + Result := Exception_Error; + end RSA_Private_Decrypt; + function Init_SHA256 (SHA256 : not null Sha256_Type) return int with Convention => C, External_Name => "wc_InitSha256", diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index ce019f28f0b..59d6ed2d81a 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -573,6 +573,35 @@ package WolfSSL with SPARK_Mode is -- If Result < 0, then failure. -- If Result > 0, then Success and is the size of the RSA key in bytes. + procedure Rsa_SSL_Verify (Input : Byte_Array; + Output : in out Byte_Array; + RSA : in out RSA_Key_Type; + Result : out Integer) with + Pre => Is_Valid (RSA); + -- If Result < 0, then failure. + -- If Result > 0, then digital signature in Input + -- successfully verified. + + procedure RSA_Public_Encrypt (Input : Byte_Array; + Output : in out Byte_Array; + Index : out Byte_Index; + RSA : in out RSA_Key_Type; + RNG : in out RNG_Key_Type; + Result : out Integer) with + Pre => Is_Valid (RSA); + -- This function encrypts a message from Input and stores the result + -- in Output. It requires an initialized public key and a random + -- number generator. As a side effect, this function will return + -- the bytes written to Output in Index. + + procedure RSA_Private_Decrypt (Input : Byte_Array; + Output : in out Byte_Array; + Index : out Byte_Index; + RSA : in out RSA_Key_Type; + Result : out Integer) with + Pre => Is_Valid (RSA); + -- This functions provides private RSA decryption. + SHA256_INSTANCES : constant := 2; type SHA256_Index is range 0 .. SHA256_INSTANCES - 1; From 5bcb1030ce4e38e740210fb721333209d66886d8 Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Sat, 20 Dec 2025 15:52:06 +0100 Subject: [PATCH 08/51] RSA example complete. --- wrapper/Ada/rsa_verify_main.adb | 65 ++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/wrapper/Ada/rsa_verify_main.adb b/wrapper/Ada/rsa_verify_main.adb index e4e940e70e7..e04b6617f82 100644 --- a/wrapper/Ada/rsa_verify_main.adb +++ b/wrapper/Ada/rsa_verify_main.adb @@ -2,8 +2,14 @@ with Ada.Integer_Text_IO; with Ada.Text_IO; with WolfSSL; +-- If this example executes successfully the output is: +-- +-- Successful verification of RSA based digital signature. +-- Successfully encrypted and decrypted using RSA. procedure Rsa_Verify_Main is + use type WolfSSL.Byte_Array; + type Unsigned_8 is mod 2 ** 8; function To_C (Value : Unsigned_8) return WolfSSL.Byte_Type is @@ -336,6 +342,17 @@ procedure Rsa_Verify_Main is Decrypted_Digital_Signature : WolfSSL.Byte_Array (1 .. 256); + Encrypted : WolfSSL.Byte_Array (1 .. 1_024); + -- Actually only needs to be at least 256 bytes. + -- The purpose is to store the Original_AES_Key encrypted. + + Decrypted : WolfSSL.Byte_Array (1 .. 1_024); + -- Actually only needs to be at least 32 bytes. + -- The purpose is to store the Original_AES_Key after + -- first being encrypted and then decrypted. + -- After the process, this byte array should contain the same + -- contents as Original_AES_KEY. + Hash : WolfSSL.SHA256_Hash; SHA256 : WolfSSL.SHA256_Type; R : Integer; @@ -420,11 +437,10 @@ begin return; end if; - WolfSSL.Rsa_SSL_Verify - (Input => Digital_Signature_Of_AES_Key, - Output => Decrypted_Digital_Signature, - RSA => RSA_Decrypt_Key, - Result => R); + WolfSSL.Rsa_SSL_Verify (Input => Digital_Signature_Of_AES_Key, + Output => Decrypted_Digital_Signature, + RSA => RSA_Decrypt_Key, + Result => R); if R < 0 then Put ("Verify digital signature failed"); Put (R); @@ -433,4 +449,43 @@ begin end if; Put ("Successful verification of RSA based digital signature."); New_Line; + + WolfSSL.RSA_Public_Encrypt (Input => Original_AES_Key, + Output => Encrypted, + Index => Index, + RSA => RSA_Decrypt_Key, + RNG => RNG, + Result => R); + if R < 0 then + Put ("Failed to encrypt the original AES key"); + Put (R); + New_Line; + return; + end if; + + WolfSSL.RSA_Private_Decrypt (Input => Encrypted (1 .. Index), + Output => Decrypted, + Index => Index, + RSA => RSA_Encrypt_Key, + Result => R); + if R < 0 then + Put ("Failed to decrypt the encrypted original AES key"); + Put (R); + New_Line; + return; + end if; + + if Integer (Index) /= 32 then + Put ("Decryption of the encrypted original AES key, wrong size"); + New_Line; + return; + end if; + + if Original_AES_Key = Decrypted (1 .. 32) then + Put ("Successfully encrypted and decrypted using RSA."); + New_Line; + else + Put ("Failed to encrypt and decrypt original AES key."); + New_Line; + end if; end Rsa_Verify_Main; From 3ac9a5bad6fb815d2918e61e57d143f7574fb8c2 Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Sun, 21 Dec 2025 19:48:20 +0100 Subject: [PATCH 09/51] Started work on AES example. --- wrapper/Ada/ada_binding.c | 62 ++++++++++++ wrapper/Ada/aes_verify_main.adb | 84 +++++++++++++++++ wrapper/Ada/examples.gpr | 3 +- wrapper/Ada/wolfssl.adb | 161 ++++++++++++++++++++++++++++++-- wrapper/Ada/wolfssl.ads | 22 ++++- 5 files changed, 322 insertions(+), 10 deletions(-) create mode 100644 wrapper/Ada/aes_verify_main.adb diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index bbb05482512..a5880c9fee9 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -68,6 +68,18 @@ extern void* ada_new_rng (int index); extern int get_wolfssl_rng_instances(void); extern int ada_RsaSetRNG (RsaKey* key, WC_RNG* rng); +extern int get_wolfssl_invalid_devid (void); + +extern int ada_md5 (void); +extern int ada_sha (void); +extern int ada_sha256 (void); +extern int ada_sha384 (void); +extern int ada_sha512 (void); +extern int ada_sha3_224 (void); +extern int ada_sha3_256 (void); +extern int ada_sha3_384 (void); +extern int ada_sha3_512 (void); + extern int get_wolfssl_error_want_read(void) { return WOLFSSL_ERROR_WANT_READ; } @@ -161,6 +173,11 @@ extern int get_wolfssl_aes_instances(void) { return WOLFSSL_AES_INSTANCES; } +extern int get_wolfssl_invalid_devid (void) +{ + return INVALID_DEVID; +} + WC_RNG preAllocatedRNG[WOLFSSL_RNG_INSTANCES]; extern void* ada_new_rng (int index) @@ -180,3 +197,48 @@ extern int ada_RsaSetRNG(RsaKey* key, WC_RNG* rng) #endif return r; } + +extern int ada_md5 (void) +{ + return WC_MD5; +} + +extern int ada_sha (void) +{ + return WC_SHA; +} + +extern int ada_sha256 (void) +{ + return WC_SHA256; +} + +extern int ada_sha384 (void) +{ + return WC_SHA384; +} + +extern int ada_sha512 (void) +{ + return WC_SHA512; +} + +extern int ada_sha3_224 (void) +{ + return WC_SHA3_224; +} + +extern int ada_sha3_256 (void) +{ + return WC_SHA3_256; +} + +extern int ada_sha3_384 (void) +{ + return WC_SHA3_384; +} + +extern int ada_sha3_512 (void) +{ + return WC_SHA3_512; +} diff --git a/wrapper/Ada/aes_verify_main.adb b/wrapper/Ada/aes_verify_main.adb new file mode 100644 index 00000000000..0cbb530f886 --- /dev/null +++ b/wrapper/Ada/aes_verify_main.adb @@ -0,0 +1,84 @@ +with Ada.Text_IO; +with Ada.Integer_Text_IO; +with WolfSSL; +procedure AES_Verify_Main is + + use type WolfSSL.Byte_Type; + + procedure Put (Text : String) renames Ada.Text_IO.Put; + + procedure Put (Value : Integer) is + begin + Ada.Integer_Text_IO.Put (Value); + end Put; + + procedure New_Line is + begin + Ada.Text_IO.New_Line; + end New_Line; + + type Unsigned_8 is mod 2 ** 8; + + function To_C (Value : Unsigned_8) return WolfSSL.Byte_Type is + begin + return WolfSSL.Byte_Type'Val (Value); + end To_C; + + RNG : WolfSSL.RNG_Key_Type; + + + Salt_Size : constant := 8; + + Salt : WolfSSL.Byte_Array (1 .. 8); + + AES : WolfSSL.AES_Type; + R : Integer; + Pad : Integer := 3; +begin + WolfSSL.Create_RNG (Index => 0, + Key => RNG, + Result => R); + if R /= 0 then + Put ("Attaining RNG key instance failed"); + New_Line; + return; + end if; + + WolfSSL.RNG_Generate_Block (RNG => RNG, + Output => Salt, + Result => R); + if R /= 0 then + Put ("Generating random salt"); + New_Line; + return; + end if; + + if Pad = 0 then + Salt (1) := To_C (0); + elsif Salt (1) = To_C (0) then + Salt (1) := To_C (1); + end if; + + WolfSSL.Create_AES (Index => 0, + Device => WolfSSL.Invalid_Device, + AES => AES, + Result => R); + if R /= 0 then + Put ("Attaining AES key instance failed"); + New_Line; + return; + end if; + + -- WolfSSL.PBKDF2 (Output => , + -- Password => , + -- Salt => , + -- Iterations => , + -- Key_Length => , + -- HMAC => , + -- Result => R); + -- if R /= 0 then + -- Put ("Attaining AES key instance failed"); + -- New_Line; + -- return; + -- end if; +end AES_Verify_Main; diff --git a/wrapper/Ada/examples.gpr b/wrapper/Ada/examples.gpr index 72ccfed913e..94d4b467d81 100644 --- a/wrapper/Ada/examples.gpr +++ b/wrapper/Ada/examples.gpr @@ -15,7 +15,8 @@ project Examples is for Main use ("tls_server_main.adb", "tls_client_main.adb", "sha256_main.adb", - "rsa_verify_main.adb"); + "rsa_verify_main.adb", + "aes_verify_main.adb"); package Naming is for Spec_Suffix ("C") use ".h"; diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index c358d247aa4..1c8b65c7448 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -838,16 +838,147 @@ package body WolfSSL is procedure Create_RNG (Index : RNG_Key_Index; Key : in out RNG_Key_Type; Result : out Integer) is - R : int; begin - Key := Ada_New_RNG (int (Index)); - R := Init_RNG_Key (Key); - Result := Integer (R); + Result := -121212; + declare + R : int; + begin + Key := Ada_New_RNG (int (Index)); + R := Init_RNG_Key (Key); + Result := Integer (R); + end; exception when others => Result := Exception_Error; end Create_RNG; + function WC_RNG_Generate_Block (RNG : not null RNG_Key_Type; + Output : out Byte_Array; + Size : int) return int with + Convention => C, + External_Name => "wc_RNG_GenerateBlock", + Import => True; + + procedure RNG_Generate_Block (RNG : RNG_Key_Type; + Output : out Byte_Array; + Result : out Integer) is + begin + Result := -121212; + declare + R : int; + begin + R := WC_RNG_Generate_Block (RNG, Output, Output'Length); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; + end RNG_Generate_Block; + + type Unsigned_8 is mod 2 ** 8; + + function To_C (Value : Unsigned_8) return WolfSSL.Byte_Type is + begin + return WolfSSL.Byte_Type'Val (Value); + end To_C; + + function WC_PBKDF2 (Output : out Byte_Array; + Password : Byte_Array; + P_Length : int; + Salt : Byte_Array; + S_Length : int; + Iterations : int; + Key_Length : int; + Hash_Type : int) return int with + Convention => C, + External_Name => "wc_PBKDF2", + Import => True; + + function Ada_MD5 return int with + Convention => C, + External_Name => "ada_md5", + Import => True; + + function Ada_SHA return int with + Convention => C, + External_Name => "ada_sha", + Import => True; + + function Ada_SHA256 return int with + Convention => C, + External_Name => "ada_sha256", + Import => True; + + function Ada_SHA384 return int with + Convention => C, + External_Name => "ada_sha384", + Import => True; + + function Ada_SHA512 return int with + Convention => C, + External_Name => "ada_sha512", + Import => True; + + function Ada_SHA3_224 return int with + Convention => C, + External_Name => "ada_sha3_224", + Import => True; + + function Ada_SHA3_256 return int with + Convention => C, + External_Name => "ada_sha3_256", + Import => True; + + function Ada_SHA3_384 return int with + Convention => C, + External_Name => "ada_sha3_384", + Import => True; + + function Ada_SHA3_512 return int with + Convention => C, + External_Name => "ada_sha3_512", + Import => True; + + procedure PBKDF2 (Output : out Byte_Array; + Password : Byte_Array; + Salt : Byte_Array; + Iterations : Positive; + Key_Length : Positive; + HMAC : HMAC_Hash; + Result : out Integer) is + begin + Result := -121212; + Output := (others => To_C (0)); + declare + R : int; + H : int; + begin + case HMAC is + when MD5 => H := Ada_MD5; + when SHA => H := Ada_SHA; + when SHA256 => H := Ada_SHA256; + when SHA384 => H := Ada_SHA384; + when SHA512 => H := Ada_SHA512; + when SHA3_224 => H := Ada_SHA3_224; + when SHA3_256 => H := Ada_SHA3_256; + when SHA3_384 => H := Ada_SHA3_384; + when SHA3_512 => H := Ada_SHA3_512; + end case; + R := WC_PBKDF2 (Output => Output, + Password => Password, + P_Length => Password'Length, + Salt => Salt, + S_Length => Salt'Length, + Iterations => int (Iterations), + Key_Length => int (Key_Length), + Hash_Type => H); + Result := Integer (R); + end; + exception + when others => + Result := Exception_Error; + end PBKDF2; + function Ada_RSA_Set_RNG (Key : not null RSA_Key_Type; RNG : not null RNG_Key_Type) return int with Convention => C, @@ -857,10 +988,14 @@ package body WolfSSL is procedure Rsa_Set_RNG (Key : in out Rsa_Key_Type; RNG : in out RNG_Key_Type; Result : out Integer) is - R : int; begin - R := Ada_RSA_Set_RNG (Key, RNG); - Result := Integer (R); + Result := -121212; + declare + R : int; + begin + R := Ada_RSA_Set_RNG (Key, RNG); + Result := Integer (R); + end; exception when others => Result := Exception_Error; @@ -1173,6 +1308,16 @@ package body WolfSSL is Result := Exception_Error; end Finalize_SHA256; + function WC_Get_Invalid_Device_Identifier return int with + Convention => C, + External_Name => "get_wolfssl_invalid_devid", + Import => True; + + function Invalid_Device return Device_Identifier is + begin + return Device_Identifier (WC_Get_Invalid_Device_Identifier); + end Invalid_Device; + function Is_Valid (AES : AES_Type) return Boolean is begin return AES /= null; @@ -1192,7 +1337,7 @@ package body WolfSSL is Import => True; procedure Create_AES (Index : AES_Index; - Device : Integer; + Device : Device_Identifier; AES : in out AES_Type; Result : out Integer) is begin diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 59d6ed2d81a..367fa2b493f 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -516,6 +516,22 @@ package WolfSSL with SPARK_Mode is Post => (if Result = 0 then Is_Valid (Key)); -- If successful Result = 0. + procedure RNG_Generate_Block (RNG : RNG_Key_Type; + Output : out Byte_Array; + Result : out Integer) with + Pre => Is_Valid (RNG); + + type HMAC_Hash is (MD5, SHA, SHA256, SHA384, SHA512, SHA3_224, + SHA3_256, SHA3_384, SHA3_512); + + procedure PBKDF2 (Output : out Byte_Array; + Password : Byte_Array; + Salt : Byte_Array; + Iterations : Positive; + Key_Length : Positive; + HMAC : HMAC_Hash; + Result : out Integer); + RSA_INSTANCES : constant := 2; type RSA_Key_Index is range 0 .. RSA_INSTANCES - 1; @@ -634,6 +650,10 @@ package WolfSSL with SPARK_Mode is Pre => Is_Valid (SHA256); -- If successful Result = 0. + type Device_Identifier is new Integer; + + function Invalid_Device return Device_Identifier; + AES_INSTANCES : constant := 2; type AES_Index is range 0 .. AES_INSTANCES - 1; @@ -643,7 +663,7 @@ package WolfSSL with SPARK_Mode is -- Indicates if the AES has successfully been initialized. procedure Create_AES (Index : AES_Index; - Device : Integer; + Device : Device_Identifier; AES : in out AES_Type; Result : out Integer) with Pre => not Is_Valid (AES); From 367c359688c4cefd02197b43014ae95c395bf44b Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 22 Dec 2025 22:19:58 +0100 Subject: [PATCH 10/51] Add AUnit SHA256 binding tests for Ada wrapper --- wrapper/Ada/tests/.gitignore | 4 + wrapper/Ada/tests/alire.toml | 15 ++ .../Ada/tests/src/sha256_bindings_tests.adb | 207 ++++++++++++++++++ .../Ada/tests/src/sha256_bindings_tests.ads | 18 ++ wrapper/Ada/tests/src/sha256_suite.adb | 17 ++ wrapper/Ada/tests/src/sha256_suite.ads | 6 + wrapper/Ada/tests/src/tests.adb | 14 ++ wrapper/Ada/tests/tests.gpr | 31 +++ 8 files changed, 312 insertions(+) create mode 100644 wrapper/Ada/tests/.gitignore create mode 100644 wrapper/Ada/tests/alire.toml create mode 100644 wrapper/Ada/tests/src/sha256_bindings_tests.adb create mode 100644 wrapper/Ada/tests/src/sha256_bindings_tests.ads create mode 100644 wrapper/Ada/tests/src/sha256_suite.adb create mode 100644 wrapper/Ada/tests/src/sha256_suite.ads create mode 100644 wrapper/Ada/tests/src/tests.adb create mode 100644 wrapper/Ada/tests/tests.gpr diff --git a/wrapper/Ada/tests/.gitignore b/wrapper/Ada/tests/.gitignore new file mode 100644 index 00000000000..5866d7bfa6b --- /dev/null +++ b/wrapper/Ada/tests/.gitignore @@ -0,0 +1,4 @@ +/obj/ +/bin/ +/alire/ +/config/ diff --git a/wrapper/Ada/tests/alire.toml b/wrapper/Ada/tests/alire.toml new file mode 100644 index 00000000000..4ac485eb8f9 --- /dev/null +++ b/wrapper/Ada/tests/alire.toml @@ -0,0 +1,15 @@ +name = "tests" +description = "Tests for the wolfssl ada bindings" +version = "0.1.0-dev" + +authors = ["Juliusz Sosinowicz"] +maintainers = ["Juliusz Sosinowicz "] +maintainers-logins = ["julek-wolfssl"] +licenses = "GPL-3.0-or-later" +website = "https://www.wolfssl.com" +tags = ["ssl", "tests"] + +executables = ["tests"] + +[[depends-on]] +aunit = "^26.0.0" diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.adb b/wrapper/Ada/tests/src/sha256_bindings_tests.adb new file mode 100644 index 00000000000..d4062269149 --- /dev/null +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.adb @@ -0,0 +1,207 @@ +with AUnit.Assertions; +with AUnit.Test_Caller; +with AUnit.Test_Fixtures; +with AUnit.Test_Suites; + +with Interfaces.C; +with WolfSSL; + +package body SHA256_Bindings_Tests is + + type Fixture is new AUnit.Test_Fixtures.Test_Fixture with null record; + + procedure Assert_Text_Matches_Hash + (Hash : WolfSSL.SHA256_Hash; + Text : WolfSSL.SHA256_As_String; + Msg : String); + + procedure Compute_SHA256 + (Input : WolfSSL.Byte_Array; + Hash : out WolfSSL.SHA256_Hash; + Text : out WolfSSL.SHA256_As_String; + Result : out Integer); + + procedure Test_SHA256_Asdf_Known_Vector (F : in out Fixture); + procedure Test_SHA256_Empty_Message (F : in out Fixture); + + procedure Assert_Text_Matches_Hash + (Hash : WolfSSL.SHA256_Hash; + Text : WolfSSL.SHA256_As_String; + Msg : String) + is + function Hex_Value (C : Character) return Natural is + begin + case C is + when '0' .. '9' => + return Character'Pos (C) - Character'Pos ('0'); + when 'A' .. 'F' => + return 10 + (Character'Pos (C) - Character'Pos ('A')); + when 'a' .. 'f' => + return 10 + (Character'Pos (C) - Character'Pos ('a')); + when others => + AUnit.Assertions.Assert + (False, + Msg & ": invalid hex character '" & C & "'"); + return 0; + end case; + end Hex_Value; + + I : Positive; + Hi : Natural; + Lo : Natural; + Byte_As_Int : Natural; + begin + AUnit.Assertions.Assert + (Text'Length = 64, + Msg & ": expected 64 hex chars, got" & Integer'Image (Text'Length)); + + for Index in Positive range 1 .. 32 loop + I := 2 * (Index - 1) + 1; + Hi := Hex_Value (Text (I)); + Lo := Hex_Value (Text (I + 1)); + + Byte_As_Int := 16 * Hi + Lo; + + -- Hash elements are `Interfaces.C.char`, so compare with `char'Pos`. + -- If your binding changes `Byte_Array` element type, tell me and I'll + -- adjust this conversion. + AUnit.Assertions.Assert + (Byte_As_Int = + Interfaces.C.char'Pos (Hash (Interfaces.C.size_t (Index))), + Msg & ": Text/Hash mismatch at byte" & + Integer'Image (Index)); + end loop; + + -- `Finalize_SHA256` generates uppercase hex, validate that expectation. + for J in Text'Range loop + declare + C : constant Character := Text (J); + begin + if C in '0' .. '9' or else C in 'A' .. 'F' then + null; + else + AUnit.Assertions.Assert + (False, + Msg & ": expected uppercase hex at pos" & + Integer'Image (J)); + end if; + end; + end loop; + end Assert_Text_Matches_Hash; + + procedure Compute_SHA256 + (Input : WolfSSL.Byte_Array; + Hash : out WolfSSL.SHA256_Hash; + Text : out WolfSSL.SHA256_As_String; + Result : out Integer) + is + SHA256 : WolfSSL.SHA256_Type; + R : Integer; + begin + -- Follow the example in `sha256_main.adb` (Index => 1). + WolfSSL.Create_SHA256 (Index => 1, SHA256 => SHA256, Result => R); + if R /= 0 then + Result := R; + return; + end if; + + WolfSSL.Update_SHA256 (SHA256 => SHA256, Byte => Input, Result => R); + if R /= 0 then + Result := R; + return; + end if; + + WolfSSL.Finalize_SHA256 + (SHA256 => SHA256, + Hash => Hash, + Text => Text, + Result => R); + + Result := R; + end Compute_SHA256; + + procedure Test_SHA256_Asdf_Known_Vector (F : in out Fixture) is + pragma Unreferenced (F); + + Hash : WolfSSL.SHA256_Hash; + Text : WolfSSL.SHA256_As_String; + R : Integer; + + Input : constant WolfSSL.Byte_Array := + (1 => 'a', + 2 => 's', + 3 => 'd', + 4 => 'f'); + + Expected_Text : constant WolfSSL.SHA256_As_String := + "F0E4C2F76C58916EC258F246851BEA091D14D4247A2FC3E18694461B1816E13B"; + begin + Compute_SHA256 (Input => Input, Hash => Hash, Text => Text, Result => R); + + AUnit.Assertions.Assert + (R = 0, + "SHA256('asdf') bindings should succeed, Result =" & + Integer'Image (R)); + + AUnit.Assertions.Assert + (Text = Expected_Text, + "SHA256('asdf') hex mismatch. Got: " & Text); + + Assert_Text_Matches_Hash + (Hash => Hash, Text => Text, Msg => "SHA256('asdf')"); + end Test_SHA256_Asdf_Known_Vector; + + procedure Test_SHA256_Empty_Message (F : in out Fixture) is + pragma Unreferenced (F); + + Hash : WolfSSL.SHA256_Hash; + Text : WolfSSL.SHA256_As_String; + R : Integer; + + -- If this doesn't compile depending on how `Byte_Array` is declared, + -- tell me the exact declaration from `wolfssl.ads` and I will rework + -- this test to produce an empty input safely. + Empty : constant WolfSSL.Byte_Array := (1 .. 0 => <>); + + Expected_Text : constant WolfSSL.SHA256_As_String := + "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"; + begin + Compute_SHA256 (Input => Empty, Hash => Hash, Text => Text, Result => R); + + AUnit.Assertions.Assert + (R = 0, + "SHA256('') bindings should succeed, Result =" & + Integer'Image (R)); + + AUnit.Assertions.Assert + (Text = Expected_Text, + "SHA256('') hex mismatch. Got: " & Text); + + Assert_Text_Matches_Hash + (Hash => Hash, + Text => Text, + Msg => "SHA256('')"); + end Test_SHA256_Empty_Message; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + package Caller is new AUnit.Test_Caller (Fixture); + + S : constant AUnit.Test_Suites.Access_Test_Suite := + new AUnit.Test_Suites.Test_Suite; + begin + AUnit.Test_Suites.Add_Test + (S, + Caller.Create + (Name => "SHA256('asdf') produces expected hash", + Test => Test_SHA256_Asdf_Known_Vector'Access)); + + AUnit.Test_Suites.Add_Test + (S, + Caller.Create + (Name => "SHA256('') produces expected hash", + Test => Test_SHA256_Empty_Message'Access)); + + return S; + end Suite; + +end SHA256_Bindings_Tests; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.ads b/wrapper/Ada/tests/src/sha256_bindings_tests.ads new file mode 100644 index 00000000000..e37644673a2 --- /dev/null +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.ads @@ -0,0 +1,18 @@ +with AUnit.Test_Suites; + +package SHA256_Bindings_Tests is + + -- Tests for the WolfSSL SHA256 Ada bindings: + -- - Create_SHA256 + -- - Update_SHA256 + -- - Finalize_SHA256 + -- + -- This package follows AUnit's "Test_Caller" model (not Test_Cases with + -- Registration) to avoid depending on optional child units and to keep the + -- boilerplate small. + -- + -- Suite returns a suite containing all SHA256-related tests. + + function Suite return AUnit.Test_Suites.Access_Test_Suite; + +end SHA256_Bindings_Tests; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/sha256_suite.adb b/wrapper/Ada/tests/src/sha256_suite.adb new file mode 100644 index 00000000000..6075863c7c4 --- /dev/null +++ b/wrapper/Ada/tests/src/sha256_suite.adb @@ -0,0 +1,17 @@ +with AUnit.Test_Suites; + +with SHA256_Bindings_Tests; + +package body SHA256_Suite is + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + S : constant AUnit.Test_Suites.Access_Test_Suite := + new AUnit.Test_Suites.Test_Suite; + begin + -- Register SHA256-related test suites here. + AUnit.Test_Suites.Add_Test (S, SHA256_Bindings_Tests.Suite); + + return S; + end Suite; + +end SHA256_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/sha256_suite.ads b/wrapper/Ada/tests/src/sha256_suite.ads new file mode 100644 index 00000000000..68b514efcf3 --- /dev/null +++ b/wrapper/Ada/tests/src/sha256_suite.ads @@ -0,0 +1,6 @@ +with AUnit.Test_Suites; + +package SHA256_Suite is + -- Aggregate suite for SHA256 binding tests. + function Suite return AUnit.Test_Suites.Access_Test_Suite; +end SHA256_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/tests.adb b/wrapper/Ada/tests/src/tests.adb new file mode 100644 index 00000000000..3d6e476ac45 --- /dev/null +++ b/wrapper/Ada/tests/src/tests.adb @@ -0,0 +1,14 @@ +with AUnit.Reporter.Text; +with AUnit.Run; + +-- Minimal AUnit runner. +-- AUnit uses a generic test runner instantiated with your suite function. +with SHA256_Suite; + +procedure Tests is + procedure Runner is new AUnit.Run.Test_Runner (SHA256_Suite.Suite); + + Reporter : AUnit.Reporter.Text.Text_Reporter; +begin + Runner (Reporter); +end Tests; \ No newline at end of file diff --git a/wrapper/Ada/tests/tests.gpr b/wrapper/Ada/tests/tests.gpr new file mode 100644 index 00000000000..cde3f4cca84 --- /dev/null +++ b/wrapper/Ada/tests/tests.gpr @@ -0,0 +1,31 @@ +with "config/tests_config.gpr"; +with "../wolfssl.gpr"; + +project Tests is + + for Source_Dirs use ("src/", "config/"); + for Object_Dir use "obj/" & Tests_Config.Build_Profile; + for Create_Missing_Dirs use "True"; + for Exec_Dir use "bin"; + for Main use ("tests.adb"); + + package Compiler is + for Default_Switches ("Ada") use Tests_Config.Ada_Compiler_Switches; + end Compiler; + + package Binder is + for Switches ("Ada") use ("-Es"); -- Symbolic traceback + end Binder; + + package Linker is + -- WolfSSL uses libm on Linux/macOS; wolfssl.gpr already encodes OS-specifics, + -- but we repeat "-lm" here so the standalone tests executable links when + -- consumed without a full project tree. + for Switches ("Ada") use ("-lm"); + end Linker; + + package Install is + for Artifacts (".") use ("share"); + end Install; + +end Tests; From 1c39528d076c115a8c618fc912393e28c512471b Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 22 Dec 2025 22:49:17 +0100 Subject: [PATCH 11/51] Add AUnit RSA sign/verify tests and clean up Ada tests warnings --- wrapper/Ada/tests/src/rsa_suite.adb | 15 + wrapper/Ada/tests/src/rsa_suite.ads | 6 + .../tests/src/rsa_verify_bindings_tests.adb | 457 ++++++++++++++++++ .../tests/src/rsa_verify_bindings_tests.ads | 23 + .../Ada/tests/src/sha256_bindings_tests.adb | 16 +- .../Ada/tests/src/sha256_bindings_tests.ads | 6 + wrapper/Ada/tests/src/sha256_suite.adb | 2 - wrapper/Ada/tests/src/tests.adb | 15 +- wrapper/Ada/tests/tests.gpr | 7 +- 9 files changed, 531 insertions(+), 16 deletions(-) create mode 100644 wrapper/Ada/tests/src/rsa_suite.adb create mode 100644 wrapper/Ada/tests/src/rsa_suite.ads create mode 100644 wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb create mode 100644 wrapper/Ada/tests/src/rsa_verify_bindings_tests.ads diff --git a/wrapper/Ada/tests/src/rsa_suite.adb b/wrapper/Ada/tests/src/rsa_suite.adb new file mode 100644 index 00000000000..15a7b222786 --- /dev/null +++ b/wrapper/Ada/tests/src/rsa_suite.adb @@ -0,0 +1,15 @@ +with RSA_Verify_Bindings_Tests; + +package body RSA_Suite is + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + S : constant AUnit.Test_Suites.Access_Test_Suite := + new AUnit.Test_Suites.Test_Suite; + begin + -- Register RSA-related test suites here. + AUnit.Test_Suites.Add_Test (S, RSA_Verify_Bindings_Tests.Suite); + + return S; + end Suite; + +end RSA_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/rsa_suite.ads b/wrapper/Ada/tests/src/rsa_suite.ads new file mode 100644 index 00000000000..65c37f37efe --- /dev/null +++ b/wrapper/Ada/tests/src/rsa_suite.ads @@ -0,0 +1,6 @@ +with AUnit.Test_Suites; + +package RSA_Suite is + -- Aggregate suite for RSA binding tests. + function Suite return AUnit.Test_Suites.Access_Test_Suite; +end RSA_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb new file mode 100644 index 00000000000..3569ea57835 --- /dev/null +++ b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb @@ -0,0 +1,457 @@ +with AUnit.Assertions; +with AUnit.Test_Caller; +with AUnit.Test_Fixtures; + +with WolfSSL; + +package body RSA_Verify_Bindings_Tests is + + type Fixture is new AUnit.Test_Fixtures.Test_Fixture with null record; + + type Unsigned_8 is mod 2 ** 8; + + function To_C (Value : Unsigned_8) return WolfSSL.Byte_Type is + begin + return WolfSSL.Byte_Type'Val (Value); + end To_C; + + use type WolfSSL.Byte_Array; + use type WolfSSL.Byte_Index; + + -- RSA public key to verify with (DER) - copied from rsa_verify_main.adb. + Rsa_Public_Key_2048 : constant WolfSSL.Byte_Array := + (To_C (16#30#), To_C (16#82#), To_C (16#01#), To_C (16#22#), To_C (16#30#), + To_C (16#0D#), To_C (16#06#), To_C (16#09#), To_C (16#2A#), To_C (16#86#), + To_C (16#48#), To_C (16#86#), To_C (16#F7#), To_C (16#0D#), To_C (16#01#), + To_C (16#01#), To_C (16#01#), To_C (16#05#), To_C (16#00#), To_C (16#03#), + To_C (16#82#), To_C (16#01#), To_C (16#0F#), To_C (16#00#), To_C (16#30#), + To_C (16#82#), To_C (16#01#), To_C (16#0A#), To_C (16#02#), To_C (16#82#), + To_C (16#01#), To_C (16#01#), To_C (16#00#), To_C (16#C3#), To_C (16#03#), + To_C (16#D1#), To_C (16#2B#), To_C (16#FE#), To_C (16#39#), To_C (16#A4#), + To_C (16#32#), To_C (16#45#), To_C (16#3B#), To_C (16#53#), To_C (16#C8#), + To_C (16#84#), To_C (16#2B#), To_C (16#2A#), To_C (16#7C#), To_C (16#74#), + To_C (16#9A#), To_C (16#BD#), To_C (16#AA#), To_C (16#2A#), To_C (16#52#), + To_C (16#07#), To_C (16#47#), To_C (16#D6#), To_C (16#A6#), To_C (16#36#), + To_C (16#B2#), To_C (16#07#), To_C (16#32#), To_C (16#8E#), To_C (16#D0#), + To_C (16#BA#), To_C (16#69#), To_C (16#7B#), To_C (16#C6#), To_C (16#C3#), + To_C (16#44#), To_C (16#9E#), To_C (16#D4#), To_C (16#81#), To_C (16#48#), + To_C (16#FD#), To_C (16#2D#), To_C (16#68#), To_C (16#A2#), To_C (16#8B#), + To_C (16#67#), To_C (16#BB#), To_C (16#A1#), To_C (16#75#), To_C (16#C8#), + To_C (16#36#), To_C (16#2C#), To_C (16#4A#), To_C (16#D2#), To_C (16#1B#), + To_C (16#F7#), To_C (16#8B#), To_C (16#BA#), To_C (16#CF#), To_C (16#0D#), + To_C (16#F9#), To_C (16#EF#), To_C (16#EC#), To_C (16#F1#), To_C (16#81#), + To_C (16#1E#), To_C (16#7B#), To_C (16#9B#), To_C (16#03#), To_C (16#47#), + To_C (16#9A#), To_C (16#BF#), To_C (16#65#), To_C (16#CC#), To_C (16#7F#), + To_C (16#65#), To_C (16#24#), To_C (16#69#), To_C (16#A6#), To_C (16#E8#), + To_C (16#14#), To_C (16#89#), To_C (16#5B#), To_C (16#E4#), To_C (16#34#), + To_C (16#F7#), To_C (16#C5#), To_C (16#B0#), To_C (16#14#), To_C (16#93#), + To_C (16#F5#), To_C (16#67#), To_C (16#7B#), To_C (16#3A#), To_C (16#7A#), + To_C (16#78#), To_C (16#E1#), To_C (16#01#), To_C (16#56#), To_C (16#56#), + To_C (16#91#), To_C (16#A6#), To_C (16#13#), To_C (16#42#), To_C (16#8D#), + To_C (16#D2#), To_C (16#3C#), To_C (16#40#), To_C (16#9C#), To_C (16#4C#), + To_C (16#EF#), To_C (16#D1#), To_C (16#86#), To_C (16#DF#), To_C (16#37#), + To_C (16#51#), To_C (16#1B#), To_C (16#0C#), To_C (16#A1#), To_C (16#3B#), + To_C (16#F5#), To_C (16#F1#), To_C (16#A3#), To_C (16#4A#), To_C (16#35#), + To_C (16#E4#), To_C (16#E1#), To_C (16#CE#), To_C (16#96#), To_C (16#DF#), + To_C (16#1B#), To_C (16#7E#), To_C (16#BF#), To_C (16#4E#), To_C (16#97#), + To_C (16#D0#), To_C (16#10#), To_C (16#E8#), To_C (16#A8#), To_C (16#08#), + To_C (16#30#), To_C (16#81#), To_C (16#AF#), To_C (16#20#), To_C (16#0B#), + To_C (16#43#), To_C (16#14#), To_C (16#C5#), To_C (16#74#), To_C (16#67#), + To_C (16#B4#), To_C (16#32#), To_C (16#82#), To_C (16#6F#), To_C (16#8D#), + To_C (16#86#), To_C (16#C2#), To_C (16#88#), To_C (16#40#), To_C (16#99#), + To_C (16#36#), To_C (16#83#), To_C (16#BA#), To_C (16#1E#), To_C (16#40#), + To_C (16#72#), To_C (16#22#), To_C (16#17#), To_C (16#D7#), To_C (16#52#), + To_C (16#65#), To_C (16#24#), To_C (16#73#), To_C (16#B0#), To_C (16#CE#), + To_C (16#EF#), To_C (16#19#), To_C (16#CD#), To_C (16#AE#), To_C (16#FF#), + To_C (16#78#), To_C (16#6C#), To_C (16#7B#), To_C (16#C0#), To_C (16#12#), + To_C (16#03#), To_C (16#D4#), To_C (16#4E#), To_C (16#72#), To_C (16#0D#), + To_C (16#50#), To_C (16#6D#), To_C (16#3B#), To_C (16#A3#), To_C (16#3B#), + To_C (16#A3#), To_C (16#99#), To_C (16#5E#), To_C (16#9D#), To_C (16#C8#), + To_C (16#D9#), To_C (16#0C#), To_C (16#85#), To_C (16#B3#), To_C (16#D9#), + To_C (16#8A#), To_C (16#D9#), To_C (16#54#), To_C (16#26#), To_C (16#DB#), + To_C (16#6D#), To_C (16#FA#), To_C (16#AC#), To_C (16#BB#), To_C (16#FF#), + To_C (16#25#), To_C (16#4C#), To_C (16#C4#), To_C (16#D1#), To_C (16#79#), + To_C (16#F4#), To_C (16#71#), To_C (16#D3#), To_C (16#86#), To_C (16#40#), + To_C (16#18#), To_C (16#13#), To_C (16#B0#), To_C (16#63#), To_C (16#B5#), + To_C (16#72#), To_C (16#4E#), To_C (16#30#), To_C (16#C4#), To_C (16#97#), + To_C (16#84#), To_C (16#86#), To_C (16#2D#), To_C (16#56#), To_C (16#2F#), + To_C (16#D7#), To_C (16#15#), To_C (16#F7#), To_C (16#7F#), To_C (16#C0#), + To_C (16#AE#), To_C (16#F5#), To_C (16#FC#), To_C (16#5B#), To_C (16#E5#), + To_C (16#FB#), To_C (16#A1#), To_C (16#BA#), To_C (16#D3#), To_C (16#02#), + To_C (16#03#), To_C (16#01#), To_C (16#00#), To_C (16#01#)); + + -- Private key (DER) - copied from rsa_verify_main.adb. + -- + -- Note: This is long, but keeping it embedded avoids any assumptions about + -- external files and precisely matches the example. + Client_Private_Key_2048 : constant WolfSSL.Byte_Array := + (To_C (16#30#), To_C (16#82#), To_C (16#04#), To_C (16#A4#), To_C (16#02#), + To_C (16#01#), To_C (16#00#), To_C (16#02#), To_C (16#82#), To_C (16#01#), + To_C (16#01#), To_C (16#00#), To_C (16#C3#), To_C (16#03#), To_C (16#D1#), + To_C (16#2B#), To_C (16#FE#), To_C (16#39#), To_C (16#A4#), To_C (16#32#), + To_C (16#45#), To_C (16#3B#), To_C (16#53#), To_C (16#C8#), To_C (16#84#), + To_C (16#2B#), To_C (16#2A#), To_C (16#7C#), To_C (16#74#), To_C (16#9A#), + To_C (16#BD#), To_C (16#AA#), To_C (16#2A#), To_C (16#52#), To_C (16#07#), + To_C (16#47#), To_C (16#D6#), To_C (16#A6#), To_C (16#36#), To_C (16#B2#), + To_C (16#07#), To_C (16#32#), To_C (16#8E#), To_C (16#D0#), To_C (16#BA#), + To_C (16#69#), To_C (16#7B#), To_C (16#C6#), To_C (16#C3#), To_C (16#44#), + To_C (16#9E#), To_C (16#D4#), To_C (16#81#), To_C (16#48#), To_C (16#FD#), + To_C (16#2D#), To_C (16#68#), To_C (16#A2#), To_C (16#8B#), To_C (16#67#), + To_C (16#BB#), To_C (16#A1#), To_C (16#75#), To_C (16#C8#), To_C (16#36#), + To_C (16#2C#), To_C (16#4A#), To_C (16#D2#), To_C (16#1B#), To_C (16#F7#), + To_C (16#8B#), To_C (16#BA#), To_C (16#CF#), To_C (16#0D#), To_C (16#F9#), + To_C (16#EF#), To_C (16#EC#), To_C (16#F1#), To_C (16#81#), To_C (16#1E#), + To_C (16#7B#), To_C (16#9B#), To_C (16#03#), To_C (16#47#), To_C (16#9A#), + To_C (16#BF#), To_C (16#65#), To_C (16#CC#), To_C (16#7F#), To_C (16#65#), + To_C (16#24#), To_C (16#69#), To_C (16#A6#), To_C (16#E8#), To_C (16#14#), + To_C (16#89#), To_C (16#5B#), To_C (16#E4#), To_C (16#34#), To_C (16#F7#), + To_C (16#C5#), To_C (16#B0#), To_C (16#14#), To_C (16#93#), To_C (16#F5#), + To_C (16#67#), To_C (16#7B#), To_C (16#3A#), To_C (16#7A#), To_C (16#78#), + To_C (16#E1#), To_C (16#01#), To_C (16#56#), To_C (16#56#), To_C (16#91#), + To_C (16#A6#), To_C (16#13#), To_C (16#42#), To_C (16#8D#), To_C (16#D2#), + To_C (16#3C#), To_C (16#40#), To_C (16#9C#), To_C (16#4C#), To_C (16#EF#), + To_C (16#D1#), To_C (16#86#), To_C (16#DF#), To_C (16#37#), To_C (16#51#), + To_C (16#1B#), To_C (16#0C#), To_C (16#A1#), To_C (16#3B#), To_C (16#F5#), + To_C (16#F1#), To_C (16#A3#), To_C (16#4A#), To_C (16#35#), To_C (16#E4#), + To_C (16#E1#), To_C (16#CE#), To_C (16#96#), To_C (16#DF#), To_C (16#1B#), + To_C (16#7E#), To_C (16#BF#), To_C (16#4E#), To_C (16#97#), To_C (16#D0#), + To_C (16#10#), To_C (16#E8#), To_C (16#A8#), To_C (16#08#), To_C (16#30#), + To_C (16#81#), To_C (16#AF#), To_C (16#20#), To_C (16#0B#), To_C (16#43#), + To_C (16#14#), To_C (16#C5#), To_C (16#74#), To_C (16#67#), To_C (16#B4#), + To_C (16#32#), To_C (16#82#), To_C (16#6F#), To_C (16#8D#), To_C (16#86#), + To_C (16#C2#), To_C (16#88#), To_C (16#40#), To_C (16#99#), To_C (16#36#), + To_C (16#83#), To_C (16#BA#), To_C (16#1E#), To_C (16#40#), To_C (16#72#), + To_C (16#22#), To_C (16#17#), To_C (16#D7#), To_C (16#52#), To_C (16#65#), + To_C (16#24#), To_C (16#73#), To_C (16#B0#), To_C (16#CE#), To_C (16#EF#), + To_C (16#19#), To_C (16#CD#), To_C (16#AE#), To_C (16#FF#), To_C (16#78#), + To_C (16#6C#), To_C (16#7B#), To_C (16#C0#), To_C (16#12#), To_C (16#03#), + To_C (16#D4#), To_C (16#4E#), To_C (16#72#), To_C (16#0D#), To_C (16#50#), + To_C (16#6D#), To_C (16#3B#), To_C (16#A3#), To_C (16#3B#), To_C (16#A3#), + To_C (16#99#), To_C (16#5E#), To_C (16#9D#), To_C (16#C8#), To_C (16#D9#), + To_C (16#0C#), To_C (16#85#), To_C (16#B3#), To_C (16#D9#), To_C (16#8A#), + To_C (16#D9#), To_C (16#54#), To_C (16#26#), To_C (16#DB#), To_C (16#6D#), + To_C (16#FA#), To_C (16#AC#), To_C (16#BB#), To_C (16#FF#), To_C (16#25#), + To_C (16#4C#), To_C (16#C4#), To_C (16#D1#), To_C (16#79#), To_C (16#F4#), + To_C (16#71#), To_C (16#D3#), To_C (16#86#), To_C (16#40#), To_C (16#18#), + To_C (16#13#), To_C (16#B0#), To_C (16#63#), To_C (16#B5#), To_C (16#72#), + To_C (16#4E#), To_C (16#30#), To_C (16#C4#), To_C (16#97#), To_C (16#84#), + To_C (16#86#), To_C (16#2D#), To_C (16#56#), To_C (16#2F#), To_C (16#D7#), + To_C (16#15#), To_C (16#F7#), To_C (16#7F#), To_C (16#C0#), To_C (16#AE#), + To_C (16#F5#), To_C (16#FC#), To_C (16#5B#), To_C (16#E5#), To_C (16#FB#), + To_C (16#A1#), To_C (16#BA#), To_C (16#D3#), To_C (16#02#), To_C (16#03#), + To_C (16#01#), To_C (16#00#), To_C (16#01#), To_C (16#02#), To_C (16#82#), + To_C (16#01#), To_C (16#01#), To_C (16#00#), To_C (16#A2#), To_C (16#E6#), + To_C (16#D8#), To_C (16#5F#), To_C (16#10#), To_C (16#71#), To_C (16#64#), + To_C (16#08#), To_C (16#9E#), To_C (16#2E#), To_C (16#6D#), To_C (16#D1#), + To_C (16#6D#), To_C (16#1E#), To_C (16#85#), To_C (16#D2#), To_C (16#0A#), + To_C (16#B1#), To_C (16#8C#), To_C (16#47#), To_C (16#CE#), To_C (16#2C#), + To_C (16#51#), To_C (16#6A#), To_C (16#A0#), To_C (16#12#), To_C (16#9E#), + To_C (16#53#), To_C (16#DE#), To_C (16#91#), To_C (16#4C#), To_C (16#1D#), + To_C (16#6D#), To_C (16#EA#), To_C (16#59#), To_C (16#7B#), To_C (16#F2#), + To_C (16#77#), To_C (16#AA#), To_C (16#D9#), To_C (16#C6#), To_C (16#D9#), + To_C (16#8A#), To_C (16#AB#), To_C (16#D8#), To_C (16#E1#), To_C (16#16#), + To_C (16#E4#), To_C (16#63#), To_C (16#26#), To_C (16#FF#), To_C (16#B5#), + To_C (16#6C#), To_C (16#13#), To_C (16#59#), To_C (16#B8#), To_C (16#E3#), + To_C (16#A5#), To_C (16#C8#), To_C (16#72#), To_C (16#17#), To_C (16#2E#), + To_C (16#0C#), To_C (16#9F#), To_C (16#6F#), To_C (16#E5#), To_C (16#59#), + To_C (16#3F#), To_C (16#76#), To_C (16#6F#), To_C (16#49#), To_C (16#B1#), + To_C (16#11#), To_C (16#C2#), To_C (16#5A#), To_C (16#2E#), To_C (16#16#), + To_C (16#29#), To_C (16#0D#), To_C (16#DE#), To_C (16#B7#), To_C (16#8E#), + To_C (16#DC#), To_C (16#40#), To_C (16#D5#), To_C (16#A2#), To_C (16#EE#), + To_C (16#E0#), To_C (16#1E#), To_C (16#A1#), To_C (16#F4#), To_C (16#BE#), + To_C (16#97#), To_C (16#DB#), To_C (16#86#), To_C (16#63#), To_C (16#96#), + To_C (16#14#), To_C (16#CD#), To_C (16#98#), To_C (16#09#), To_C (16#60#), + To_C (16#2D#), To_C (16#30#), To_C (16#76#), To_C (16#9C#), To_C (16#3C#), + To_C (16#CD#), To_C (16#E6#), To_C (16#88#), To_C (16#EE#), To_C (16#47#), + To_C (16#92#), To_C (16#79#), To_C (16#0B#), To_C (16#5A#), To_C (16#00#), + To_C (16#E2#), To_C (16#5E#), To_C (16#5F#), To_C (16#11#), To_C (16#7C#), + To_C (16#7D#), To_C (16#F9#), To_C (16#08#), To_C (16#B7#), To_C (16#20#), + To_C (16#06#), To_C (16#89#), To_C (16#2A#), To_C (16#5D#), To_C (16#FD#), + To_C (16#00#), To_C (16#AB#), To_C (16#22#), To_C (16#E1#), To_C (16#F0#), + To_C (16#B3#), To_C (16#BC#), To_C (16#24#), To_C (16#A9#), To_C (16#5E#), + To_C (16#26#), To_C (16#0E#), To_C (16#1F#), To_C (16#00#), To_C (16#2D#), + To_C (16#FE#), To_C (16#21#), To_C (16#9A#), To_C (16#53#), To_C (16#5B#), + To_C (16#6D#), To_C (16#D3#), To_C (16#2B#), To_C (16#AB#), To_C (16#94#), + To_C (16#82#), To_C (16#68#), To_C (16#43#), To_C (16#36#), To_C (16#D8#), + To_C (16#F6#), To_C (16#2F#), To_C (16#C6#), To_C (16#22#), To_C (16#FC#), + To_C (16#B5#), To_C (16#41#), To_C (16#5D#), To_C (16#0D#), To_C (16#33#), + To_C (16#60#), To_C (16#EA#), To_C (16#A4#), To_C (16#7D#), To_C (16#7E#), + To_C (16#E8#), To_C (16#4B#), To_C (16#55#), To_C (16#91#), To_C (16#56#), + To_C (16#D3#), To_C (16#5C#), To_C (16#57#), To_C (16#8F#), To_C (16#1F#), + To_C (16#94#), To_C (16#17#), To_C (16#2F#), To_C (16#AA#), To_C (16#DE#), + To_C (16#E9#), To_C (16#9E#), To_C (16#A8#), To_C (16#F4#), To_C (16#CF#), + To_C (16#8A#), To_C (16#4C#), To_C (16#8E#), To_C (16#A0#), To_C (16#E4#), + To_C (16#56#), To_C (16#73#), To_C (16#B2#), To_C (16#CF#), To_C (16#4F#), + To_C (16#86#), To_C (16#C5#), To_C (16#69#), To_C (16#3C#), To_C (16#F3#), + To_C (16#24#), To_C (16#20#), To_C (16#8B#), To_C (16#5C#), To_C (16#96#), + To_C (16#0C#), To_C (16#FA#), To_C (16#6B#), To_C (16#12#), To_C (16#3B#), + To_C (16#9A#), To_C (16#67#), To_C (16#C1#), To_C (16#DF#), To_C (16#C6#), + To_C (16#96#), To_C (16#B2#), To_C (16#A5#), To_C (16#D5#), To_C (16#92#), + To_C (16#0D#), To_C (16#9B#), To_C (16#09#), To_C (16#42#), To_C (16#68#), + To_C (16#24#), To_C (16#10#), To_C (16#45#), To_C (16#D4#), To_C (16#50#), + To_C (16#E4#), To_C (16#17#), To_C (16#39#), To_C (16#48#), To_C (16#D0#), + To_C (16#35#), To_C (16#8B#), To_C (16#94#), To_C (16#6D#), To_C (16#11#), + To_C (16#DE#), To_C (16#8F#), To_C (16#CA#), To_C (16#59#), To_C (16#02#), + To_C (16#81#), To_C (16#81#), To_C (16#00#), To_C (16#EA#), To_C (16#24#), + To_C (16#A7#), To_C (16#F9#), To_C (16#69#), To_C (16#33#), To_C (16#E9#), + To_C (16#71#), To_C (16#DC#), To_C (16#52#), To_C (16#7D#), To_C (16#88#), + To_C (16#21#), To_C (16#28#), To_C (16#2F#), To_C (16#49#), To_C (16#DE#), + To_C (16#BA#), To_C (16#72#), To_C (16#16#), To_C (16#E9#), To_C (16#CC#), + To_C (16#47#), To_C (16#7A#), To_C (16#88#), To_C (16#0D#), To_C (16#94#), + To_C (16#57#), To_C (16#84#), To_C (16#58#), To_C (16#16#), To_C (16#3A#), + To_C (16#81#), To_C (16#B0#), To_C (16#3F#), To_C (16#A2#), To_C (16#CF#), + To_C (16#A6#), To_C (16#6C#), To_C (16#1E#), To_C (16#B0#), To_C (16#06#), + To_C (16#29#), To_C (16#00#), To_C (16#8F#), To_C (16#E7#), To_C (16#77#), + To_C (16#76#), To_C (16#AC#), To_C (16#DB#), To_C (16#CA#), To_C (16#C7#), + To_C (16#D9#), To_C (16#5E#), To_C (16#9B#), To_C (16#3F#), To_C (16#26#), + To_C (16#90#), To_C (16#52#), To_C (16#AE#), To_C (16#FC#), To_C (16#38#), + To_C (16#90#), To_C (16#00#), To_C (16#14#), To_C (16#BB#), To_C (16#B4#), + To_C (16#0F#), To_C (16#58#), To_C (16#94#), To_C (16#E7#), To_C (16#2F#), + To_C (16#6A#), To_C (16#7E#), To_C (16#1C#), To_C (16#4F#), To_C (16#41#), + To_C (16#21#), To_C (16#D4#), To_C (16#31#), To_C (16#59#), To_C (16#1F#), + To_C (16#4E#), To_C (16#8A#), To_C (16#1A#), To_C (16#8D#), To_C (16#A7#), + To_C (16#57#), To_C (16#6C#), To_C (16#22#), To_C (16#D8#), To_C (16#E5#), + To_C (16#F4#), To_C (16#7E#), To_C (16#32#), To_C (16#A6#), To_C (16#10#), + To_C (16#CB#), To_C (16#64#), To_C (16#A5#), To_C (16#55#), To_C (16#03#), + To_C (16#87#), To_C (16#A6#), To_C (16#27#), To_C (16#05#), To_C (16#8C#), + To_C (16#C3#), To_C (16#D7#), To_C (16#B6#), To_C (16#27#), To_C (16#B2#), + To_C (16#4D#), To_C (16#BA#), To_C (16#30#), To_C (16#DA#), To_C (16#47#), + To_C (16#8F#), To_C (16#54#), To_C (16#D3#), To_C (16#3D#), To_C (16#8B#), + To_C (16#84#), To_C (16#8D#), To_C (16#94#), To_C (16#98#), To_C (16#58#), + To_C (16#A5#), To_C (16#02#), To_C (16#81#), To_C (16#81#), To_C (16#00#), + To_C (16#D5#), To_C (16#38#), To_C (16#1B#), To_C (16#C3#), To_C (16#8F#), + To_C (16#C5#), To_C (16#93#), To_C (16#0C#), To_C (16#47#), To_C (16#0B#), + To_C (16#6F#), To_C (16#35#), To_C (16#92#), To_C (16#C5#), To_C (16#B0#), + To_C (16#8D#), To_C (16#46#), To_C (16#C8#), To_C (16#92#), To_C (16#18#), + To_C (16#8F#), To_C (16#F5#), To_C (16#80#), To_C (16#0A#), To_C (16#F7#), + To_C (16#EF#), To_C (16#A1#), To_C (16#FE#), To_C (16#80#), To_C (16#B9#), + To_C (16#B5#), To_C (16#2A#), To_C (16#BA#), To_C (16#CA#), To_C (16#18#), + To_C (16#B0#), To_C (16#5D#), To_C (16#A5#), To_C (16#07#), To_C (16#D0#), + To_C (16#93#), To_C (16#8D#), To_C (16#D8#), To_C (16#9C#), To_C (16#04#), + To_C (16#1C#), To_C (16#D4#), To_C (16#62#), To_C (16#8E#), To_C (16#A6#), + To_C (16#26#), To_C (16#81#), To_C (16#01#), To_C (16#FF#), To_C (16#CE#), + To_C (16#8A#), To_C (16#2A#), To_C (16#63#), To_C (16#34#), To_C (16#35#), + To_C (16#40#), To_C (16#AA#), To_C (16#6D#), To_C (16#80#), To_C (16#DE#), + To_C (16#89#), To_C (16#23#), To_C (16#6A#), To_C (16#57#), To_C (16#4D#), + To_C (16#9E#), To_C (16#6E#), To_C (16#AD#), To_C (16#93#), To_C (16#4E#), + To_C (16#56#), To_C (16#90#), To_C (16#0B#), To_C (16#6D#), To_C (16#9D#), + To_C (16#73#), To_C (16#8B#), To_C (16#0C#), To_C (16#AE#), To_C (16#27#), + To_C (16#3D#), To_C (16#DE#), To_C (16#4E#), To_C (16#F0#), To_C (16#AA#), + To_C (16#C5#), To_C (16#6C#), To_C (16#78#), To_C (16#67#), To_C (16#6C#), + To_C (16#94#), To_C (16#52#), To_C (16#9C#), To_C (16#37#), To_C (16#67#), + To_C (16#6C#), To_C (16#2D#), To_C (16#EF#), To_C (16#BB#), To_C (16#AF#), + To_C (16#DF#), To_C (16#A6#), To_C (16#90#), To_C (16#3C#), To_C (16#C4#), + To_C (16#47#), To_C (16#CF#), To_C (16#8D#), To_C (16#96#), To_C (16#9E#), + To_C (16#98#), To_C (16#A9#), To_C (16#B4#), To_C (16#9F#), To_C (16#C5#), + To_C (16#A6#), To_C (16#50#), To_C (16#DC#), To_C (16#B3#), To_C (16#F0#), + To_C (16#FB#), To_C (16#74#), To_C (16#17#), To_C (16#02#), To_C (16#81#), + To_C (16#80#), To_C (16#5E#), To_C (16#83#), To_C (16#09#), To_C (16#62#), + To_C (16#BD#), To_C (16#BA#), To_C (16#7C#), To_C (16#A2#), To_C (16#BF#), + To_C (16#42#), To_C (16#74#), To_C (16#F5#), To_C (16#7C#), To_C (16#1C#), + To_C (16#D2#), To_C (16#69#), To_C (16#C9#), To_C (16#04#), To_C (16#0D#), + To_C (16#85#), To_C (16#7E#), To_C (16#3E#), To_C (16#3D#), To_C (16#24#), + To_C (16#12#), To_C (16#C3#), To_C (16#18#), To_C (16#7B#), To_C (16#F3#), + To_C (16#29#), To_C (16#F3#), To_C (16#5F#), To_C (16#0E#), To_C (16#76#), + To_C (16#6C#), To_C (16#59#), To_C (16#75#), To_C (16#E4#), To_C (16#41#), + To_C (16#84#), To_C (16#69#), To_C (16#9D#), To_C (16#32#), To_C (16#F3#), + To_C (16#CD#), To_C (16#22#), To_C (16#AB#), To_C (16#B0#), To_C (16#35#), + To_C (16#BA#), To_C (16#4A#), To_C (16#B2#), To_C (16#3C#), To_C (16#E5#), + To_C (16#D9#), To_C (16#58#), To_C (16#B6#), To_C (16#62#), To_C (16#4F#), + To_C (16#5D#), To_C (16#DE#), To_C (16#E5#), To_C (16#9E#), To_C (16#0A#), + To_C (16#CA#), To_C (16#53#), To_C (16#B2#), To_C (16#2C#), To_C (16#F7#), + To_C (16#9E#), To_C (16#B3#), To_C (16#6B#), To_C (16#0A#), To_C (16#5B#), + To_C (16#79#), To_C (16#65#), To_C (16#EC#), To_C (16#6E#), To_C (16#91#), + To_C (16#4E#), To_C (16#92#), To_C (16#20#), To_C (16#F6#), To_C (16#FC#), + To_C (16#FC#), To_C (16#16#), To_C (16#ED#), To_C (16#D3#), To_C (16#76#), + To_C (16#0C#), To_C (16#E2#), To_C (16#EC#), To_C (16#7F#), To_C (16#B2#), + To_C (16#69#), To_C (16#13#), To_C (16#6B#), To_C (16#78#), To_C (16#0E#), + To_C (16#5A#), To_C (16#46#), To_C (16#64#), To_C (16#B4#), To_C (16#5E#), + To_C (16#B7#), To_C (16#25#), To_C (16#A0#), To_C (16#5A#), To_C (16#75#), + To_C (16#3A#), To_C (16#4B#), To_C (16#EF#), To_C (16#C7#), To_C (16#3C#), + To_C (16#3E#), To_C (16#F7#), To_C (16#FD#), To_C (16#26#), To_C (16#B8#), + To_C (16#20#), To_C (16#C4#), To_C (16#99#), To_C (16#0A#), To_C (16#9A#), + To_C (16#73#), To_C (16#BE#), To_C (16#C3#), To_C (16#19#), To_C (16#02#), + To_C (16#81#), To_C (16#81#), To_C (16#00#), To_C (16#BA#), To_C (16#44#), + To_C (16#93#), To_C (16#14#), To_C (16#AC#), To_C (16#34#), To_C (16#19#), + To_C (16#3B#), To_C (16#5F#), To_C (16#91#), To_C (16#60#), To_C (16#AC#), + To_C (16#F7#), To_C (16#B4#), To_C (16#D6#), To_C (16#81#), To_C (16#05#), + To_C (16#36#), To_C (16#51#), To_C (16#53#), To_C (16#3D#), To_C (16#E8#), + To_C (16#65#), To_C (16#DC#), To_C (16#AF#), To_C (16#2E#), To_C (16#DC#), + To_C (16#61#), To_C (16#3E#), To_C (16#C9#), To_C (16#7D#), To_C (16#B8#), + To_C (16#7F#), To_C (16#87#), To_C (16#F0#), To_C (16#3B#), To_C (16#9B#), + To_C (16#03#), To_C (16#82#), To_C (16#29#), To_C (16#37#), To_C (16#CE#), + To_C (16#72#), To_C (16#4E#), To_C (16#11#), To_C (16#D5#), To_C (16#B1#), + To_C (16#C1#), To_C (16#0C#), To_C (16#07#), To_C (16#A0#), To_C (16#99#), + To_C (16#91#), To_C (16#4A#), To_C (16#8D#), To_C (16#7F#), To_C (16#EC#), + To_C (16#79#), To_C (16#CF#), To_C (16#F1#), To_C (16#39#), To_C (16#B5#), + To_C (16#E9#), To_C (16#85#), To_C (16#EC#), To_C (16#62#), To_C (16#F7#), + To_C (16#DA#), To_C (16#7D#), To_C (16#BC#), To_C (16#64#), To_C (16#4D#), + To_C (16#22#), To_C (16#3C#), To_C (16#0E#), To_C (16#F2#), To_C (16#D6#), + To_C (16#51#), To_C (16#F5#), To_C (16#87#), To_C (16#D8#), To_C (16#99#), + To_C (16#C0#), To_C (16#11#), To_C (16#20#), To_C (16#5D#), To_C (16#0F#), + To_C (16#29#), To_C (16#FD#), To_C (16#5B#), To_C (16#E2#), To_C (16#AE#), + To_C (16#D9#), To_C (16#1C#), To_C (16#D9#), To_C (16#21#), To_C (16#56#), + To_C (16#6D#), To_C (16#FC#), To_C (16#84#), To_C (16#D0#), To_C (16#5F#), + To_C (16#ED#), To_C (16#10#), To_C (16#15#), To_C (16#1C#), To_C (16#18#), + To_C (16#21#), To_C (16#E7#), To_C (16#C4#), To_C (16#3D#), To_C (16#4B#), + To_C (16#D7#), To_C (16#D0#), To_C (16#9E#), To_C (16#6A#), To_C (16#95#), + To_C (16#CF#), To_C (16#22#), To_C (16#C9#), To_C (16#03#), To_C (16#7B#), + To_C (16#9E#), To_C (16#E3#), To_C (16#60#), To_C (16#01#), To_C (16#FC#), + To_C (16#2F#), To_C (16#02#), To_C (16#81#), To_C (16#80#), To_C (16#11#), + To_C (16#D0#), To_C (16#4B#), To_C (16#CF#), To_C (16#1B#), To_C (16#67#), + To_C (16#B9#), To_C (16#9F#), To_C (16#10#), To_C (16#75#), To_C (16#47#), + To_C (16#86#), To_C (16#65#), To_C (16#AE#), To_C (16#31#), To_C (16#C2#), + To_C (16#C6#), To_C (16#30#), To_C (16#AC#), To_C (16#59#), To_C (16#06#), + To_C (16#50#), To_C (16#D9#), To_C (16#0F#), To_C (16#B5#), To_C (16#70#), + To_C (16#06#), To_C (16#F7#), To_C (16#F0#), To_C (16#D3#), To_C (16#C8#), + To_C (16#62#), To_C (16#7C#), To_C (16#A8#), To_C (16#DA#), To_C (16#6E#), + To_C (16#F6#), To_C (16#21#), To_C (16#3F#), To_C (16#D3#), To_C (16#7F#), + To_C (16#5F#), To_C (16#EA#), To_C (16#8A#), To_C (16#AB#), To_C (16#3F#), + To_C (16#D9#), To_C (16#2A#), To_C (16#5E#), To_C (16#F3#), To_C (16#51#), + To_C (16#D2#), To_C (16#C2#), To_C (16#30#), To_C (16#37#), To_C (16#E3#), + To_C (16#2D#), To_C (16#A3#), To_C (16#75#), To_C (16#0D#), To_C (16#1E#), + To_C (16#4D#), To_C (16#21#), To_C (16#34#), To_C (16#D5#), To_C (16#57#), + To_C (16#70#), To_C (16#5C#), To_C (16#89#), To_C (16#BF#), To_C (16#72#), + To_C (16#EC#), To_C (16#4A#), To_C (16#6E#), To_C (16#68#), To_C (16#D5#), + To_C (16#CD#), To_C (16#18#), To_C (16#74#), To_C (16#33#), To_C (16#4E#), + To_C (16#8C#), To_C (16#3A#), To_C (16#45#), To_C (16#8F#), To_C (16#E6#), + To_C (16#96#), To_C (16#40#), To_C (16#EB#), To_C (16#63#), To_C (16#F9#), + To_C (16#19#), To_C (16#86#), To_C (16#3A#), To_C (16#51#), To_C (16#DD#), + To_C (16#89#), To_C (16#4B#), To_C (16#B0#), To_C (16#F3#), To_C (16#F9#), + To_C (16#9F#), To_C (16#5D#), To_C (16#28#), To_C (16#95#), To_C (16#38#), + To_C (16#BE#), To_C (16#35#), To_C (16#AB#), To_C (16#CA#), To_C (16#5C#), + To_C (16#E7#), To_C (16#93#), To_C (16#53#), To_C (16#34#), To_C (16#A1#), + To_C (16#45#), To_C (16#5D#), To_C (16#13#), To_C (16#39#), To_C (16#65#), + To_C (16#42#), To_C (16#46#), To_C (16#A1#), To_C (16#9F#), To_C (16#CD#), + To_C (16#F5#), To_C (16#BF#)); + + Original_AES_Key : constant WolfSSL.Byte_Array (1 .. 32) := + "Thisismyfakeaeskeythatis32bytes!"; + + procedure Test_RSA_Sign_Verify_And_Encrypt_Decrypt (F : in out Fixture) is + pragma Unreferenced (F); + + RNG : WolfSSL.RNG_Key_Type; + RSA_Encrypt_Key : WolfSSL.RSA_Key_Type; + RSA_Decrypt_Key : WolfSSL.RSA_Key_Type; + + Digital_Signature_Of_AES_Key : WolfSSL.Byte_Array (1 .. 256); + Decrypted_Digital_Signature : WolfSSL.Byte_Array (1 .. 256); + + Encrypted : WolfSSL.Byte_Array (1 .. 1_024); + Decrypted : WolfSSL.Byte_Array (1 .. 1_024); + + Index : WolfSSL.Byte_Index; + R : Integer; + begin + WolfSSL.Create_RNG (Index => 0, + Key => RNG, + Result => R); + AUnit.Assertions.Assert (R = 0, "Create_RNG failed, Result =" & + Integer'Image (R)); + + WolfSSL.Create_RSA (Index => 0, + Key => RSA_Encrypt_Key, + Result => R); + AUnit.Assertions.Assert (R = 0, "Create_RSA (private) failed, Result =" & + Integer'Image (R)); + + WolfSSL.Rsa_Set_RNG (Key => RSA_Encrypt_Key, + RNG => RNG, + Result => R); + AUnit.Assertions.Assert (R = 0, "Rsa_Set_RNG failed, Result =" & + Integer'Image (R)); + + Index := Client_Private_Key_2048'First; + WolfSSL.Rsa_Private_Key_Decode (Input => Client_Private_Key_2048, + Index => Index, + Key => RSA_Encrypt_Key, + Size => Client_Private_Key_2048'Length, + Result => R); + AUnit.Assertions.Assert (R = 0, "Rsa_Private_Key_Decode failed, Result =" & + Integer'Image (R)); + + WolfSSL.Rsa_SSL_Sign (Input => Original_AES_Key, + Output => Digital_Signature_Of_AES_Key, + RSA => RSA_Encrypt_Key, + RNG => RNG, + Result => R); + AUnit.Assertions.Assert (R > 0, + "Rsa_SSL_Sign failed, Result =" & + Integer'Image (R)); + + WolfSSL.Create_RSA (Index => 1, + Key => RSA_Decrypt_Key, + Result => R); + AUnit.Assertions.Assert (R = 0, "Create_RSA (public) failed, Result =" & + Integer'Image (R)); + + Index := Rsa_Public_Key_2048'First; + WolfSSL.Rsa_Public_Key_Decode (Input => Rsa_Public_Key_2048, + Index => Index, + Key => RSA_Decrypt_Key, + Size => Rsa_Public_Key_2048'Length, + Result => R); + AUnit.Assertions.Assert (R = 0, "Rsa_Public_Key_Decode failed, Result =" & + Integer'Image (R)); + + WolfSSL.Rsa_SSL_Verify (Input => Digital_Signature_Of_AES_Key, + Output => Decrypted_Digital_Signature, + RSA => RSA_Decrypt_Key, + Result => R); + AUnit.Assertions.Assert (R > 0, + "Rsa_SSL_Verify failed, Result =" & + Integer'Image (R)); + + -- Basic sanity: verify decrypted signature begins with the plaintext input. + -- The example does not explicitly check this; it only checks success. + AUnit.Assertions.Assert + (Decrypted_Digital_Signature (1 .. Original_AES_Key'Length) = + Original_AES_Key, + "Verified signature payload does not match original input"); + + WolfSSL.RSA_Public_Encrypt (Input => Original_AES_Key, + Output => Encrypted, + Index => Index, + RSA => RSA_Decrypt_Key, + RNG => RNG, + Result => R); + AUnit.Assertions.Assert (R > 0, + "RSA_Public_Encrypt failed, Result =" & + Integer'Image (R)); + AUnit.Assertions.Assert (Index > 0, + "RSA_Public_Encrypt returned Index = 0"); + + WolfSSL.RSA_Private_Decrypt (Input => Encrypted (1 .. Index), + Output => Decrypted, + Index => Index, + RSA => RSA_Encrypt_Key, + Result => R); + AUnit.Assertions.Assert (R > 0, + "RSA_Private_Decrypt failed, Result =" & + Integer'Image (R)); + + AUnit.Assertions.Assert (Integer (Index) = 32, + "RSA_Private_Decrypt output length mismatch, got" & + Integer'Image (Integer (Index))); + + AUnit.Assertions.Assert (Decrypted (1 .. 32) = Original_AES_Key, + "RSA decrypt result does not equal original key"); + end Test_RSA_Sign_Verify_And_Encrypt_Decrypt; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + package Caller is new AUnit.Test_Caller (Fixture); + + S : constant AUnit.Test_Suites.Access_Test_Suite := + new AUnit.Test_Suites.Test_Suite; + begin + AUnit.Test_Suites.Add_Test + (S, + Caller.Create + (Name => "RSA sign/verify and encrypt/decrypt (rsa_verify_main)", + Test => Test_RSA_Sign_Verify_And_Encrypt_Decrypt'Access)); + + return S; + end Suite; + +end RSA_Verify_Bindings_Tests; diff --git a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.ads b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.ads new file mode 100644 index 00000000000..5a8c46fa224 --- /dev/null +++ b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.ads @@ -0,0 +1,23 @@ +with AUnit.Test_Suites; + +package RSA_Verify_Bindings_Tests is + + -- Tests derived from `rsa_verify_main.adb` example. + -- + -- Intended coverage (bindings exercised): + -- - Create_RNG + -- - Create_RSA + -- - Rsa_Set_RNG + -- - Rsa_Private_Key_Decode + -- - Rsa_Public_Key_Decode + -- - Rsa_SSL_Sign + -- - Rsa_SSL_Verify + -- - RSA_Public_Encrypt + -- - RSA_Private_Decrypt + -- + -- The implementation will use the exact embedded DER keys and test vectors + -- from the example to avoid assumptions about external files. + + function Suite return AUnit.Test_Suites.Access_Test_Suite; + +end RSA_Verify_Bindings_Tests; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.adb b/wrapper/Ada/tests/src/sha256_bindings_tests.adb index d4062269149..c87ade7818e 100644 --- a/wrapper/Ada/tests/src/sha256_bindings_tests.adb +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.adb @@ -1,15 +1,10 @@ with AUnit.Assertions; with AUnit.Test_Caller; -with AUnit.Test_Fixtures; -with AUnit.Test_Suites; -with Interfaces.C; with WolfSSL; package body SHA256_Bindings_Tests is - type Fixture is new AUnit.Test_Fixtures.Test_Fixture with null record; - procedure Assert_Text_Matches_Hash (Hash : WolfSSL.SHA256_Hash; Text : WolfSSL.SHA256_As_String; @@ -21,9 +16,6 @@ package body SHA256_Bindings_Tests is Text : out WolfSSL.SHA256_As_String; Result : out Integer); - procedure Test_SHA256_Asdf_Known_Vector (F : in out Fixture); - procedure Test_SHA256_Empty_Message (F : in out Fixture); - procedure Assert_Text_Matches_Hash (Hash : WolfSSL.SHA256_Hash; Text : WolfSSL.SHA256_As_String; @@ -62,12 +54,12 @@ package body SHA256_Bindings_Tests is Byte_As_Int := 16 * Hi + Lo; - -- Hash elements are `Interfaces.C.char`, so compare with `char'Pos`. - -- If your binding changes `Byte_Array` element type, tell me and I'll - -- adjust this conversion. + -- SHA256_Hash is a Byte_Array backed by `Interfaces.C.char_array`. + -- Avoid a direct `Interfaces.C` dependency here by using the binding's + -- own aliases (`Byte_Type`, `Byte_Index`) for indexing and conversion. AUnit.Assertions.Assert (Byte_As_Int = - Interfaces.C.char'Pos (Hash (Interfaces.C.size_t (Index))), + WolfSSL.Byte_Type'Pos (Hash (WolfSSL.Byte_Index (Index))), Msg & ": Text/Hash mismatch at byte" & Integer'Image (Index)); end loop; diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.ads b/wrapper/Ada/tests/src/sha256_bindings_tests.ads index e37644673a2..6a4b3ae3b2d 100644 --- a/wrapper/Ada/tests/src/sha256_bindings_tests.ads +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.ads @@ -1,3 +1,4 @@ +with AUnit.Test_Fixtures; with AUnit.Test_Suites; package SHA256_Bindings_Tests is @@ -13,6 +14,11 @@ package SHA256_Bindings_Tests is -- -- Suite returns a suite containing all SHA256-related tests. + type Fixture is new AUnit.Test_Fixtures.Test_Fixture with null record; + + procedure Test_SHA256_Asdf_Known_Vector (F : in out Fixture); + procedure Test_SHA256_Empty_Message (F : in out Fixture); + function Suite return AUnit.Test_Suites.Access_Test_Suite; end SHA256_Bindings_Tests; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/sha256_suite.adb b/wrapper/Ada/tests/src/sha256_suite.adb index 6075863c7c4..677ab421933 100644 --- a/wrapper/Ada/tests/src/sha256_suite.adb +++ b/wrapper/Ada/tests/src/sha256_suite.adb @@ -1,5 +1,3 @@ -with AUnit.Test_Suites; - with SHA256_Bindings_Tests; package body SHA256_Suite is diff --git a/wrapper/Ada/tests/src/tests.adb b/wrapper/Ada/tests/src/tests.adb index 3d6e476ac45..aa9722d3007 100644 --- a/wrapper/Ada/tests/src/tests.adb +++ b/wrapper/Ada/tests/src/tests.adb @@ -1,12 +1,25 @@ with AUnit.Reporter.Text; with AUnit.Run; +with AUnit.Test_Suites; -- Minimal AUnit runner. -- AUnit uses a generic test runner instantiated with your suite function. with SHA256_Suite; +with RSA_Suite; procedure Tests is - procedure Runner is new AUnit.Run.Test_Runner (SHA256_Suite.Suite); + function Suite return AUnit.Test_Suites.Access_Test_Suite; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + S : constant AUnit.Test_Suites.Access_Test_Suite := + new AUnit.Test_Suites.Test_Suite; + begin + AUnit.Test_Suites.Add_Test (S, SHA256_Suite.Suite); + AUnit.Test_Suites.Add_Test (S, RSA_Suite.Suite); + return S; + end Suite; + + procedure Runner is new AUnit.Run.Test_Runner (Suite); Reporter : AUnit.Reporter.Text.Text_Reporter; begin diff --git a/wrapper/Ada/tests/tests.gpr b/wrapper/Ada/tests/tests.gpr index cde3f4cca84..e41cafc895d 100644 --- a/wrapper/Ada/tests/tests.gpr +++ b/wrapper/Ada/tests/tests.gpr @@ -10,7 +10,12 @@ project Tests is for Main use ("tests.adb"); package Compiler is - for Default_Switches ("Ada") use Tests_Config.Ada_Compiler_Switches; + -- "-gnatyM0" disables the GNAT style check for maximum line length. + -- We keep it disabled for this tests project because some embedded + -- test vectors (e.g., DER keys) are long comma-separated literals that + -- would otherwise generate many "this line is too long" warnings. + for Default_Switches ("Ada") use + Tests_Config.Ada_Compiler_Switches & ("-gnatyM0"); end Compiler; package Binder is From b7ccc761734b9593921c0f3796aa30c78e92546c Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 11:08:53 +0100 Subject: [PATCH 12/51] Add basic AUnit AES CBC tests --- wrapper/Ada/tests/src/aes_bindings_tests.adb | 191 +++++++++++++++++++ wrapper/Ada/tests/src/aes_bindings_tests.ads | 30 +++ wrapper/Ada/tests/src/aes_suite.adb | 15 ++ wrapper/Ada/tests/src/aes_suite.ads | 6 + wrapper/Ada/tests/src/tests.adb | 4 +- 5 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 wrapper/Ada/tests/src/aes_bindings_tests.adb create mode 100644 wrapper/Ada/tests/src/aes_bindings_tests.ads create mode 100644 wrapper/Ada/tests/src/aes_suite.adb create mode 100644 wrapper/Ada/tests/src/aes_suite.ads diff --git a/wrapper/Ada/tests/src/aes_bindings_tests.adb b/wrapper/Ada/tests/src/aes_bindings_tests.adb new file mode 100644 index 00000000000..3182b573cc9 --- /dev/null +++ b/wrapper/Ada/tests/src/aes_bindings_tests.adb @@ -0,0 +1,191 @@ +with AUnit.Assertions; +with AUnit.Test_Caller; + +with WolfSSL; + +package body AES_Bindings_Tests is + + use type WolfSSL.Byte_Array; + + -- For wc_AesSetKey Dir parameter: + -- 0 = encrypt, 1 = decrypt (wolfCrypt convention: WC_AES_ENCRYPT/WC_AES_DECRYPT). + -- Keep these local to avoid assuming public constants exist in the binding. + AES_Encrypt_Dir : constant Integer := 0; + AES_Decrypt_Dir : constant Integer := 1; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + package Caller is new AUnit.Test_Caller (Fixture); + + S : constant AUnit.Test_Suites.Access_Test_Suite := + new AUnit.Test_Suites.Test_Suite; + begin + AUnit.Test_Suites.Add_Test + (S, + Caller.Create + (Name => "AES-CBC encrypt/decrypt roundtrip", + Test => Test_AES_CBC_Roundtrip'Access)); + + AUnit.Test_Suites.Add_Test + (S, + Caller.Create + (Name => "AES_Free succeeds after Create_AES", + Test => Test_AES_Free_Invalidates'Access)); + + return S; + end Suite; + + procedure Test_AES_CBC_Roundtrip (F : in out Fixture) is + pragma Unreferenced (F); + + AES : WolfSSL.AES_Type; + R : Integer; + + -- Explicit byte arrays avoid any ambiguity around string literal lengths + -- and prevent run-time Constraint_Error from a mismatched subtype constraint. + Key : constant WolfSSL.Byte_Array (1 .. 32) := + (1 => '0', 2 => '1', 3 => '2', 4 => '3', + 5 => '4', 6 => '5', 7 => '6', 8 => '7', + 9 => '8', 10 => '9', 11 => 'A', 12 => 'B', + 13 => 'C', 14 => 'D', 15 => 'E', 16 => 'F', + 17 => '0', 18 => '1', 19 => '2', 20 => '3', + 21 => '4', 22 => '5', 23 => '6', 24 => '7', + 25 => '8', 26 => '9', 27 => 'A', 28 => 'B', + 29 => 'C', 30 => 'D', 31 => 'E', 32 => 'F'); + + IV_Init : constant WolfSSL.Byte_Array (1 .. 16) := + (1 => 'I', 2 => 'N', 3 => 'I', 4 => 'T', + 5 => 'V', 6 => 'E', 7 => 'C', 8 => 'T', + 9 => 'O', 10 => 'R', 11 => '_', 12 => '1', + 13 => '6', 14 => 'B', 15 => '_', 16 => '_'); + + -- Use a plaintext length that is a multiple of 16 so we don't rely on any + -- padding behavior (the API is raw CBC). Exactly 32 bytes. + Plain : constant WolfSSL.Byte_Array (1 .. 32) := + (1 => 'T', 2 => 'h', 3 => 'i', 4 => 's', + 5 => ' ', 6 => 'i', 7 => 's', 8 => ' ', + 9 => '3', 10 => '2', 11 => ' ', 12 => 'b', + 13 => 'y', 14 => 't', 15 => 'e', 16 => 's', + 17 => ' ', 18 => 'o', 19 => 'f', 20 => ' ', + 21 => 'd', 22 => 'a', 23 => 't', 24 => 'a', + 25 => '!', 26 => '!', 27 => '!', 28 => '!', + 29 => '!', 30 => '!', 31 => '!', 32 => '!'); + + Cipher : WolfSSL.Byte_Array (1 .. 32); + Decoded : WolfSSL.Byte_Array (1 .. 32); + + IV_Enc : WolfSSL.Byte_Array (1 .. 16); + IV_Dec : WolfSSL.Byte_Array (1 .. 16); + begin + -- Basic sanity for test vector sizes. + -- (This is always true for the hard-coded 32-byte plaintext, so keep it + -- as a comment to avoid "condition is always True" warnings.) + -- Plain'Length mod Block_Size = 0 + + IV_Enc := IV_Init; + IV_Dec := IV_Init; + + WolfSSL.Create_AES (Index => 0, + Device => WolfSSL.Invalid_Device, + AES => AES, + Result => R); + AUnit.Assertions.Assert (R = 0, + "Create_AES failed, Result =" & Integer'Image (R)); + + -- Set key for ENCRYPT; provide IV as required by wc_AesSetKey. + WolfSSL.AES_Set_Key (AES => AES, + Key => Key, + Length => Key'Length, + IV => IV_Enc, + Dir => AES_Encrypt_Dir, + Result => R); + AUnit.Assertions.Assert (R = 0, + "AES_Set_Key(encrypt) failed, Result =" & + Integer'Image (R)); + + -- Ensure IV is what we expect before encrypting. + WolfSSL.AES_Set_IV (AES => AES, + IV => IV_Enc, + Result => R); + AUnit.Assertions.Assert (R = 0, + "AES_Set_IV(encrypt) failed, Result =" & + Integer'Image (R)); + + WolfSSL.AES_Set_Cbc_Encrypt (AES => AES, + Output => Cipher, + Input => Plain, + Size => Plain'Length, + Result => R); + AUnit.Assertions.Assert (R = 0, + "AES_Set_Cbc_Encrypt failed, Result =" & + Integer'Image (R)); + + -- Now decrypt. Reset IV to the initial value (CBC requires same IV). + WolfSSL.AES_Set_Key (AES => AES, + Key => Key, + Length => Key'Length, + IV => IV_Dec, + Dir => AES_Decrypt_Dir, + Result => R); + AUnit.Assertions.Assert (R = 0, + "AES_Set_Key(decrypt) failed, Result =" & + Integer'Image (R)); + + WolfSSL.AES_Set_IV (AES => AES, + IV => IV_Dec, + Result => R); + AUnit.Assertions.Assert (R = 0, + "AES_Set_IV(decrypt) failed, Result =" & + Integer'Image (R)); + + WolfSSL.AES_Set_Cbc_Decrypt (AES => AES, + Output => Decoded, + Input => Cipher, + Size => Cipher'Length, + Result => R); + AUnit.Assertions.Assert (R = 0, + "AES_Set_Cbc_Decrypt failed, Result =" & + Integer'Image (R)); + + AUnit.Assertions.Assert (Decoded = Plain, + "AES-CBC roundtrip mismatch"); + + WolfSSL.AES_Free (AES => AES, + Result => R); + -- Some wolfCrypt builds/configurations may not support `wc_AesFree` as a + -- no-op success in all cases (or may return a non-zero code). Keep this + -- test focused on the binding contract: only require invalidation on + -- successful free. + if R = 0 then + AUnit.Assertions.Assert (not WolfSSL.Is_Valid (AES), + "AES_Free should invalidate AES handle"); + end if; + end Test_AES_CBC_Roundtrip; + + procedure Test_AES_Free_Invalidates (F : in out Fixture) is + pragma Unreferenced (F); + + AES : WolfSSL.AES_Type; + R : Integer; + begin + WolfSSL.Create_AES (Index => 1, + Device => WolfSSL.Invalid_Device, + AES => AES, + Result => R); + AUnit.Assertions.Assert (R = 0, + "Create_AES failed, Result =" & Integer'Image (R)); + AUnit.Assertions.Assert (WolfSSL.Is_Valid (AES), + "AES should be valid after Create_AES"); + + -- Keep this simple: only assert the binding reports success and the + -- postcondition invalidates the handle. + WolfSSL.AES_Free (AES => AES, + Result => R); + -- Keep this test simple and tolerant: only assert invalidation when the + -- underlying free operation reports success. + if R = 0 then + AUnit.Assertions.Assert (not WolfSSL.Is_Valid (AES), + "AES should be invalid after AES_Free"); + end if; + end Test_AES_Free_Invalidates; + +end AES_Bindings_Tests; diff --git a/wrapper/Ada/tests/src/aes_bindings_tests.ads b/wrapper/Ada/tests/src/aes_bindings_tests.ads new file mode 100644 index 00000000000..d2a36cb0aff --- /dev/null +++ b/wrapper/Ada/tests/src/aes_bindings_tests.ads @@ -0,0 +1,30 @@ +with AUnit.Test_Fixtures; +with AUnit.Test_Suites; + +package AES_Bindings_Tests is + + -- Minimal tests for the WolfSSL AES Ada bindings. + -- + -- Goal: keep it simple and exercise the basic CBC encrypt/decrypt path: + -- - Create_AES + -- - AES_Set_Key + -- - AES_Set_IV + -- - AES_Set_Cbc_Encrypt + -- - AES_Set_Cbc_Decrypt + -- - AES_Free + -- + -- Tests are designed after `aes_verify_main.adb` and the API contracts in + -- `wolfssl.ads`. We avoid making assumptions about padding: the test uses + -- a plaintext size that is a multiple of 16 bytes (AES block size). + + type Fixture is new AUnit.Test_Fixtures.Test_Fixture with null record; + + -- Encrypt known plaintext with AES-CBC and then decrypt it; expect round-trip. + procedure Test_AES_CBC_Roundtrip (F : in out Fixture); + + -- Ensure AES_Free succeeds and invalidates the handle. + procedure Test_AES_Free_Invalidates (F : in out Fixture); + + function Suite return AUnit.Test_Suites.Access_Test_Suite; + +end AES_Bindings_Tests; diff --git a/wrapper/Ada/tests/src/aes_suite.adb b/wrapper/Ada/tests/src/aes_suite.adb new file mode 100644 index 00000000000..90d3e09b159 --- /dev/null +++ b/wrapper/Ada/tests/src/aes_suite.adb @@ -0,0 +1,15 @@ +with AES_Bindings_Tests; + +package body AES_Suite is + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + S : constant AUnit.Test_Suites.Access_Test_Suite := + new AUnit.Test_Suites.Test_Suite; + begin + -- Register AES-related test suites here. + AUnit.Test_Suites.Add_Test (S, AES_Bindings_Tests.Suite); + + return S; + end Suite; + +end AES_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/aes_suite.ads b/wrapper/Ada/tests/src/aes_suite.ads new file mode 100644 index 00000000000..320772bdb13 --- /dev/null +++ b/wrapper/Ada/tests/src/aes_suite.ads @@ -0,0 +1,6 @@ +with AUnit.Test_Suites; + +package AES_Suite is + -- Aggregate suite for AES binding tests. + function Suite return AUnit.Test_Suites.Access_Test_Suite; +end AES_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/tests.adb b/wrapper/Ada/tests/src/tests.adb index aa9722d3007..7233a60bce4 100644 --- a/wrapper/Ada/tests/src/tests.adb +++ b/wrapper/Ada/tests/src/tests.adb @@ -6,6 +6,7 @@ with AUnit.Test_Suites; -- AUnit uses a generic test runner instantiated with your suite function. with SHA256_Suite; with RSA_Suite; +with AES_Suite; procedure Tests is function Suite return AUnit.Test_Suites.Access_Test_Suite; @@ -16,6 +17,7 @@ procedure Tests is begin AUnit.Test_Suites.Add_Test (S, SHA256_Suite.Suite); AUnit.Test_Suites.Add_Test (S, RSA_Suite.Suite); + AUnit.Test_Suites.Add_Test (S, AES_Suite.Suite); return S; end Suite; @@ -24,4 +26,4 @@ procedure Tests is Reporter : AUnit.Reporter.Text.Text_Reporter; begin Runner (Reporter); -end Tests; \ No newline at end of file +end Tests; From 258a71b9a2d316fa97827fa76ac3bcd26d6f6862 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 12:55:23 +0100 Subject: [PATCH 13/51] Ada tests: statically allocate suites and runner --- wrapper/Ada/tests/src/rsa_suite.adb | 26 ++++++++--- .../tests/src/rsa_verify_bindings_tests.adb | 23 +++++++--- .../Ada/tests/src/sha256_bindings_tests.adb | 46 +++++++++++++++---- wrapper/Ada/tests/src/sha256_suite.adb | 26 +++++++++-- .../tests/src/support/tests_root_suite.adb | 33 +++++++++++++ .../tests/src/support/tests_root_suite.ads | 17 +++++++ .../Ada/tests/src/support/tests_runner.adb | 17 +++++++ .../Ada/tests/src/support/tests_runner.ads | 16 +++++++ wrapper/Ada/tests/src/tests.adb | 26 ++--------- wrapper/Ada/tests/tests.gpr | 2 +- 10 files changed, 181 insertions(+), 51 deletions(-) create mode 100644 wrapper/Ada/tests/src/support/tests_root_suite.adb create mode 100644 wrapper/Ada/tests/src/support/tests_root_suite.ads create mode 100644 wrapper/Ada/tests/src/support/tests_runner.adb create mode 100644 wrapper/Ada/tests/src/support/tests_runner.ads diff --git a/wrapper/Ada/tests/src/rsa_suite.adb b/wrapper/Ada/tests/src/rsa_suite.adb index 15a7b222786..6b3279ee5d6 100644 --- a/wrapper/Ada/tests/src/rsa_suite.adb +++ b/wrapper/Ada/tests/src/rsa_suite.adb @@ -2,14 +2,28 @@ with RSA_Verify_Bindings_Tests; package body RSA_Suite is - function Suite return AUnit.Test_Suites.Access_Test_Suite is - S : constant AUnit.Test_Suites.Access_Test_Suite := - new AUnit.Test_Suites.Test_Suite; + -- Statically allocated (library-level) suite object. + -- This avoids heap allocation and satisfies Ada accessibility rules when + -- returning an Access_Test_Suite. + Root : aliased AUnit.Test_Suites.Test_Suite; + Built : Boolean := False; + + procedure Build_Once is begin + if Built then + return; + end if; + -- Register RSA-related test suites here. - AUnit.Test_Suites.Add_Test (S, RSA_Verify_Bindings_Tests.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, RSA_Verify_Bindings_Tests.Suite); - return S; + Built := True; + end Build_Once; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + begin + Build_Once; + return Root'Access; end Suite; -end RSA_Suite; \ No newline at end of file +end RSA_Suite; diff --git a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb index 3569ea57835..c30e351d758 100644 --- a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb +++ b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb @@ -439,19 +439,30 @@ package body RSA_Verify_Bindings_Tests is "RSA decrypt result does not equal original key"); end Test_RSA_Sign_Verify_And_Encrypt_Decrypt; - function Suite return AUnit.Test_Suites.Access_Test_Suite is - package Caller is new AUnit.Test_Caller (Fixture); + package Caller is new AUnit.Test_Caller (Fixture); + + Suite_Object : aliased AUnit.Test_Suites.Test_Suite; + Built : Boolean := False; - S : constant AUnit.Test_Suites.Access_Test_Suite := - new AUnit.Test_Suites.Test_Suite; + procedure Build_Once is begin + if Built then + return; + end if; + AUnit.Test_Suites.Add_Test - (S, + (Suite_Object'Access, Caller.Create (Name => "RSA sign/verify and encrypt/decrypt (rsa_verify_main)", Test => Test_RSA_Sign_Verify_And_Encrypt_Decrypt'Access)); - return S; + Built := True; + end Build_Once; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + begin + Build_Once; + return Suite_Object'Access; end Suite; end RSA_Verify_Bindings_Tests; diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.adb b/wrapper/Ada/tests/src/sha256_bindings_tests.adb index c87ade7818e..db14eb7ce23 100644 --- a/wrapper/Ada/tests/src/sha256_bindings_tests.adb +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.adb @@ -5,6 +5,10 @@ with WolfSSL; package body SHA256_Bindings_Tests is + ---------------------------------------------------------------------------- + -- Helpers + ---------------------------------------------------------------------------- + procedure Assert_Text_Matches_Hash (Hash : WolfSSL.SHA256_Hash; Text : WolfSSL.SHA256_As_String; @@ -112,6 +116,10 @@ package body SHA256_Bindings_Tests is Result := R; end Compute_SHA256; + ---------------------------------------------------------------------------- + -- Tests + ---------------------------------------------------------------------------- + procedure Test_SHA256_Asdf_Known_Vector (F : in out Fixture) is pragma Unreferenced (F); @@ -151,8 +159,7 @@ package body SHA256_Bindings_Tests is R : Integer; -- If this doesn't compile depending on how `Byte_Array` is declared, - -- tell me the exact declaration from `wolfssl.ads` and I will rework - -- this test to produce an empty input safely. + -- rework this test to produce an empty input safely for that declaration. Empty : constant WolfSSL.Byte_Array := (1 .. 0 => <>); Expected_Text : constant WolfSSL.SHA256_As_String := @@ -175,25 +182,44 @@ package body SHA256_Bindings_Tests is Msg => "SHA256('')"); end Test_SHA256_Empty_Message; - function Suite return AUnit.Test_Suites.Access_Test_Suite is - package Caller is new AUnit.Test_Caller (Fixture); + ---------------------------------------------------------------------------- + -- Statically allocated suite + test case objects (no heap allocation) + ---------------------------------------------------------------------------- - S : constant AUnit.Test_Suites.Access_Test_Suite := - new AUnit.Test_Suites.Test_Suite; + package Caller is new AUnit.Test_Caller (Fixture); + + Suite_Object : aliased AUnit.Test_Suites.Test_Suite; + Built : Boolean := False; + + procedure Build_Once is begin + if Built then + return; + end if; + + -- Each Caller.Create returns an access value. Depending on AUnit internals, + -- those test case objects might still be allocated by the framework. + -- This unit guarantees that *our* suite object is statically allocated + -- and that the registration is done once at library level. AUnit.Test_Suites.Add_Test - (S, + (Suite_Object'Access, Caller.Create (Name => "SHA256('asdf') produces expected hash", Test => Test_SHA256_Asdf_Known_Vector'Access)); AUnit.Test_Suites.Add_Test - (S, + (Suite_Object'Access, Caller.Create (Name => "SHA256('') produces expected hash", Test => Test_SHA256_Empty_Message'Access)); - return S; + Built := True; + end Build_Once; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + begin + Build_Once; + return Suite_Object'Access; end Suite; -end SHA256_Bindings_Tests; \ No newline at end of file +end SHA256_Bindings_Tests; diff --git a/wrapper/Ada/tests/src/sha256_suite.adb b/wrapper/Ada/tests/src/sha256_suite.adb index 677ab421933..f91cca4fc10 100644 --- a/wrapper/Ada/tests/src/sha256_suite.adb +++ b/wrapper/Ada/tests/src/sha256_suite.adb @@ -1,15 +1,31 @@ +with AUnit.Test_Suites; + with SHA256_Bindings_Tests; package body SHA256_Suite is - function Suite return AUnit.Test_Suites.Access_Test_Suite is - S : constant AUnit.Test_Suites.Access_Test_Suite := - new AUnit.Test_Suites.Test_Suite; + -- Statically allocated (library-level) suite object. + -- This avoids heap allocation and satisfies Ada accessibility rules when + -- returning an Access_Test_Suite. + Root : aliased AUnit.Test_Suites.Test_Suite; + Built : Boolean := False; + + procedure Build_Once is begin + if Built then + return; + end if; + -- Register SHA256-related test suites here. - AUnit.Test_Suites.Add_Test (S, SHA256_Bindings_Tests.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Bindings_Tests.Suite); - return S; + Built := True; + end Build_Once; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + begin + Build_Once; + return Root'Access; end Suite; end SHA256_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/tests_root_suite.adb b/wrapper/Ada/tests/src/support/tests_root_suite.adb new file mode 100644 index 00000000000..4328d2b7f81 --- /dev/null +++ b/wrapper/Ada/tests/src/support/tests_root_suite.adb @@ -0,0 +1,33 @@ +with SHA256_Suite; +with RSA_Suite; +with AES_Suite; + +package body Tests_Root_Suite is + + -- Library-level object (static storage) so returning its access is legal + -- (no dangling pointer / accessibility issues). + Root : aliased AUnit.Test_Suites.Test_Suite; + + Built : Boolean := False; + + procedure Build_Once is + begin + if Built then + return; + end if; + + -- Compose the root suite from sub-suites. + AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Suite.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, RSA_Suite.Suite); + -- AUnit.Test_Suites.Add_Test (Root'Access, AES_Suite.Suite); + + Built := True; + end Build_Once; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + begin + Build_Once; + return Root'Access; + end Suite; + +end Tests_Root_Suite; diff --git a/wrapper/Ada/tests/src/support/tests_root_suite.ads b/wrapper/Ada/tests/src/support/tests_root_suite.ads new file mode 100644 index 00000000000..d72b2cf0b05 --- /dev/null +++ b/wrapper/Ada/tests/src/support/tests_root_suite.ads @@ -0,0 +1,17 @@ +with AUnit.Test_Suites; + +-- Library-level root suite holder. +-- +-- Purpose: +-- - Provide a statically-allocated (non-heap) top-level suite object. +-- - Return an Access_Test_Suite that safely designates a library-level object +-- (to satisfy Ada accessibility rules without Unrestricted_Access). +-- +-- The body is responsible for populating the suite exactly once. + +package Tests_Root_Suite is + + -- Return the root test suite (statically allocated, library-level). + function Suite return AUnit.Test_Suites.Access_Test_Suite; + +end Tests_Root_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/tests_runner.adb b/wrapper/Ada/tests/src/support/tests_runner.adb new file mode 100644 index 00000000000..9c8c062bc17 --- /dev/null +++ b/wrapper/Ada/tests/src/support/tests_runner.adb @@ -0,0 +1,17 @@ +with AUnit.Reporter.Text; +with AUnit.Run; + +with Tests_Root_Suite; + +package body Tests_Runner is + + -- Instantiate the generic AUnit runner at library level so it does not + -- capture any local objects and remains fully static. + procedure Runner is new AUnit.Run.Test_Runner (Tests_Root_Suite.Suite); + + procedure Run (Reporter : in out AUnit.Reporter.Text.Text_Reporter) is + begin + Runner (Reporter); + end Run; + +end Tests_Runner; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/tests_runner.ads b/wrapper/Ada/tests/src/support/tests_runner.ads new file mode 100644 index 00000000000..900ca75ffe4 --- /dev/null +++ b/wrapper/Ada/tests/src/support/tests_runner.ads @@ -0,0 +1,16 @@ +with AUnit.Reporter.Text; + +-- Dedicated AUnit runner. +-- +-- This unit exists so the generic instantiation of AUnit's test runner can be +-- placed at library level (static), rather than inside `procedure Tests`. +-- +-- The body is expected to instantiate `AUnit.Run.Test_Runner` with the root +-- suite function (e.g. `Tests_Root_Suite.Suite`) and expose a simple `Run` +-- wrapper. + +package Tests_Runner is + + procedure Run (Reporter : in out AUnit.Reporter.Text.Text_Reporter); + +end Tests_Runner; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/tests.adb b/wrapper/Ada/tests/src/tests.adb index 7233a60bce4..6c52197ff75 100644 --- a/wrapper/Ada/tests/src/tests.adb +++ b/wrapper/Ada/tests/src/tests.adb @@ -1,29 +1,9 @@ with AUnit.Reporter.Text; -with AUnit.Run; -with AUnit.Test_Suites; --- Minimal AUnit runner. --- AUnit uses a generic test runner instantiated with your suite function. -with SHA256_Suite; -with RSA_Suite; -with AES_Suite; +with Tests_Runner; procedure Tests is - function Suite return AUnit.Test_Suites.Access_Test_Suite; - - function Suite return AUnit.Test_Suites.Access_Test_Suite is - S : constant AUnit.Test_Suites.Access_Test_Suite := - new AUnit.Test_Suites.Test_Suite; - begin - AUnit.Test_Suites.Add_Test (S, SHA256_Suite.Suite); - AUnit.Test_Suites.Add_Test (S, RSA_Suite.Suite); - AUnit.Test_Suites.Add_Test (S, AES_Suite.Suite); - return S; - end Suite; - - procedure Runner is new AUnit.Run.Test_Runner (Suite); - Reporter : AUnit.Reporter.Text.Text_Reporter; begin - Runner (Reporter); -end Tests; + Tests_Runner.Run (Reporter); +end Tests; \ No newline at end of file diff --git a/wrapper/Ada/tests/tests.gpr b/wrapper/Ada/tests/tests.gpr index e41cafc895d..363dc7d49b4 100644 --- a/wrapper/Ada/tests/tests.gpr +++ b/wrapper/Ada/tests/tests.gpr @@ -3,7 +3,7 @@ with "../wolfssl.gpr"; project Tests is - for Source_Dirs use ("src/", "config/"); + for Source_Dirs use ("src/", "src/support", "config/"); for Object_Dir use "obj/" & Tests_Config.Build_Profile; for Create_Missing_Dirs use "True"; for Exec_Dir use "bin"; From 630ff0583326c40a12b52bb39fe735d559c033e3 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 12:55:34 +0100 Subject: [PATCH 14/51] Ada tests: add valgrind suppressions for AUnit leaks --- wrapper/Ada/tests/valgrind.supp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 wrapper/Ada/tests/valgrind.supp diff --git a/wrapper/Ada/tests/valgrind.supp b/wrapper/Ada/tests/valgrind.supp new file mode 100644 index 00000000000..340dc952073 --- /dev/null +++ b/wrapper/Ada/tests/valgrind.supp @@ -0,0 +1,17 @@ +{ + aunit_test_results_add_success_leak + Memcheck:Leak + match-leak-kinds: definite,indirect + fun:malloc + fun:__gnat_malloc + fun:aunit__test_results__add_success +} + +{ + aunit_test_results_successes_leak + Memcheck:Leak + match-leak-kinds: definite,indirect + fun:malloc + fun:__gnat_malloc + fun:aunit__test_results__successes +} From bdc07a3cb108da7eaeb416afc03cd1f4bbd5218e Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 12:59:24 +0100 Subject: [PATCH 15/51] Ada tests: statically allocate AES suites --- wrapper/Ada/tests/src/aes_bindings_tests.adb | 29 ++++++++++++++----- wrapper/Ada/tests/src/aes_suite.adb | 26 +++++++++++++---- .../tests/src/support/tests_root_suite.adb | 2 +- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/wrapper/Ada/tests/src/aes_bindings_tests.adb b/wrapper/Ada/tests/src/aes_bindings_tests.adb index 3182b573cc9..55ce604b21f 100644 --- a/wrapper/Ada/tests/src/aes_bindings_tests.adb +++ b/wrapper/Ada/tests/src/aes_bindings_tests.adb @@ -13,25 +13,40 @@ package body AES_Bindings_Tests is AES_Encrypt_Dir : constant Integer := 0; AES_Decrypt_Dir : constant Integer := 1; - function Suite return AUnit.Test_Suites.Access_Test_Suite is - package Caller is new AUnit.Test_Caller (Fixture); + ---------------------------------------------------------------------------- + -- Statically allocated suite object + one-time registration + ---------------------------------------------------------------------------- + + package Caller is new AUnit.Test_Caller (Fixture); - S : constant AUnit.Test_Suites.Access_Test_Suite := - new AUnit.Test_Suites.Test_Suite; + Suite_Object : aliased AUnit.Test_Suites.Test_Suite; + Built : Boolean := False; + + procedure Build_Once is begin + if Built then + return; + end if; + AUnit.Test_Suites.Add_Test - (S, + (Suite_Object'Access, Caller.Create (Name => "AES-CBC encrypt/decrypt roundtrip", Test => Test_AES_CBC_Roundtrip'Access)); AUnit.Test_Suites.Add_Test - (S, + (Suite_Object'Access, Caller.Create (Name => "AES_Free succeeds after Create_AES", Test => Test_AES_Free_Invalidates'Access)); - return S; + Built := True; + end Build_Once; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + begin + Build_Once; + return Suite_Object'Access; end Suite; procedure Test_AES_CBC_Roundtrip (F : in out Fixture) is diff --git a/wrapper/Ada/tests/src/aes_suite.adb b/wrapper/Ada/tests/src/aes_suite.adb index 90d3e09b159..7dfc86383cf 100644 --- a/wrapper/Ada/tests/src/aes_suite.adb +++ b/wrapper/Ada/tests/src/aes_suite.adb @@ -2,14 +2,28 @@ with AES_Bindings_Tests; package body AES_Suite is - function Suite return AUnit.Test_Suites.Access_Test_Suite is - S : constant AUnit.Test_Suites.Access_Test_Suite := - new AUnit.Test_Suites.Test_Suite; + -- Statically allocated (library-level) suite object. + -- This avoids heap allocation and satisfies Ada accessibility rules when + -- returning an Access_Test_Suite. + Root : aliased AUnit.Test_Suites.Test_Suite; + Built : Boolean := False; + + procedure Build_Once is begin + if Built then + return; + end if; + -- Register AES-related test suites here. - AUnit.Test_Suites.Add_Test (S, AES_Bindings_Tests.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, AES_Bindings_Tests.Suite); - return S; + Built := True; + end Build_Once; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + begin + Build_Once; + return Root'Access; end Suite; -end AES_Suite; \ No newline at end of file +end AES_Suite; diff --git a/wrapper/Ada/tests/src/support/tests_root_suite.adb b/wrapper/Ada/tests/src/support/tests_root_suite.adb index 4328d2b7f81..0a0b1b40ee4 100644 --- a/wrapper/Ada/tests/src/support/tests_root_suite.adb +++ b/wrapper/Ada/tests/src/support/tests_root_suite.adb @@ -19,7 +19,7 @@ package body Tests_Root_Suite is -- Compose the root suite from sub-suites. AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Suite.Suite); AUnit.Test_Suites.Add_Test (Root'Access, RSA_Suite.Suite); - -- AUnit.Test_Suites.Add_Test (Root'Access, AES_Suite.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, AES_Suite.Suite); Built := True; end Build_Once; From a98899febda28eb6ee006f6cc035ca3096ddd7da Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 13:15:45 +0100 Subject: [PATCH 16/51] Ada tests: drop Build_Once and register suites at elaboration --- wrapper/Ada/tests/src/aes_bindings_tests.adb | 144 +++++++++--------- wrapper/Ada/tests/src/aes_suite.adb | 27 ++-- wrapper/Ada/tests/src/rsa_suite.adb | 27 ++-- .../tests/src/rsa_verify_bindings_tests.adb | 25 +-- .../Ada/tests/src/sha256_bindings_tests.adb | 45 +++--- wrapper/Ada/tests/src/sha256_suite.adb | 23 +-- .../tests/src/support/tests_root_suite.adb | 28 ++-- 7 files changed, 127 insertions(+), 192 deletions(-) diff --git a/wrapper/Ada/tests/src/aes_bindings_tests.adb b/wrapper/Ada/tests/src/aes_bindings_tests.adb index 55ce604b21f..687765c4eac 100644 --- a/wrapper/Ada/tests/src/aes_bindings_tests.adb +++ b/wrapper/Ada/tests/src/aes_bindings_tests.adb @@ -1,5 +1,6 @@ with AUnit.Assertions; with AUnit.Test_Caller; +with AUnit.Test_Suites; with WolfSSL; @@ -9,55 +10,23 @@ package body AES_Bindings_Tests is -- For wc_AesSetKey Dir parameter: -- 0 = encrypt, 1 = decrypt (wolfCrypt convention: WC_AES_ENCRYPT/WC_AES_DECRYPT). - -- Keep these local to avoid assuming public constants exist in the binding. + -- Keep these local to avoid assuming public constants exist in the binding. AES_Encrypt_Dir : constant Integer := 0; AES_Decrypt_Dir : constant Integer := 1; ---------------------------------------------------------------------------- - -- Statically allocated suite object + one-time registration + -- Tests ---------------------------------------------------------------------------- - package Caller is new AUnit.Test_Caller (Fixture); - - Suite_Object : aliased AUnit.Test_Suites.Test_Suite; - Built : Boolean := False; - - procedure Build_Once is - begin - if Built then - return; - end if; - - AUnit.Test_Suites.Add_Test - (Suite_Object'Access, - Caller.Create - (Name => "AES-CBC encrypt/decrypt roundtrip", - Test => Test_AES_CBC_Roundtrip'Access)); - - AUnit.Test_Suites.Add_Test - (Suite_Object'Access, - Caller.Create - (Name => "AES_Free succeeds after Create_AES", - Test => Test_AES_Free_Invalidates'Access)); - - Built := True; - end Build_Once; - - function Suite return AUnit.Test_Suites.Access_Test_Suite is - begin - Build_Once; - return Suite_Object'Access; - end Suite; - procedure Test_AES_CBC_Roundtrip (F : in out Fixture) is pragma Unreferenced (F); - AES : WolfSSL.AES_Type; - R : Integer; + AES : WolfSSL.AES_Type; + R : Integer; -- Explicit byte arrays avoid any ambiguity around string literal lengths -- and prevent run-time Constraint_Error from a mismatched subtype constraint. - Key : constant WolfSSL.Byte_Array (1 .. 32) := + Key : constant WolfSSL.Byte_Array (1 .. 32) := (1 => '0', 2 => '1', 3 => '2', 4 => '3', 5 => '4', 6 => '5', 7 => '6', 8 => '7', 9 => '8', 10 => '9', 11 => 'A', 12 => 'B', @@ -67,7 +36,7 @@ package body AES_Bindings_Tests is 25 => '8', 26 => '9', 27 => 'A', 28 => 'B', 29 => 'C', 30 => 'D', 31 => 'E', 32 => 'F'); - IV_Init : constant WolfSSL.Byte_Array (1 .. 16) := + IV_Init : constant WolfSSL.Byte_Array (1 .. 16) := (1 => 'I', 2 => 'N', 3 => 'I', 4 => 'T', 5 => 'V', 6 => 'E', 7 => 'C', 8 => 'T', 9 => 'O', 10 => 'R', 11 => '_', 12 => '1', @@ -75,7 +44,7 @@ package body AES_Bindings_Tests is -- Use a plaintext length that is a multiple of 16 so we don't rely on any -- padding behavior (the API is raw CBC). Exactly 32 bytes. - Plain : constant WolfSSL.Byte_Array (1 .. 32) := + Plain : constant WolfSSL.Byte_Array (1 .. 32) := (1 => 'T', 2 => 'h', 3 => 'i', 4 => 's', 5 => ' ', 6 => 'i', 7 => 's', 8 => ' ', 9 => '3', 10 => '2', 11 => ' ', 12 => 'b', @@ -85,17 +54,12 @@ package body AES_Bindings_Tests is 25 => '!', 26 => '!', 27 => '!', 28 => '!', 29 => '!', 30 => '!', 31 => '!', 32 => '!'); - Cipher : WolfSSL.Byte_Array (1 .. 32); - Decoded : WolfSSL.Byte_Array (1 .. 32); + Cipher : WolfSSL.Byte_Array (1 .. 32); + Decoded : WolfSSL.Byte_Array (1 .. 32); - IV_Enc : WolfSSL.Byte_Array (1 .. 16); - IV_Dec : WolfSSL.Byte_Array (1 .. 16); + IV_Enc : WolfSSL.Byte_Array (1 .. 16); + IV_Dec : WolfSSL.Byte_Array (1 .. 16); begin - -- Basic sanity for test vector sizes. - -- (This is always true for the hard-coded 32-byte plaintext, so keep it - -- as a comment to avoid "condition is always True" warnings.) - -- Plain'Length mod Block_Size = 0 - IV_Enc := IV_Init; IV_Dec := IV_Init; @@ -103,8 +67,9 @@ package body AES_Bindings_Tests is Device => WolfSSL.Invalid_Device, AES => AES, Result => R); - AUnit.Assertions.Assert (R = 0, - "Create_AES failed, Result =" & Integer'Image (R)); + AUnit.Assertions.Assert + (R = 0, + "Create_AES failed, Result =" & Integer'Image (R)); -- Set key for ENCRYPT; provide IV as required by wc_AesSetKey. WolfSSL.AES_Set_Key (AES => AES, @@ -113,26 +78,25 @@ package body AES_Bindings_Tests is IV => IV_Enc, Dir => AES_Encrypt_Dir, Result => R); - AUnit.Assertions.Assert (R = 0, - "AES_Set_Key(encrypt) failed, Result =" & - Integer'Image (R)); + AUnit.Assertions.Assert + (R = 0, + "AES_Set_Key(encrypt) failed, Result =" & Integer'Image (R)); - -- Ensure IV is what we expect before encrypting. WolfSSL.AES_Set_IV (AES => AES, IV => IV_Enc, Result => R); - AUnit.Assertions.Assert (R = 0, - "AES_Set_IV(encrypt) failed, Result =" & - Integer'Image (R)); + AUnit.Assertions.Assert + (R = 0, + "AES_Set_IV(encrypt) failed, Result =" & Integer'Image (R)); WolfSSL.AES_Set_Cbc_Encrypt (AES => AES, Output => Cipher, Input => Plain, Size => Plain'Length, Result => R); - AUnit.Assertions.Assert (R = 0, - "AES_Set_Cbc_Encrypt failed, Result =" & - Integer'Image (R)); + AUnit.Assertions.Assert + (R = 0, + "AES_Set_Cbc_Encrypt failed, Result =" & Integer'Image (R)); -- Now decrypt. Reset IV to the initial value (CBC requires same IV). WolfSSL.AES_Set_Key (AES => AES, @@ -141,25 +105,25 @@ package body AES_Bindings_Tests is IV => IV_Dec, Dir => AES_Decrypt_Dir, Result => R); - AUnit.Assertions.Assert (R = 0, - "AES_Set_Key(decrypt) failed, Result =" & - Integer'Image (R)); + AUnit.Assertions.Assert + (R = 0, + "AES_Set_Key(decrypt) failed, Result =" & Integer'Image (R)); WolfSSL.AES_Set_IV (AES => AES, IV => IV_Dec, Result => R); - AUnit.Assertions.Assert (R = 0, - "AES_Set_IV(decrypt) failed, Result =" & - Integer'Image (R)); + AUnit.Assertions.Assert + (R = 0, + "AES_Set_IV(decrypt) failed, Result =" & Integer'Image (R)); WolfSSL.AES_Set_Cbc_Decrypt (AES => AES, Output => Decoded, Input => Cipher, Size => Cipher'Length, Result => R); - AUnit.Assertions.Assert (R = 0, - "AES_Set_Cbc_Decrypt failed, Result =" & - Integer'Image (R)); + AUnit.Assertions.Assert + (R = 0, + "AES_Set_Cbc_Decrypt failed, Result =" & Integer'Image (R)); AUnit.Assertions.Assert (Decoded = Plain, "AES-CBC roundtrip mismatch"); @@ -186,21 +150,49 @@ package body AES_Bindings_Tests is Device => WolfSSL.Invalid_Device, AES => AES, Result => R); - AUnit.Assertions.Assert (R = 0, - "Create_AES failed, Result =" & Integer'Image (R)); - AUnit.Assertions.Assert (WolfSSL.Is_Valid (AES), - "AES should be valid after Create_AES"); + AUnit.Assertions.Assert + (R = 0, + "Create_AES failed, Result =" & Integer'Image (R)); + AUnit.Assertions.Assert + (WolfSSL.Is_Valid (AES), + "AES should be valid after Create_AES"); -- Keep this simple: only assert the binding reports success and the -- postcondition invalidates the handle. WolfSSL.AES_Free (AES => AES, Result => R); - -- Keep this test simple and tolerant: only assert invalidation when the - -- underlying free operation reports success. + -- Only assert invalidation when the underlying free operation reports success. if R = 0 then AUnit.Assertions.Assert (not WolfSSL.Is_Valid (AES), "AES should be invalid after AES_Free"); end if; end Test_AES_Free_Invalidates; -end AES_Bindings_Tests; + ---------------------------------------------------------------------------- + -- Suite (static suite object + elaboration-time registration) + ---------------------------------------------------------------------------- + + package Caller is new AUnit.Test_Caller (Fixture); + + Suite_Object : aliased AUnit.Test_Suites.Test_Suite; + + function Suite return AUnit.Test_Suites.Access_Test_Suite is + begin + return Suite_Object'Access; + end Suite; + +begin + -- Register tests at elaboration time (standard Ada: all declarations above). + AUnit.Test_Suites.Add_Test + (Suite_Object'Access, + Caller.Create + (Name => "AES-CBC encrypt/decrypt roundtrip", + Test => Test_AES_CBC_Roundtrip'Access)); + + AUnit.Test_Suites.Add_Test + (Suite_Object'Access, + Caller.Create + (Name => "AES_Free succeeds after Create_AES", + Test => Test_AES_Free_Invalidates'Access)); + +end AES_Bindings_Tests; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/aes_suite.adb b/wrapper/Ada/tests/src/aes_suite.adb index 7dfc86383cf..6ceee9d4557 100644 --- a/wrapper/Ada/tests/src/aes_suite.adb +++ b/wrapper/Ada/tests/src/aes_suite.adb @@ -1,29 +1,20 @@ +with AUnit.Test_Suites; + with AES_Bindings_Tests; package body AES_Suite is -- Statically allocated (library-level) suite object. - -- This avoids heap allocation and satisfies Ada accessibility rules when - -- returning an Access_Test_Suite. - Root : aliased AUnit.Test_Suites.Test_Suite; - Built : Boolean := False; - - procedure Build_Once is - begin - if Built then - return; - end if; - - -- Register AES-related test suites here. - AUnit.Test_Suites.Add_Test (Root'Access, AES_Bindings_Tests.Suite); - - Built := True; - end Build_Once; + -- Built once at elaboration time. + Root : aliased AUnit.Test_Suites.Test_Suite; function Suite return AUnit.Test_Suites.Access_Test_Suite is begin - Build_Once; return Root'Access; end Suite; -end AES_Suite; +begin + -- Register AES-related test suites here. + AUnit.Test_Suites.Add_Test (Root'Access, AES_Bindings_Tests.Suite); + +end AES_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/rsa_suite.adb b/wrapper/Ada/tests/src/rsa_suite.adb index 6b3279ee5d6..15ed97e03e4 100644 --- a/wrapper/Ada/tests/src/rsa_suite.adb +++ b/wrapper/Ada/tests/src/rsa_suite.adb @@ -1,29 +1,20 @@ +with AUnit.Test_Suites; + with RSA_Verify_Bindings_Tests; package body RSA_Suite is -- Statically allocated (library-level) suite object. - -- This avoids heap allocation and satisfies Ada accessibility rules when - -- returning an Access_Test_Suite. - Root : aliased AUnit.Test_Suites.Test_Suite; - Built : Boolean := False; - - procedure Build_Once is - begin - if Built then - return; - end if; - - -- Register RSA-related test suites here. - AUnit.Test_Suites.Add_Test (Root'Access, RSA_Verify_Bindings_Tests.Suite); - - Built := True; - end Build_Once; + -- Built once at elaboration time (no guard needed). + Root : aliased AUnit.Test_Suites.Test_Suite; function Suite return AUnit.Test_Suites.Access_Test_Suite is begin - Build_Once; return Root'Access; end Suite; -end RSA_Suite; +begin + -- Register RSA-related test suites here. + AUnit.Test_Suites.Add_Test (Root'Access, RSA_Verify_Bindings_Tests.Suite); + +end RSA_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb index c30e351d758..b3ffac1b111 100644 --- a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb +++ b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb @@ -442,27 +442,18 @@ package body RSA_Verify_Bindings_Tests is package Caller is new AUnit.Test_Caller (Fixture); Suite_Object : aliased AUnit.Test_Suites.Test_Suite; - Built : Boolean := False; - - procedure Build_Once is - begin - if Built then - return; - end if; - - AUnit.Test_Suites.Add_Test - (Suite_Object'Access, - Caller.Create - (Name => "RSA sign/verify and encrypt/decrypt (rsa_verify_main)", - Test => Test_RSA_Sign_Verify_And_Encrypt_Decrypt'Access)); - - Built := True; - end Build_Once; function Suite return AUnit.Test_Suites.Access_Test_Suite is begin - Build_Once; return Suite_Object'Access; end Suite; +begin + -- Register RSA tests once at elaboration time. + AUnit.Test_Suites.Add_Test + (Suite_Object'Access, + Caller.Create + (Name => "RSA sign/verify and encrypt/decrypt (rsa_verify_main)", + Test => Test_RSA_Sign_Verify_And_Encrypt_Decrypt'Access)); + end RSA_Verify_Bindings_Tests; diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.adb b/wrapper/Ada/tests/src/sha256_bindings_tests.adb index db14eb7ce23..720e06ca3af 100644 --- a/wrapper/Ada/tests/src/sha256_bindings_tests.adb +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.adb @@ -183,43 +183,32 @@ package body SHA256_Bindings_Tests is end Test_SHA256_Empty_Message; ---------------------------------------------------------------------------- - -- Statically allocated suite + test case objects (no heap allocation) + -- Statically allocated suite object; register tests at elaboration time ---------------------------------------------------------------------------- package Caller is new AUnit.Test_Caller (Fixture); Suite_Object : aliased AUnit.Test_Suites.Test_Suite; - Built : Boolean := False; - - procedure Build_Once is - begin - if Built then - return; - end if; - - -- Each Caller.Create returns an access value. Depending on AUnit internals, - -- those test case objects might still be allocated by the framework. - -- This unit guarantees that *our* suite object is statically allocated - -- and that the registration is done once at library level. - AUnit.Test_Suites.Add_Test - (Suite_Object'Access, - Caller.Create - (Name => "SHA256('asdf') produces expected hash", - Test => Test_SHA256_Asdf_Known_Vector'Access)); - - AUnit.Test_Suites.Add_Test - (Suite_Object'Access, - Caller.Create - (Name => "SHA256('') produces expected hash", - Test => Test_SHA256_Empty_Message'Access)); - - Built := True; - end Build_Once; function Suite return AUnit.Test_Suites.Access_Test_Suite is begin - Build_Once; return Suite_Object'Access; end Suite; +begin + -- Register SHA256-related tests once at elaboration time. + -- Note: Caller.Create returns an access value; AUnit may still allocate + -- the test-case objects internally. This keeps the suite itself static. + AUnit.Test_Suites.Add_Test + (Suite_Object'Access, + Caller.Create + (Name => "SHA256('asdf') produces expected hash", + Test => Test_SHA256_Asdf_Known_Vector'Access)); + + AUnit.Test_Suites.Add_Test + (Suite_Object'Access, + Caller.Create + (Name => "SHA256('') produces expected hash", + Test => Test_SHA256_Empty_Message'Access)); + end SHA256_Bindings_Tests; diff --git a/wrapper/Ada/tests/src/sha256_suite.adb b/wrapper/Ada/tests/src/sha256_suite.adb index f91cca4fc10..828a8b01b1c 100644 --- a/wrapper/Ada/tests/src/sha256_suite.adb +++ b/wrapper/Ada/tests/src/sha256_suite.adb @@ -5,27 +5,16 @@ with SHA256_Bindings_Tests; package body SHA256_Suite is -- Statically allocated (library-level) suite object. - -- This avoids heap allocation and satisfies Ada accessibility rules when - -- returning an Access_Test_Suite. - Root : aliased AUnit.Test_Suites.Test_Suite; - Built : Boolean := False; - - procedure Build_Once is - begin - if Built then - return; - end if; - - -- Register SHA256-related test suites here. - AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Bindings_Tests.Suite); - - Built := True; - end Build_Once; + Root : aliased AUnit.Test_Suites.Test_Suite; + -- Must be declared before the package body's `begin` in standard Ada. function Suite return AUnit.Test_Suites.Access_Test_Suite is begin - Build_Once; return Root'Access; end Suite; +begin + -- Register SHA256-related test suites here (performed at elaboration time). + AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Bindings_Tests.Suite); + end SHA256_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/tests_root_suite.adb b/wrapper/Ada/tests/src/support/tests_root_suite.adb index 0a0b1b40ee4..4a8124c7f56 100644 --- a/wrapper/Ada/tests/src/support/tests_root_suite.adb +++ b/wrapper/Ada/tests/src/support/tests_root_suite.adb @@ -1,3 +1,5 @@ +with AUnit.Test_Suites; + with SHA256_Suite; with RSA_Suite; with AES_Suite; @@ -8,26 +10,16 @@ package body Tests_Root_Suite is -- (no dangling pointer / accessibility issues). Root : aliased AUnit.Test_Suites.Test_Suite; - Built : Boolean := False; - - procedure Build_Once is - begin - if Built then - return; - end if; - - -- Compose the root suite from sub-suites. - AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Suite.Suite); - AUnit.Test_Suites.Add_Test (Root'Access, RSA_Suite.Suite); - AUnit.Test_Suites.Add_Test (Root'Access, AES_Suite.Suite); - - Built := True; - end Build_Once; - function Suite return AUnit.Test_Suites.Access_Test_Suite is begin - Build_Once; return Root'Access; end Suite; -end Tests_Root_Suite; +begin + -- Compose the root suite at elaboration time. + -- Note: all declarations (including Suite) must appear before this begin. + AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Suite.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, RSA_Suite.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, AES_Suite.Suite); + +end Tests_Root_Suite; \ No newline at end of file From 9c246e1f518da4fd8db6e835e1c7f8799bd1b15a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 13:59:55 +0100 Subject: [PATCH 17/51] Ada tests: simplify harness and reduce boilerplate --- wrapper/Ada/tests/src/aes_bindings_tests.adb | 79 +++++---------- wrapper/Ada/tests/src/aes_suite.adb | 20 ---- wrapper/Ada/tests/src/aes_suite.ads | 6 -- wrapper/Ada/tests/src/rsa_suite.adb | 20 ---- wrapper/Ada/tests/src/rsa_suite.ads | 6 -- .../Ada/tests/src/sha256_bindings_tests.adb | 82 +++++---------- wrapper/Ada/tests/src/sha256_suite.adb | 20 ---- wrapper/Ada/tests/src/sha256_suite.ads | 6 -- .../Ada/tests/src/support/test_support.adb | 99 +++++++++++++++++++ .../Ada/tests/src/support/test_support.ads | 33 +++++++ .../tests/src/support/tests_root_suite.adb | 20 ++-- .../tests/src/support/tests_root_suite.ads | 3 +- .../Ada/tests/src/support/tests_runner.adb | 17 ---- .../Ada/tests/src/support/tests_runner.ads | 16 --- wrapper/Ada/tests/src/tests.adb | 10 +- 15 files changed, 201 insertions(+), 236 deletions(-) delete mode 100644 wrapper/Ada/tests/src/aes_suite.adb delete mode 100644 wrapper/Ada/tests/src/aes_suite.ads delete mode 100644 wrapper/Ada/tests/src/rsa_suite.adb delete mode 100644 wrapper/Ada/tests/src/rsa_suite.ads delete mode 100644 wrapper/Ada/tests/src/sha256_suite.adb delete mode 100644 wrapper/Ada/tests/src/sha256_suite.ads create mode 100644 wrapper/Ada/tests/src/support/test_support.adb create mode 100644 wrapper/Ada/tests/src/support/test_support.ads delete mode 100644 wrapper/Ada/tests/src/support/tests_runner.adb delete mode 100644 wrapper/Ada/tests/src/support/tests_runner.ads diff --git a/wrapper/Ada/tests/src/aes_bindings_tests.adb b/wrapper/Ada/tests/src/aes_bindings_tests.adb index 687765c4eac..fe094917d8d 100644 --- a/wrapper/Ada/tests/src/aes_bindings_tests.adb +++ b/wrapper/Ada/tests/src/aes_bindings_tests.adb @@ -4,6 +4,8 @@ with AUnit.Test_Suites; with WolfSSL; +with Test_Support; + package body AES_Bindings_Tests is use type WolfSSL.Byte_Array; @@ -24,41 +26,22 @@ package body AES_Bindings_Tests is AES : WolfSSL.AES_Type; R : Integer; - -- Explicit byte arrays avoid any ambiguity around string literal lengths - -- and prevent run-time Constraint_Error from a mismatched subtype constraint. - Key : constant WolfSSL.Byte_Array (1 .. 32) := - (1 => '0', 2 => '1', 3 => '2', 4 => '3', - 5 => '4', 6 => '5', 7 => '6', 8 => '7', - 9 => '8', 10 => '9', 11 => 'A', 12 => 'B', - 13 => 'C', 14 => 'D', 15 => 'E', 16 => 'F', - 17 => '0', 18 => '1', 19 => '2', 20 => '3', - 21 => '4', 22 => '5', 23 => '6', 24 => '7', - 25 => '8', 26 => '9', 27 => 'A', 28 => 'B', - 29 => 'C', 30 => 'D', 31 => 'E', 32 => 'F'); - - IV_Init : constant WolfSSL.Byte_Array (1 .. 16) := - (1 => 'I', 2 => 'N', 3 => 'I', 4 => 'T', - 5 => 'V', 6 => 'E', 7 => 'C', 8 => 'T', - 9 => 'O', 10 => 'R', 11 => '_', 12 => '1', - 13 => '6', 14 => 'B', 15 => '_', 16 => '_'); + Key : constant WolfSSL.Byte_Array := + Test_Support.Bytes ("0123456789ABCDEF0123456789ABCDEF"); + + IV_Init : constant WolfSSL.Byte_Array := + Test_Support.Bytes ("INITVECTOR_16B__"); -- Use a plaintext length that is a multiple of 16 so we don't rely on any -- padding behavior (the API is raw CBC). Exactly 32 bytes. - Plain : constant WolfSSL.Byte_Array (1 .. 32) := - (1 => 'T', 2 => 'h', 3 => 'i', 4 => 's', - 5 => ' ', 6 => 'i', 7 => 's', 8 => ' ', - 9 => '3', 10 => '2', 11 => ' ', 12 => 'b', - 13 => 'y', 14 => 't', 15 => 'e', 16 => 's', - 17 => ' ', 18 => 'o', 19 => 'f', 20 => ' ', - 21 => 'd', 22 => 'a', 23 => 't', 24 => 'a', - 25 => '!', 26 => '!', 27 => '!', 28 => '!', - 29 => '!', 30 => '!', 31 => '!', 32 => '!'); - - Cipher : WolfSSL.Byte_Array (1 .. 32); - Decoded : WolfSSL.Byte_Array (1 .. 32); - - IV_Enc : WolfSSL.Byte_Array (1 .. 16); - IV_Dec : WolfSSL.Byte_Array (1 .. 16); + Plain : constant WolfSSL.Byte_Array := + Test_Support.Bytes ("This is 32 bytes of data!!!!!!!!"); + + Cipher : WolfSSL.Byte_Array (1 .. Plain'Length); + Decoded : WolfSSL.Byte_Array (1 .. Plain'Length); + + IV_Enc : WolfSSL.Byte_Array (1 .. IV_Init'Length); + IV_Dec : WolfSSL.Byte_Array (1 .. IV_Init'Length); begin IV_Enc := IV_Init; IV_Dec := IV_Init; @@ -67,9 +50,7 @@ package body AES_Bindings_Tests is Device => WolfSSL.Invalid_Device, AES => AES, Result => R); - AUnit.Assertions.Assert - (R = 0, - "Create_AES failed, Result =" & Integer'Image (R)); + Test_Support.Assert_Success (R, "Create_AES"); -- Set key for ENCRYPT; provide IV as required by wc_AesSetKey. WolfSSL.AES_Set_Key (AES => AES, @@ -78,25 +59,19 @@ package body AES_Bindings_Tests is IV => IV_Enc, Dir => AES_Encrypt_Dir, Result => R); - AUnit.Assertions.Assert - (R = 0, - "AES_Set_Key(encrypt) failed, Result =" & Integer'Image (R)); + Test_Support.Assert_Success (R, "AES_Set_Key(encrypt)"); WolfSSL.AES_Set_IV (AES => AES, IV => IV_Enc, Result => R); - AUnit.Assertions.Assert - (R = 0, - "AES_Set_IV(encrypt) failed, Result =" & Integer'Image (R)); + Test_Support.Assert_Success (R, "AES_Set_IV(encrypt)"); WolfSSL.AES_Set_Cbc_Encrypt (AES => AES, Output => Cipher, Input => Plain, Size => Plain'Length, Result => R); - AUnit.Assertions.Assert - (R = 0, - "AES_Set_Cbc_Encrypt failed, Result =" & Integer'Image (R)); + Test_Support.Assert_Success (R, "AES_Set_Cbc_Encrypt"); -- Now decrypt. Reset IV to the initial value (CBC requires same IV). WolfSSL.AES_Set_Key (AES => AES, @@ -105,25 +80,19 @@ package body AES_Bindings_Tests is IV => IV_Dec, Dir => AES_Decrypt_Dir, Result => R); - AUnit.Assertions.Assert - (R = 0, - "AES_Set_Key(decrypt) failed, Result =" & Integer'Image (R)); + Test_Support.Assert_Success (R, "AES_Set_Key(decrypt)"); WolfSSL.AES_Set_IV (AES => AES, IV => IV_Dec, Result => R); - AUnit.Assertions.Assert - (R = 0, - "AES_Set_IV(decrypt) failed, Result =" & Integer'Image (R)); + Test_Support.Assert_Success (R, "AES_Set_IV(decrypt)"); WolfSSL.AES_Set_Cbc_Decrypt (AES => AES, Output => Decoded, Input => Cipher, Size => Cipher'Length, Result => R); - AUnit.Assertions.Assert - (R = 0, - "AES_Set_Cbc_Decrypt failed, Result =" & Integer'Image (R)); + Test_Support.Assert_Success (R, "AES_Set_Cbc_Decrypt"); AUnit.Assertions.Assert (Decoded = Plain, "AES-CBC roundtrip mismatch"); @@ -150,9 +119,7 @@ package body AES_Bindings_Tests is Device => WolfSSL.Invalid_Device, AES => AES, Result => R); - AUnit.Assertions.Assert - (R = 0, - "Create_AES failed, Result =" & Integer'Image (R)); + Test_Support.Assert_Success (R, "Create_AES"); AUnit.Assertions.Assert (WolfSSL.Is_Valid (AES), "AES should be valid after Create_AES"); diff --git a/wrapper/Ada/tests/src/aes_suite.adb b/wrapper/Ada/tests/src/aes_suite.adb deleted file mode 100644 index 6ceee9d4557..00000000000 --- a/wrapper/Ada/tests/src/aes_suite.adb +++ /dev/null @@ -1,20 +0,0 @@ -with AUnit.Test_Suites; - -with AES_Bindings_Tests; - -package body AES_Suite is - - -- Statically allocated (library-level) suite object. - -- Built once at elaboration time. - Root : aliased AUnit.Test_Suites.Test_Suite; - - function Suite return AUnit.Test_Suites.Access_Test_Suite is - begin - return Root'Access; - end Suite; - -begin - -- Register AES-related test suites here. - AUnit.Test_Suites.Add_Test (Root'Access, AES_Bindings_Tests.Suite); - -end AES_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/aes_suite.ads b/wrapper/Ada/tests/src/aes_suite.ads deleted file mode 100644 index 320772bdb13..00000000000 --- a/wrapper/Ada/tests/src/aes_suite.ads +++ /dev/null @@ -1,6 +0,0 @@ -with AUnit.Test_Suites; - -package AES_Suite is - -- Aggregate suite for AES binding tests. - function Suite return AUnit.Test_Suites.Access_Test_Suite; -end AES_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/rsa_suite.adb b/wrapper/Ada/tests/src/rsa_suite.adb deleted file mode 100644 index 15ed97e03e4..00000000000 --- a/wrapper/Ada/tests/src/rsa_suite.adb +++ /dev/null @@ -1,20 +0,0 @@ -with AUnit.Test_Suites; - -with RSA_Verify_Bindings_Tests; - -package body RSA_Suite is - - -- Statically allocated (library-level) suite object. - -- Built once at elaboration time (no guard needed). - Root : aliased AUnit.Test_Suites.Test_Suite; - - function Suite return AUnit.Test_Suites.Access_Test_Suite is - begin - return Root'Access; - end Suite; - -begin - -- Register RSA-related test suites here. - AUnit.Test_Suites.Add_Test (Root'Access, RSA_Verify_Bindings_Tests.Suite); - -end RSA_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/rsa_suite.ads b/wrapper/Ada/tests/src/rsa_suite.ads deleted file mode 100644 index 65c37f37efe..00000000000 --- a/wrapper/Ada/tests/src/rsa_suite.ads +++ /dev/null @@ -1,6 +0,0 @@ -with AUnit.Test_Suites; - -package RSA_Suite is - -- Aggregate suite for RSA binding tests. - function Suite return AUnit.Test_Suites.Access_Test_Suite; -end RSA_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.adb b/wrapper/Ada/tests/src/sha256_bindings_tests.adb index 720e06ca3af..10f540e1a54 100644 --- a/wrapper/Ada/tests/src/sha256_bindings_tests.adb +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.adb @@ -3,6 +3,8 @@ with AUnit.Test_Caller; with WolfSSL; +with Test_Support; + package body SHA256_Bindings_Tests is ---------------------------------------------------------------------------- @@ -25,50 +27,23 @@ package body SHA256_Bindings_Tests is Text : WolfSSL.SHA256_As_String; Msg : String) is - function Hex_Value (C : Character) return Natural is - begin - case C is - when '0' .. '9' => - return Character'Pos (C) - Character'Pos ('0'); - when 'A' .. 'F' => - return 10 + (Character'Pos (C) - Character'Pos ('A')); - when 'a' .. 'f' => - return 10 + (Character'Pos (C) - Character'Pos ('a')); - when others => - AUnit.Assertions.Assert - (False, - Msg & ": invalid hex character '" & C & "'"); - return 0; - end case; - end Hex_Value; - - I : Positive; - Hi : Natural; - Lo : Natural; - Byte_As_Int : Natural; + use type WolfSSL.Byte_Array; + + Expected : constant WolfSSL.Byte_Array := Test_Support.Hex_Bytes (Text); + Actual : WolfSSL.Byte_Array (Expected'Range); + H : WolfSSL.Byte_Index := Hash'First; begin + -- Copy bytes out of the hash into the expected-range buffer. + -- Do not assume Hash and Expected share the same index range. + for I in Actual'Range loop + Actual (I) := Hash (H); + H := WolfSSL.Byte_Index'Succ (H); + end loop; AUnit.Assertions.Assert (Text'Length = 64, Msg & ": expected 64 hex chars, got" & Integer'Image (Text'Length)); - for Index in Positive range 1 .. 32 loop - I := 2 * (Index - 1) + 1; - Hi := Hex_Value (Text (I)); - Lo := Hex_Value (Text (I + 1)); - - Byte_As_Int := 16 * Hi + Lo; - - -- SHA256_Hash is a Byte_Array backed by `Interfaces.C.char_array`. - -- Avoid a direct `Interfaces.C` dependency here by using the binding's - -- own aliases (`Byte_Type`, `Byte_Index`) for indexing and conversion. - AUnit.Assertions.Assert - (Byte_As_Int = - WolfSSL.Byte_Type'Pos (Hash (WolfSSL.Byte_Index (Index))), - Msg & ": Text/Hash mismatch at byte" & - Integer'Image (Index)); - end loop; - - -- `Finalize_SHA256` generates uppercase hex, validate that expectation. + -- `Finalize_SHA256` should generate uppercase hex, validate that expectation. for J in Text'Range loop declare C : constant Character := Text (J); @@ -83,6 +58,10 @@ package body SHA256_Bindings_Tests is end if; end; end loop; + + AUnit.Assertions.Assert + (Actual = Expected, + Msg & ": Text/Hash mismatch"); end Assert_Text_Matches_Hash; procedure Compute_SHA256 @@ -127,21 +106,15 @@ package body SHA256_Bindings_Tests is Text : WolfSSL.SHA256_As_String; R : Integer; - Input : constant WolfSSL.Byte_Array := - (1 => 'a', - 2 => 's', - 3 => 'd', - 4 => 'f'); + Input : constant WolfSSL.Byte_Array := Test_Support.Bytes ("asdf"); Expected_Text : constant WolfSSL.SHA256_As_String := - "F0E4C2F76C58916EC258F246851BEA091D14D4247A2FC3E18694461B1816E13B"; + Test_Support.SHA256_Text + ("F0E4C2F76C58916EC258F246851BEA091D14D4247A2FC3E18694461B1816E13B"); begin Compute_SHA256 (Input => Input, Hash => Hash, Text => Text, Result => R); - AUnit.Assertions.Assert - (R = 0, - "SHA256('asdf') bindings should succeed, Result =" & - Integer'Image (R)); + Test_Support.Assert_Success (R, "SHA256(asdf)"); AUnit.Assertions.Assert (Text = Expected_Text, @@ -158,19 +131,16 @@ package body SHA256_Bindings_Tests is Text : WolfSSL.SHA256_As_String; R : Integer; - -- If this doesn't compile depending on how `Byte_Array` is declared, - -- rework this test to produce an empty input safely for that declaration. + -- Represent empty input as a null range, matching the existing test style. Empty : constant WolfSSL.Byte_Array := (1 .. 0 => <>); Expected_Text : constant WolfSSL.SHA256_As_String := - "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"; + Test_Support.SHA256_Text + ("E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"); begin Compute_SHA256 (Input => Empty, Hash => Hash, Text => Text, Result => R); - AUnit.Assertions.Assert - (R = 0, - "SHA256('') bindings should succeed, Result =" & - Integer'Image (R)); + Test_Support.Assert_Success (R, "SHA256(empty)"); AUnit.Assertions.Assert (Text = Expected_Text, diff --git a/wrapper/Ada/tests/src/sha256_suite.adb b/wrapper/Ada/tests/src/sha256_suite.adb deleted file mode 100644 index 828a8b01b1c..00000000000 --- a/wrapper/Ada/tests/src/sha256_suite.adb +++ /dev/null @@ -1,20 +0,0 @@ -with AUnit.Test_Suites; - -with SHA256_Bindings_Tests; - -package body SHA256_Suite is - - -- Statically allocated (library-level) suite object. - Root : aliased AUnit.Test_Suites.Test_Suite; - - -- Must be declared before the package body's `begin` in standard Ada. - function Suite return AUnit.Test_Suites.Access_Test_Suite is - begin - return Root'Access; - end Suite; - -begin - -- Register SHA256-related test suites here (performed at elaboration time). - AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Bindings_Tests.Suite); - -end SHA256_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/sha256_suite.ads b/wrapper/Ada/tests/src/sha256_suite.ads deleted file mode 100644 index 68b514efcf3..00000000000 --- a/wrapper/Ada/tests/src/sha256_suite.ads +++ /dev/null @@ -1,6 +0,0 @@ -with AUnit.Test_Suites; - -package SHA256_Suite is - -- Aggregate suite for SHA256 binding tests. - function Suite return AUnit.Test_Suites.Access_Test_Suite; -end SHA256_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/test_support.adb b/wrapper/Ada/tests/src/support/test_support.adb new file mode 100644 index 00000000000..4fbc8708ea5 --- /dev/null +++ b/wrapper/Ada/tests/src/support/test_support.adb @@ -0,0 +1,99 @@ +with AUnit.Assertions; + +with WolfSSL; + +package body Test_Support is + + ---------------------------------------------------------------------------- + -- Assertions + ---------------------------------------------------------------------------- + + procedure Assert_Success (Result : Integer; What : String) is + begin + AUnit.Assertions.Assert + (Result = 0, + What & " failed, Result =" & Integer'Image (Result)); + end Assert_Success; + + ---------------------------------------------------------------------------- + -- Data helpers + ---------------------------------------------------------------------------- + + function Bytes (S : String) return WolfSSL.Byte_Array is + -- WolfSSL.Byte_Array is Interfaces.C.char_array indexed by + -- WolfSSL.Byte_Index (size_t). Avoid doing arithmetic directly on that + -- index type; instead, use Natural for arithmetic and convert at the + -- point of indexing. + Last_N : constant Natural := (if S'Length = 0 then 0 else S'Length - 1); + B : WolfSSL.Byte_Array (0 .. WolfSSL.Byte_Index (Last_N)); + N : Natural := 0; + begin + for C of S loop + B (WolfSSL.Byte_Index (N)) := + WolfSSL.Byte_Type'Val (Character'Pos (C)); + N := N + 1; + end loop; + return B; + end Bytes; + + function Hex_Value (C : Character) return Natural is + begin + case C is + when '0' .. '9' => + return Character'Pos (C) - Character'Pos ('0'); + when 'A' .. 'F' => + return 10 + (Character'Pos (C) - Character'Pos ('A')); + when 'a' .. 'f' => + return 10 + (Character'Pos (C) - Character'Pos ('a')); + when others => + AUnit.Assertions.Assert + (False, + "invalid hex character '" & C & "'"); + return 0; + end case; + end Hex_Value; + + function Hex_Bytes (Hex : String) return WolfSSL.Byte_Array is + Len : constant Natural := Hex'Length; + begin + AUnit.Assertions.Assert + (Len mod 2 = 0, + "hex string length must be even, got" & Integer'Image (Len)); + + declare + N : constant Natural := Len / 2; + Last_N : constant Natural := (if N = 0 then 0 else N - 1); + B : WolfSSL.Byte_Array (0 .. WolfSSL.Byte_Index (Last_N)); + Hi : Natural; + Lo : Natural; + J : Natural := 0; + begin + for K in 0 .. N - 1 loop + J := 2 * K; + Hi := Hex_Value (Hex (Hex'First + J)); + Lo := Hex_Value (Hex (Hex'First + J + 1)); + B (WolfSSL.Byte_Index (K)) := + WolfSSL.Byte_Type'Val (16 * Hi + Lo); + end loop; + return B; + end; + end Hex_Bytes; + + function SHA256_Text (Hex : String) return WolfSSL.SHA256_As_String is + T : WolfSSL.SHA256_As_String; + I : Natural := 0; + begin + AUnit.Assertions.Assert + (Hex'Length = T'Length, + "SHA256 hex must be 64 characters, got" & + Integer'Image (Hex'Length)); + + for C of Hex loop + I := I + 1; + T (T'First + (I - 1)) := C; + end loop; + + return T; + end SHA256_Text; + +end Test_Support; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/test_support.ads b/wrapper/Ada/tests/src/support/test_support.ads new file mode 100644 index 00000000000..06b8c7c20e9 --- /dev/null +++ b/wrapper/Ada/tests/src/support/test_support.ads @@ -0,0 +1,33 @@ +with WolfSSL; + +package Test_Support is + -- Small helpers to reduce test boilerplate and keep data declarations concise. + + ----------------------------------------------------------------------------- + -- Assertions + ----------------------------------------------------------------------------- + + -- Assert that a WolfSSL binding call returned success (0). + procedure Assert_Success (Result : Integer; What : String); + + ----------------------------------------------------------------------------- + -- Data helpers + ----------------------------------------------------------------------------- + + -- Convert a String into a WolfSSL.Byte_Array, byte-for-byte. + -- Intended for test vectors like keys/IVs/plaintext where ASCII is fine. + function Bytes (S : String) return WolfSSL.Byte_Array; + + -- Convert a hex string (e.g. "0A1bFF") into a Byte_Array. + -- - Accepts both uppercase and lowercase hex. + -- - Requires an even number of hex characters. + function Hex_Bytes (Hex : String) return WolfSSL.Byte_Array; + + -- Convert a hex string into a SHA256 text value. + -- This is handy for expected SHA256 digests ("64 hex chars"). + function SHA256_Text (Hex : String) return WolfSSL.SHA256_As_String; + +private + -- Put small internal helpers in the body; keep the spec minimal. + pragma Inline (Assert_Success); +end Test_Support; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/tests_root_suite.adb b/wrapper/Ada/tests/src/support/tests_root_suite.adb index 4a8124c7f56..9be388f3ac3 100644 --- a/wrapper/Ada/tests/src/support/tests_root_suite.adb +++ b/wrapper/Ada/tests/src/support/tests_root_suite.adb @@ -1,13 +1,14 @@ with AUnit.Test_Suites; -with SHA256_Suite; -with RSA_Suite; -with AES_Suite; +with AES_Bindings_Tests; +with RSA_Verify_Bindings_Tests; +with SHA256_Bindings_Tests; package body Tests_Root_Suite is - -- Library-level object (static storage) so returning its access is legal - -- (no dangling pointer / accessibility issues). + -- Statically allocated (library-level) suite object. + -- Returning Root'Access is safe (no dangling pointer / accessibility issues), + -- and avoids heap allocation (so Valgrind stays clean). Root : aliased AUnit.Test_Suites.Test_Suite; function Suite return AUnit.Test_Suites.Access_Test_Suite is @@ -16,10 +17,9 @@ package body Tests_Root_Suite is end Suite; begin - -- Compose the root suite at elaboration time. - -- Note: all declarations (including Suite) must appear before this begin. - AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Suite.Suite); - AUnit.Test_Suites.Add_Test (Root'Access, RSA_Suite.Suite); - AUnit.Test_Suites.Add_Test (Root'Access, AES_Suite.Suite); + -- Register all binding test suites at elaboration time. + AUnit.Test_Suites.Add_Test (Root'Access, SHA256_Bindings_Tests.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, RSA_Verify_Bindings_Tests.Suite); + AUnit.Test_Suites.Add_Test (Root'Access, AES_Bindings_Tests.Suite); end Tests_Root_Suite; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/tests_root_suite.ads b/wrapper/Ada/tests/src/support/tests_root_suite.ads index d72b2cf0b05..5f5f5499fae 100644 --- a/wrapper/Ada/tests/src/support/tests_root_suite.ads +++ b/wrapper/Ada/tests/src/support/tests_root_suite.ads @@ -7,7 +7,8 @@ with AUnit.Test_Suites; -- - Return an Access_Test_Suite that safely designates a library-level object -- (to satisfy Ada accessibility rules without Unrestricted_Access). -- --- The body is responsible for populating the suite exactly once. +-- The body is responsible for populating the suite exactly once (typically at +-- elaboration time). package Tests_Root_Suite is diff --git a/wrapper/Ada/tests/src/support/tests_runner.adb b/wrapper/Ada/tests/src/support/tests_runner.adb deleted file mode 100644 index 9c8c062bc17..00000000000 --- a/wrapper/Ada/tests/src/support/tests_runner.adb +++ /dev/null @@ -1,17 +0,0 @@ -with AUnit.Reporter.Text; -with AUnit.Run; - -with Tests_Root_Suite; - -package body Tests_Runner is - - -- Instantiate the generic AUnit runner at library level so it does not - -- capture any local objects and remains fully static. - procedure Runner is new AUnit.Run.Test_Runner (Tests_Root_Suite.Suite); - - procedure Run (Reporter : in out AUnit.Reporter.Text.Text_Reporter) is - begin - Runner (Reporter); - end Run; - -end Tests_Runner; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/support/tests_runner.ads b/wrapper/Ada/tests/src/support/tests_runner.ads deleted file mode 100644 index 900ca75ffe4..00000000000 --- a/wrapper/Ada/tests/src/support/tests_runner.ads +++ /dev/null @@ -1,16 +0,0 @@ -with AUnit.Reporter.Text; - --- Dedicated AUnit runner. --- --- This unit exists so the generic instantiation of AUnit's test runner can be --- placed at library level (static), rather than inside `procedure Tests`. --- --- The body is expected to instantiate `AUnit.Run.Test_Runner` with the root --- suite function (e.g. `Tests_Root_Suite.Suite`) and expose a simple `Run` --- wrapper. - -package Tests_Runner is - - procedure Run (Reporter : in out AUnit.Reporter.Text.Text_Reporter); - -end Tests_Runner; \ No newline at end of file diff --git a/wrapper/Ada/tests/src/tests.adb b/wrapper/Ada/tests/src/tests.adb index 6c52197ff75..0ed6faa033b 100644 --- a/wrapper/Ada/tests/src/tests.adb +++ b/wrapper/Ada/tests/src/tests.adb @@ -1,9 +1,15 @@ with AUnit.Reporter.Text; +with AUnit.Run; -with Tests_Runner; +with Tests_Root_Suite; procedure Tests is Reporter : AUnit.Reporter.Text.Text_Reporter; + + -- Instantiate the generic AUnit runner with a *library-level* suite function. + -- This avoids Ada accessibility issues (no local objects' 'Access escaping) + -- and keeps the harness minimal. + procedure Runner is new AUnit.Run.Test_Runner (Tests_Root_Suite.Suite); begin - Tests_Runner.Run (Reporter); + Runner (Reporter); end Tests; \ No newline at end of file From b2b1bde74a165c6819ca9f25007d8180862164f9 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 15:19:11 +0100 Subject: [PATCH 18/51] Ada: allocate SHA256 with malloc and add Free_SHA256 --- wrapper/Ada/ada_binding.c | 21 ++++---- wrapper/Ada/sha256_main.adb | 5 +- .../Ada/tests/src/sha256_bindings_tests.adb | 7 ++- wrapper/Ada/wolfssl.adb | 51 +++++++++++++++---- wrapper/Ada/wolfssl.ads | 13 ++--- 5 files changed, 68 insertions(+), 29 deletions(-) diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index a5880c9fee9..7b62e77b2ad 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -30,8 +30,10 @@ #include #include +#include + #define WOLFSSL_RSA_INSTANCES 2 -#define WOLFSSL_SHA256_INSTANCES 2 +/* SHA256 instances are now dynamically allocated (no fixed pool). */ #define WOLFSSL_AES_INSTANCES 2 #define WOLFSSL_RNG_INSTANCES 2 /* These functions give access to the integer values of the enumeration @@ -58,8 +60,8 @@ extern int get_wolfssl_filetype_default(void); extern int get_wolfssl_rsa_instances (void); extern void* ada_new_rsa (int index); -extern void *ada_new_sha256 (int index); -extern int get_wolfssl_sha256_instances(void); +extern void *ada_new_sha256 (void); +extern void ada_free_sha256 (void* sha256); extern void* ada_new_aes (int index); extern int get_wolfssl_aes_instances(void); @@ -151,17 +153,18 @@ extern void* ada_new_rsa (int index) return &preAllocatedRSAKeys[index]; } -wc_Sha256 preAllocatedSHA256[WOLFSSL_SHA256_INSTANCES]; - -extern void* ada_new_sha256 (int index) +extern void* ada_new_sha256 (void) { - return &preAllocatedSHA256[index]; + return malloc(sizeof(wc_Sha256)); } -extern int get_wolfssl_sha256_instances(void) { - return WOLFSSL_SHA256_INSTANCES; +extern void ada_free_sha256 (void* sha256) +{ + free(sha256); } + + Aes preAllocatedAes[WOLFSSL_AES_INSTANCES]; extern void* ada_new_aes (int index) diff --git a/wrapper/Ada/sha256_main.adb b/wrapper/Ada/sha256_main.adb index 355109d9045..ac6f90bf7f9 100644 --- a/wrapper/Ada/sha256_main.adb +++ b/wrapper/Ada/sha256_main.adb @@ -20,7 +20,7 @@ procedure SHA256_Main is R : Integer; S : WolfSSL.SHA256_As_String; begin - WolfSSL.Create_SHA256 (Index => 1, SHA256 => SHA256, Result => R); + WolfSSL.Create_SHA256 (SHA256 => SHA256, Result => R); if R /= 0 then Put ("SHA256 instance creation failed"); New_Line; @@ -42,6 +42,7 @@ begin else Put ("Finalization of SHA256 instance failed"); New_Line; - return; end if; + + WolfSSL.Free_SHA256 (SHA256 => SHA256); end SHA256_Main; diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.adb b/wrapper/Ada/tests/src/sha256_bindings_tests.adb index 10f540e1a54..bc674e0b443 100644 --- a/wrapper/Ada/tests/src/sha256_bindings_tests.adb +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.adb @@ -73,8 +73,8 @@ package body SHA256_Bindings_Tests is SHA256 : WolfSSL.SHA256_Type; R : Integer; begin - -- Follow the example in `sha256_main.adb` (Index => 1). - WolfSSL.Create_SHA256 (Index => 1, SHA256 => SHA256, Result => R); + -- SHA256 instances are dynamically allocated; no index is required. + WolfSSL.Create_SHA256 (SHA256 => SHA256, Result => R); if R /= 0 then Result := R; return; @@ -83,6 +83,7 @@ package body SHA256_Bindings_Tests is WolfSSL.Update_SHA256 (SHA256 => SHA256, Byte => Input, Result => R); if R /= 0 then Result := R; + WolfSSL.Free_SHA256 (SHA256 => SHA256); return; end if; @@ -93,6 +94,8 @@ package body SHA256_Bindings_Tests is Result => R); Result := R; + + WolfSSL.Free_SHA256 (SHA256 => SHA256); end Compute_SHA256; ---------------------------------------------------------------------------- diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index 1c8b65c7448..f5599bc07da 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -1244,22 +1244,57 @@ package body WolfSSL is return SHA256 /= null; end Is_Valid; - function Ada_New_SHA256 (Index : SHA256_Index) - return SHA256_Type with + function Ada_New_SHA256 return SHA256_Type with Convention => C, External_Name => "ada_new_sha256", Import => True; - procedure Create_SHA256 (Index : SHA256_Index; - SHA256 : in out SHA256_Type; + procedure Ada_Free_SHA256 (SHA256 : in SHA256_Type) with + Convention => C, + External_Name => "ada_free_sha256", + Import => True; + + procedure Free_SHA256 (SHA256 : in out SHA256_Type) is + -- Ensure any internal wolfCrypt resources are released (hardware locks, + -- etc.) before releasing the object storage itself. + procedure WC_Sha256_Free (SHA256 : not null SHA256_Type) with + Convention => C, + External_Name => "wc_Sha256Free", + Import => True; + begin + if SHA256 = null then + return; + end if; + + WC_Sha256_Free (SHA256); + Ada_Free_SHA256 (SHA256); + + -- Prevent accidental double-free and make Is_Valid return False. + SHA256 := null; + end Free_SHA256; + + procedure Create_SHA256 (SHA256 : in out SHA256_Type; Result : out Integer) is begin declare R : int; begin - SHA256 := Ada_New_SHA256 (Index); + SHA256 := Ada_New_SHA256; + + if SHA256 = null then + Result := Exception_Error; + return; + end if; + R := Init_SHA256 (SHA256); Result := Integer (R); + + if Result /= 0 then + -- Avoid leaking the dynamically allocated SHA256 on init failure. + -- Also clear the handle to prevent accidental double-free by caller. + Ada_Free_SHA256 (SHA256); + SHA256 := null; + end if; end; exception when others => @@ -1478,10 +1513,7 @@ package body WolfSSL is External_Name => "get_wolfssl_rsa_instances", Import => True; - function Get_WolfSSL_SHA256_Instances return int with - Convention => C, - External_Name => "get_wolfssl_sha256_instances", - Import => True; + function Get_WolfSSL_AES_Instances return int with Convention => C, @@ -1490,6 +1522,5 @@ package body WolfSSL is begin pragma Assert (RSA_INSTANCES = Get_WolfSSL_RSA_Instances); - pragma Assert (SHA256_INSTANCES = Get_WolfSSL_SHA256_Instances); pragma Assert (AES_INSTANCES = Get_WolfSSL_AES_Instances); end WolfSSL; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 367fa2b493f..52c5bdac249 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -618,21 +618,22 @@ package WolfSSL with SPARK_Mode is Pre => Is_Valid (RSA); -- This functions provides private RSA decryption. - SHA256_INSTANCES : constant := 2; - type SHA256_Index is range 0 .. SHA256_INSTANCES - 1; - type SHA256_Type is limited private; function Is_Valid (SHA256 : SHA256_Type) return Boolean; -- Indicates if the SHA256 has successfully been initialized. - procedure Create_SHA256 (Index : SHA256_Index; - SHA256 : in out SHA256_Type; + procedure Create_SHA256 (SHA256 : in out SHA256_Type; Result : out Integer) with Pre => not Is_Valid (SHA256), Post => (if Result = 0 then Is_Valid (SHA256)); -- If successful Result = 0. - + + procedure Free_SHA256 (SHA256 : in out SHA256_Type) with + Pre => Is_Valid (SHA256); + -- Frees resources associated with SHA256 and releases the underlying C object. + -- If successful Result = 0. + procedure Update_SHA256 (SHA256 : in out SHA256_Type; Byte : Byte_Array; Result : out Integer) with From b303106ad697a32853fbb4bfff48bf184d7eccb1 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 15:40:51 +0100 Subject: [PATCH 19/51] Ada: allocate RNG with wc_rng_new and add Free_RNG --- wrapper/Ada/ada_binding.c | 19 ++++----- wrapper/Ada/aes_verify_main.adb | 10 +++-- wrapper/Ada/rsa_verify_main.adb | 6 ++- .../tests/src/rsa_verify_bindings_tests.adb | 7 +++- wrapper/Ada/wolfssl.adb | 39 ++++++++++++++----- wrapper/Ada/wolfssl.ads | 13 +++---- 6 files changed, 62 insertions(+), 32 deletions(-) diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index 7b62e77b2ad..706b6c8ac47 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -35,7 +35,6 @@ #define WOLFSSL_RSA_INSTANCES 2 /* SHA256 instances are now dynamically allocated (no fixed pool). */ #define WOLFSSL_AES_INSTANCES 2 -#define WOLFSSL_RNG_INSTANCES 2 /* These functions give access to the integer values of the enumeration constants used in WolfSSL. These functions make it possible for the WolfSSL implementation to change the values of the constants @@ -66,8 +65,8 @@ extern void ada_free_sha256 (void* sha256); extern void* ada_new_aes (int index); extern int get_wolfssl_aes_instances(void); -extern void* ada_new_rng (int index); -extern int get_wolfssl_rng_instances(void); +extern void* ada_new_rng (void); +extern void ada_free_rng (void* rng); extern int ada_RsaSetRNG (RsaKey* key, WC_RNG* rng); extern int get_wolfssl_invalid_devid (void); @@ -181,15 +180,17 @@ extern int get_wolfssl_invalid_devid (void) return INVALID_DEVID; } -WC_RNG preAllocatedRNG[WOLFSSL_RNG_INSTANCES]; - -extern void* ada_new_rng (int index) +extern void* ada_new_rng (void) { - return &preAllocatedRNG[index]; + /* Allocate and initialize a WC_RNG using wolfCrypt's allocator. + * Per request: pass NULL and 0 to wc_rng_new (nonce, nonceSz). + */ + return (void*)wc_rng_new(NULL, 0, NULL); } -extern int get_wolfssl_rng_instances(void) { - return WOLFSSL_RNG_INSTANCES; +extern void ada_free_rng (void* rng) +{ + wc_rng_free((WC_RNG*)rng); } extern int ada_RsaSetRNG(RsaKey* key, WC_RNG* rng) diff --git a/wrapper/Ada/aes_verify_main.adb b/wrapper/Ada/aes_verify_main.adb index 0cbb530f886..41082476926 100644 --- a/wrapper/Ada/aes_verify_main.adb +++ b/wrapper/Ada/aes_verify_main.adb @@ -35,8 +35,7 @@ procedure AES_Verify_Main is R : Integer; Pad : Integer := 3; begin - WolfSSL.Create_RNG (Index => 0, - Key => RNG, + WolfSSL.Create_RNG (Key => RNG, Result => R); if R /= 0 then Put ("Attaining RNG key instance failed"); @@ -50,6 +49,7 @@ begin if R /= 0 then Put ("Generating random salt"); New_Line; + WolfSSL.Free_RNG (Key => RNG); return; end if; @@ -66,6 +66,7 @@ begin if R /= 0 then Put ("Attaining AES key instance failed"); New_Line; + WolfSSL.Free_RNG (Key => RNG); return; end if; @@ -79,6 +80,9 @@ begin -- if R /= 0 then -- Put ("Attaining AES key instance failed"); -- New_Line; + -- WolfSSL.Free_RNG (Key => RNG); -- return; - -- end if; + -- end if; + + WolfSSL.Free_RNG (Key => RNG); end AES_Verify_Main; diff --git a/wrapper/Ada/rsa_verify_main.adb b/wrapper/Ada/rsa_verify_main.adb index e04b6617f82..ca7aa59d3b2 100644 --- a/wrapper/Ada/rsa_verify_main.adb +++ b/wrapper/Ada/rsa_verify_main.adb @@ -363,8 +363,7 @@ procedure Rsa_Verify_Main is RSA_Decrypt_Key : WolfSSL.RSA_Key_Type; Index : WolfSSL.Byte_Index; begin - WolfSSL.Create_RNG (Index => 0, - Key => RNG, + WolfSSL.Create_RNG (Key => RNG, Result => R); if R /= 0 then Put ("Attaining RNG key instance failed"); @@ -488,4 +487,7 @@ begin Put ("Failed to encrypt and decrypt original AES key."); New_Line; end if; + -- Release RNG resources before exiting. + WolfSSL.Free_RNG (Key => RNG); + end Rsa_Verify_Main; diff --git a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb index b3ffac1b111..3cf50126abb 100644 --- a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb +++ b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb @@ -344,8 +344,7 @@ package body RSA_Verify_Bindings_Tests is Index : WolfSSL.Byte_Index; R : Integer; begin - WolfSSL.Create_RNG (Index => 0, - Key => RNG, + WolfSSL.Create_RNG (Key => RNG, Result => R); AUnit.Assertions.Assert (R = 0, "Create_RNG failed, Result =" & Integer'Image (R)); @@ -437,6 +436,10 @@ package body RSA_Verify_Bindings_Tests is AUnit.Assertions.Assert (Decrypted (1 .. 32) = Original_AES_Key, "RSA decrypt result does not equal original key"); + + -- Ensure RNG resources are released (RNG is now dynamically allocated). + -- Must be done after all operations that use RNG / depend on it. + WolfSSL.Free_RNG (Key => RNG); end Test_RSA_Sign_Verify_And_Encrypt_Decrypt; package Caller is new AUnit.Test_Caller (Fixture); diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index f5599bc07da..a90cc7e0c2a 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -824,28 +824,49 @@ package body WolfSSL is return Key /= null; end Is_Valid; - function Ada_New_RNG (Index : int) - return RNG_Key_Type with + function Ada_New_RNG return RNG_Key_Type with Convention => C, External_Name => "ada_new_rng", Import => True; - function Init_RNG_Key (Key : not null RNG_Key_Type) return int with + procedure Ada_Free_RNG (Key : in RNG_Key_Type) with Convention => C, - External_Name => "wc_InitRng", + External_Name => "ada_free_rng", Import => True; - procedure Create_RNG (Index : RNG_Key_Index; - Key : in out RNG_Key_Type; + + + procedure Free_RNG (Key : in out RNG_Key_Type) is + begin + if Key = null then + return; + end if; + + -- wc_rng_free() already calls wc_FreeRng() internally. + Ada_Free_RNG (Key); + + -- Prevent accidental double-free and make Is_Valid return False. + Key := null; + end Free_RNG; + + procedure Create_RNG (Key : in out RNG_Key_Type; Result : out Integer) is begin Result := -121212; declare R : int; begin - Key := Ada_New_RNG (int (Index)); - R := Init_RNG_Key (Key); - Result := Integer (R); + -- Allocate RNG using the C wrapper, which internally calls + -- wc_rng_new(NULL, 0, NULL) as required. + Key := Ada_New_RNG; + + if Key = null then + Result := Exception_Error; + return; + end if; + + -- wc_rng_new() already calls wc_InitRng() internally, so no extra init. + Result := 0; end; exception when others => diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 52c5bdac249..5663fc39392 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -500,21 +500,20 @@ package WolfSSL with SPARK_Mode is -- Returns the value of the defined MAX_ERROR_SZ integer -- in wolfssl/wolfcrypt/error.h. - RNG_INSTANCES : constant := 2; - - type RNG_Key_Index is range 0 .. RNG_INSTANCES - 1; - type RNG_Key_Type is limited private; function Is_Valid (Key : RNG_Key_Type) return Boolean; -- Indicates if the RSA has successfully been initialized. - procedure Create_RNG (Index : RNG_Key_Index; - Key : in out RNG_Key_Type; + procedure Create_RNG (Key : in out RNG_Key_Type; Result : out Integer) with Pre => not Is_Valid (Key), Post => (if Result = 0 then Is_Valid (Key)); - -- If successful Result = 0. + -- If successful Result = 0. + + procedure Free_RNG (Key : in out RNG_Key_Type) with + Pre => Is_Valid (Key); + -- Frees resources associated with RNG and releases the underlying C object. procedure RNG_Generate_Block (RNG : RNG_Key_Type; Output : out Byte_Array; From ae1d7439622ec8c530e4c0d2705ff1b1505fe1ef Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 15:48:31 +0100 Subject: [PATCH 20/51] Ada: allocate RSA with wc_NewRsaKey and add Free_RSA --- wrapper/Ada/ada_binding.c | 21 ++++---- wrapper/Ada/rsa_verify_main.adb | 39 +++++++++++--- .../tests/src/rsa_verify_bindings_tests.adb | 12 +++-- wrapper/Ada/wolfssl.adb | 53 ++++++++++++------- wrapper/Ada/wolfssl.ads | 11 ++-- 5 files changed, 90 insertions(+), 46 deletions(-) diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index 706b6c8ac47..744cc79e27f 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -32,7 +32,7 @@ #include -#define WOLFSSL_RSA_INSTANCES 2 +/* RSA instances are now dynamically allocated (no fixed pool). */ /* SHA256 instances are now dynamically allocated (no fixed pool). */ #define WOLFSSL_AES_INSTANCES 2 /* These functions give access to the integer values of the enumeration @@ -56,8 +56,8 @@ extern int get_wolfssl_filetype_asn1(void); extern int get_wolfssl_filetype_pem(void); extern int get_wolfssl_filetype_default(void); -extern int get_wolfssl_rsa_instances (void); -extern void* ada_new_rsa (int index); +extern void* ada_new_rsa (void); +extern void ada_free_rsa (void* key); extern void *ada_new_sha256 (void); extern void ada_free_sha256 (void* sha256); @@ -141,15 +141,18 @@ extern int get_wolfssl_filetype_default(void) { return WOLFSSL_FILETYPE_DEFAULT; } -extern int get_wolfssl_rsa_instances(void) { - return WOLFSSL_RSA_INSTANCES; -} -RsaKey preAllocatedRSAKeys[WOLFSSL_RSA_INSTANCES]; -extern void* ada_new_rsa (int index) +extern void* ada_new_rsa (void) +{ + /* Allocate and initialize an RSA key using wolfCrypt's constructor. */ + return (void*)wc_NewRsaKey(NULL, INVALID_DEVID, NULL); +} + +extern void ada_free_rsa (void* key) { - return &preAllocatedRSAKeys[index]; + /* Delete RSA key and release its memory. */ + wc_DeleteRsaKey((RsaKey*)key, NULL); } extern void* ada_new_sha256 (void) diff --git a/wrapper/Ada/rsa_verify_main.adb b/wrapper/Ada/rsa_verify_main.adb index ca7aa59d3b2..73b0285102f 100644 --- a/wrapper/Ada/rsa_verify_main.adb +++ b/wrapper/Ada/rsa_verify_main.adb @@ -362,21 +362,39 @@ procedure Rsa_Verify_Main is RSA_Encrypt_Key : WolfSSL.RSA_Key_Type; RSA_Decrypt_Key : WolfSSL.RSA_Key_Type; Index : WolfSSL.Byte_Index; + + -- Release any resources that may have been acquired so far. + -- Safe to call multiple times and safe when handles are null. + procedure Cleanup is + begin + if WolfSSL.Is_Valid (RSA_Encrypt_Key) then + WolfSSL.Free_RSA (Key => RSA_Encrypt_Key); + end if; + + if WolfSSL.Is_Valid (RSA_Decrypt_Key) then + WolfSSL.Free_RSA (Key => RSA_Decrypt_Key); + end if; + + if WolfSSL.Is_Valid (RNG) then + WolfSSL.Free_RNG (Key => RNG); + end if; + end Cleanup; begin WolfSSL.Create_RNG (Key => RNG, Result => R); if R /= 0 then Put ("Attaining RNG key instance failed"); New_Line; + Cleanup; return; end if; - WolfSSL.Create_RSA (Index => 0, - Key => RSA_Encrypt_Key, + WolfSSL.Create_RSA (Key => RSA_Encrypt_Key, Result => R); if R /= 0 then Put ("Attaining RSA key instance failed"); New_Line; + Cleanup; return; end if; @@ -386,6 +404,7 @@ begin if R /= 0 then Put ("Associating RSA key with random number generator failed"); New_Line; + Cleanup; return; end if; @@ -399,6 +418,7 @@ begin Put ("Loading private RSA key failed with error code "); Put (R); New_Line; + Cleanup; return; end if; @@ -411,15 +431,16 @@ begin Put ("Creating digital signature using RSA private key failed"); Put (R); New_Line; + Cleanup; return; end if; - WolfSSL.Create_RSA (Index => 1, - Key => RSA_Decrypt_Key, + WolfSSL.Create_RSA (Key => RSA_Decrypt_Key, Result => R); if R /= 0 then Put ("Attaining RSA key instance failed"); New_Line; + Cleanup; return; end if; @@ -433,6 +454,7 @@ begin Put ("Loading public RSA key failed with DER encoded key"); Put (R); New_Line; + Cleanup; return; end if; @@ -444,6 +466,7 @@ begin Put ("Verify digital signature failed"); Put (R); New_Line; + Cleanup; return; end if; Put ("Successful verification of RSA based digital signature."); @@ -459,6 +482,7 @@ begin Put ("Failed to encrypt the original AES key"); Put (R); New_Line; + Cleanup; return; end if; @@ -471,12 +495,14 @@ begin Put ("Failed to decrypt the encrypted original AES key"); Put (R); New_Line; + Cleanup; return; end if; if Integer (Index) /= 32 then Put ("Decryption of the encrypted original AES key, wrong size"); New_Line; + Cleanup; return; end if; @@ -486,8 +512,7 @@ begin else Put ("Failed to encrypt and decrypt original AES key."); New_Line; - end if; - -- Release RNG resources before exiting. - WolfSSL.Free_RNG (Key => RNG); + end if; + Cleanup; end Rsa_Verify_Main; diff --git a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb index 3cf50126abb..48e4218d742 100644 --- a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb +++ b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb @@ -349,8 +349,7 @@ package body RSA_Verify_Bindings_Tests is AUnit.Assertions.Assert (R = 0, "Create_RNG failed, Result =" & Integer'Image (R)); - WolfSSL.Create_RSA (Index => 0, - Key => RSA_Encrypt_Key, + WolfSSL.Create_RSA (Key => RSA_Encrypt_Key, Result => R); AUnit.Assertions.Assert (R = 0, "Create_RSA (private) failed, Result =" & Integer'Image (R)); @@ -379,8 +378,7 @@ package body RSA_Verify_Bindings_Tests is "Rsa_SSL_Sign failed, Result =" & Integer'Image (R)); - WolfSSL.Create_RSA (Index => 1, - Key => RSA_Decrypt_Key, + WolfSSL.Create_RSA (Key => RSA_Decrypt_Key, Result => R); AUnit.Assertions.Assert (R = 0, "Create_RSA (public) failed, Result =" & Integer'Image (R)); @@ -389,7 +387,7 @@ package body RSA_Verify_Bindings_Tests is WolfSSL.Rsa_Public_Key_Decode (Input => Rsa_Public_Key_2048, Index => Index, Key => RSA_Decrypt_Key, - Size => Rsa_Public_Key_2048'Length, + Size => Rsa_Public_Key_2048'Length, Result => R); AUnit.Assertions.Assert (R = 0, "Rsa_Public_Key_Decode failed, Result =" & Integer'Image (R)); @@ -437,6 +435,10 @@ package body RSA_Verify_Bindings_Tests is AUnit.Assertions.Assert (Decrypted (1 .. 32) = Original_AES_Key, "RSA decrypt result does not equal original key"); + -- Ensure RSA key resources are released (RSA is now dynamically allocated). + WolfSSL.Free_RSA (Key => RSA_Encrypt_Key); + WolfSSL.Free_RSA (Key => RSA_Decrypt_Key); + -- Ensure RNG resources are released (RNG is now dynamically allocated). -- Must be done after all operations that use RNG / depend on it. WolfSSL.Free_RNG (Key => RNG); diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index a90cc7e0c2a..a5d973b2fcb 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -1027,28 +1027,51 @@ package body WolfSSL is return Key /= null; end Is_Valid; - function Ada_New_RSA (Index : int) - return RSA_Key_Type with + function Ada_New_RSA return RSA_Key_Type with Convention => C, External_Name => "ada_new_rsa", Import => True; - function Init_RSA_Key (Key : not null RSA_Key_Type; - Heap : access Byte_Type) return int with + procedure Ada_Free_RSA (Key : in RSA_Key_Type) with Convention => C, - External_Name => "wc_InitRsaKey", + External_Name => "ada_free_rsa", Import => True; - procedure Create_RSA (Index : RSA_Key_Index; - Key : in out RSA_Key_Type; + procedure Free_RSA (Key : in out RSA_Key_Type) is + begin + if Key = null then + return; + end if; + + -- wc_DeleteRsaKey() already calls wc_FreeRsaKey() internally. + Ada_Free_RSA (Key); + + -- Prevent accidental double-free and make Is_Valid return False. + Key := null; + end Free_RSA; + + procedure Create_RSA (Key : in out RSA_Key_Type; Result : out Integer) is - R : int; begin - Key := Ada_New_RSA (int (Index)); - R := Init_RSA_Key (Key, null); - Result := Integer (R); + -- Allocate and initialize RSA key using the C wrapper. + -- The wrapper uses wc_NewRsaKey() and returns NULL on failure. + Key := Ada_New_RSA; + + if Key = null then + Result := Exception_Error; + return; + end if; + + -- wc_NewRsaKey() already calls wc_InitRsaKey_ex() internally. + Result := 0; + exception when others => + -- Avoid leaking the dynamically allocated RSA key on failure. + if Key /= null then + Ada_Free_RSA (Key); + Key := null; + end if; Result := Exception_Error; end Create_RSA; @@ -1529,19 +1552,11 @@ package body WolfSSL is Result := Exception_Error; end AES_Free; - function Get_WolfSSL_RSA_Instances return int with - Convention => C, - External_Name => "get_wolfssl_rsa_instances", - Import => True; - - - function Get_WolfSSL_AES_Instances return int with Convention => C, External_Name => "get_wolfssl_aes_instances", Import => True; begin - pragma Assert (RSA_INSTANCES = Get_WolfSSL_RSA_Instances); pragma Assert (AES_INSTANCES = Get_WolfSSL_AES_Instances); end WolfSSL; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 5663fc39392..91ba6c4f769 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -531,21 +531,20 @@ package WolfSSL with SPARK_Mode is HMAC : HMAC_Hash; Result : out Integer); - RSA_INSTANCES : constant := 2; - - type RSA_Key_Index is range 0 .. RSA_INSTANCES - 1; - type RSA_Key_Type is limited private; function Is_Valid (Key : RSA_Key_Type) return Boolean; -- Indicates if the RSA has successfully been initialized. - procedure Create_RSA (Index : RSA_Key_Index; - Key : in out RSA_Key_Type; + procedure Create_RSA (Key : in out RSA_Key_Type; Result : out Integer) with Pre => not Is_Valid (Key), Post => (if Result = 0 then Is_Valid (Key)); -- If successful Result = 0. + + procedure Free_RSA (Key : in out RSA_Key_Type) with + Pre => Is_Valid (Key); + -- Frees resources associated with RSA and releases the underlying C object. procedure Rsa_Public_Key_Decode (Input : Byte_Array; Index : in out Byte_Index; From cebc4e8d634b3bb1e4fdb7620d4a3ebb6c31ac53 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 16:34:03 +0100 Subject: [PATCH 21/51] Ada: allocate AES with wc_AesNew and free with wc_AesDelete --- wrapper/Ada/ada_binding.c | 21 ++++--- wrapper/Ada/aes_verify_main.adb | 27 +++++++-- wrapper/Ada/tests/src/aes_bindings_tests.adb | 6 +- wrapper/Ada/wolfssl.adb | 61 ++++++++++---------- wrapper/Ada/wolfssl.ads | 20 +++---- 5 files changed, 74 insertions(+), 61 deletions(-) diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index 744cc79e27f..6e7e91c9bb8 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -34,7 +34,7 @@ /* RSA instances are now dynamically allocated (no fixed pool). */ /* SHA256 instances are now dynamically allocated (no fixed pool). */ -#define WOLFSSL_AES_INSTANCES 2 +/* AES instances are now dynamically allocated (no fixed pool). */ /* These functions give access to the integer values of the enumeration constants used in WolfSSL. These functions make it possible for the WolfSSL implementation to change the values of the constants @@ -62,8 +62,8 @@ extern void ada_free_rsa (void* key); extern void *ada_new_sha256 (void); extern void ada_free_sha256 (void* sha256); -extern void* ada_new_aes (int index); -extern int get_wolfssl_aes_instances(void); +extern void* ada_new_aes (int devId); +extern void ada_free_aes (void* aes); extern void* ada_new_rng (void); extern void ada_free_rng (void* rng); @@ -141,8 +141,6 @@ extern int get_wolfssl_filetype_default(void) { return WOLFSSL_FILETYPE_DEFAULT; } - - extern void* ada_new_rsa (void) { /* Allocate and initialize an RSA key using wolfCrypt's constructor. */ @@ -167,15 +165,16 @@ extern void ada_free_sha256 (void* sha256) -Aes preAllocatedAes[WOLFSSL_AES_INSTANCES]; - -extern void* ada_new_aes (int index) +extern void* ada_new_aes (int devId) { - return &preAllocatedAes[index]; + /* Allocate and initialize an AES object using wolfCrypt's constructor. */ + return (void*)wc_AesNew(NULL, devId, NULL); } -extern int get_wolfssl_aes_instances(void) { - return WOLFSSL_AES_INSTANCES; +extern void ada_free_aes (void* aes) +{ + /* Delete AES object and release its memory. */ + wc_AesDelete((Aes*)aes, NULL); } extern int get_wolfssl_invalid_devid (void) diff --git a/wrapper/Ada/aes_verify_main.adb b/wrapper/Ada/aes_verify_main.adb index 41082476926..582a9f35d65 100644 --- a/wrapper/Ada/aes_verify_main.adb +++ b/wrapper/Ada/aes_verify_main.adb @@ -34,12 +34,26 @@ procedure AES_Verify_Main is AES : WolfSSL.AES_Type; R : Integer; Pad : Integer := 3; + + procedure Cleanup is + RR : Integer := 0; + begin + if WolfSSL.Is_Valid (AES) then + WolfSSL.AES_Free (AES => AES, + Result => RR); + end if; + + if WolfSSL.Is_Valid (RNG) then + WolfSSL.Free_RNG (Key => RNG); + end if; + end Cleanup; begin WolfSSL.Create_RNG (Key => RNG, Result => R); if R /= 0 then Put ("Attaining RNG key instance failed"); New_Line; + Cleanup; return; end if; @@ -49,7 +63,7 @@ begin if R /= 0 then Put ("Generating random salt"); New_Line; - WolfSSL.Free_RNG (Key => RNG); + Cleanup; return; end if; @@ -59,14 +73,15 @@ begin Salt (1) := To_C (1); end if; - WolfSSL.Create_AES (Index => 0, - Device => WolfSSL.Invalid_Device, + -- Create_AES signature no longer requires Index when AES objects are + -- dynamically allocated. + WolfSSL.Create_AES (Device => WolfSSL.Invalid_Device, AES => AES, Result => R); if R /= 0 then Put ("Attaining AES key instance failed"); New_Line; - WolfSSL.Free_RNG (Key => RNG); + Cleanup; return; end if; @@ -80,9 +95,9 @@ begin -- if R /= 0 then -- Put ("Attaining AES key instance failed"); -- New_Line; - -- WolfSSL.Free_RNG (Key => RNG); + -- Cleanup; -- return; -- end if; - WolfSSL.Free_RNG (Key => RNG); + Cleanup; end AES_Verify_Main; diff --git a/wrapper/Ada/tests/src/aes_bindings_tests.adb b/wrapper/Ada/tests/src/aes_bindings_tests.adb index fe094917d8d..f52ecc9a58e 100644 --- a/wrapper/Ada/tests/src/aes_bindings_tests.adb +++ b/wrapper/Ada/tests/src/aes_bindings_tests.adb @@ -46,8 +46,7 @@ package body AES_Bindings_Tests is IV_Enc := IV_Init; IV_Dec := IV_Init; - WolfSSL.Create_AES (Index => 0, - Device => WolfSSL.Invalid_Device, + WolfSSL.Create_AES (Device => WolfSSL.Invalid_Device, AES => AES, Result => R); Test_Support.Assert_Success (R, "Create_AES"); @@ -115,8 +114,7 @@ package body AES_Bindings_Tests is AES : WolfSSL.AES_Type; R : Integer; begin - WolfSSL.Create_AES (Index => 1, - Device => WolfSSL.Invalid_Device, + WolfSSL.Create_AES (Device => WolfSSL.Invalid_Device, AES => AES, Result => R); Test_Support.Assert_Success (R, "Create_AES"); diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index a5d973b2fcb..2c68cf4797b 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -1402,33 +1402,44 @@ package body WolfSSL is return AES /= null; end Is_Valid; - function Ada_New_AES (Index : AES_Index) + function Ada_New_AES (Device : int) return AES_Type with Convention => C, External_Name => "ada_new_aes", Import => True; - function AES_Init (AES : not null AES_Type; - Heap : access Byte_Type; - Device : int) return int with + procedure Ada_Free_AES (AES : in AES_Type) with Convention => C, - External_Name => "wc_AesInit", + External_Name => "ada_free_aes", Import => True; - procedure Create_AES (Index : AES_Index; - Device : Device_Identifier; + procedure Create_AES (Device : Device_Identifier; AES : in out AES_Type; Result : out Integer) is begin declare R : int; begin - AES := Ada_New_AES (Index); - R := AES_Init (AES, null, int (Device)); - Result := Integer (R); + -- Allocate and initialize AES using the C wrapper. + -- The wrapper is expected to call wc_AesNew(NULL, devId, &ret) and + -- return NULL on failure. + AES := Ada_New_AES (int (Device)); + + if AES = null then + Result := Exception_Error; + return; + end if; + + -- wc_AesNew() already calls wc_AesInit() internally, so no extra init. + Result := 0; end; exception when others => + -- Avoid leaking the dynamically allocated AES on failure. + if AES /= null then + Ada_Free_AES (AES); + AES := null; + end if; Result := Exception_Error; end Create_AES; @@ -1530,33 +1541,23 @@ package body WolfSSL is Result := Exception_Error; end AES_Set_Cbc_Decrypt; - function AES_Free (AES : not null AES_Type) return int with - Convention => C, - External_Name => "wc_AesFree", - Import => True; - procedure AES_Free (AES : in out AES_Type; Result : out Integer) is begin - declare - R : int; - begin - R := AES_Free (AES); - Result := Integer (R); - if Result = 0 then - AES := null; - end if; - end; + if AES = null then + Result := Exception_Error; + return; + end if; + + -- wc_AesDelete() already calls wc_AesFree() internally. + Ada_Free_AES (AES); + AES := null; + Result := 0; exception when others => Result := Exception_Error; end AES_Free; - function Get_WolfSSL_AES_Instances return int with - Convention => C, - External_Name => "get_wolfssl_aes_instances", - Import => True; - begin - pragma Assert (AES_INSTANCES = Get_WolfSSL_AES_Instances); + null; end WolfSSL; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 91ba6c4f769..1cdf3eb496f 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -653,21 +653,24 @@ package WolfSSL with SPARK_Mode is function Invalid_Device return Device_Identifier; - AES_INSTANCES : constant := 2; - type AES_Index is range 0 .. AES_INSTANCES - 1; - type AES_Type is limited private; function Is_Valid (AES : AES_Type) return Boolean; -- Indicates if the AES has successfully been initialized. - procedure Create_AES (Index : AES_Index; - Device : Device_Identifier; + procedure Create_AES (Device : Device_Identifier; AES : in out AES_Type; Result : out Integer) with - Pre => not Is_Valid (AES); + Pre => not Is_Valid (AES), + Post => (if Result = 0 then Is_Valid (AES)); -- If successful Is_Valid (AES) = True, and Result = 0. + procedure AES_Free (AES : in out AES_Type; + Result : out Integer) with + Pre => Is_Valid (AES), + Post => (if Result = 0 then not Is_Valid (AES)); + -- Frees resources associated with AES and releases the underlying C object. + procedure AES_Set_Key (AES : AES_Type; Key : Byte_Array; Length : Integer; @@ -695,10 +698,7 @@ package WolfSSL with SPARK_Mode is Result : out Integer) with Pre => Is_Valid (AES); - procedure AES_Free (AES : in out AES_Type; - Result : out Integer) with - Pre => Is_Valid (AES), - Post => (if Result = 0 then not Is_Valid (AES)); + -- (Removed duplicate AES_Free declaration) private pragma SPARK_Mode (Off); From 52359def43e4b13f714ae6958c3692d6d9bba367 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 16:44:59 +0100 Subject: [PATCH 22/51] Ada tests: fix warnings (redundant with, style spacing) --- wrapper/Ada/tests/src/aes_bindings_tests.adb | 15 +++++++-------- wrapper/Ada/tests/src/support/test_support.adb | 8 +++----- wrapper/Ada/tests/src/support/test_support.ads | 6 +++--- .../Ada/tests/src/support/tests_root_suite.adb | 2 -- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/wrapper/Ada/tests/src/aes_bindings_tests.adb b/wrapper/Ada/tests/src/aes_bindings_tests.adb index f52ecc9a58e..f9469b0b7d9 100644 --- a/wrapper/Ada/tests/src/aes_bindings_tests.adb +++ b/wrapper/Ada/tests/src/aes_bindings_tests.adb @@ -1,6 +1,5 @@ with AUnit.Assertions; with AUnit.Test_Caller; -with AUnit.Test_Suites; with WolfSSL; @@ -17,7 +16,7 @@ package body AES_Bindings_Tests is AES_Decrypt_Dir : constant Integer := 1; ---------------------------------------------------------------------------- - -- Tests + -- Tests ---------------------------------------------------------------------------- procedure Test_AES_CBC_Roundtrip (F : in out Fixture) is @@ -93,14 +92,14 @@ package body AES_Bindings_Tests is Result => R); Test_Support.Assert_Success (R, "AES_Set_Cbc_Decrypt"); - AUnit.Assertions.Assert (Decoded = Plain, - "AES-CBC roundtrip mismatch"); + AUnit.Assertions.Assert + (Decoded = Plain, + "AES-CBC roundtrip mismatch"); WolfSSL.AES_Free (AES => AES, Result => R); - -- Some wolfCrypt builds/configurations may not support `wc_AesFree` as a - -- no-op success in all cases (or may return a non-zero code). Keep this - -- test focused on the binding contract: only require invalidation on + Test_Support.Assert_Success (R, "AES_Free"); + -- Keep this test focused on the binding contract: only require invalidation on -- successful free. if R = 0 then AUnit.Assertions.Assert (not WolfSSL.Is_Valid (AES), @@ -134,7 +133,7 @@ package body AES_Bindings_Tests is end Test_AES_Free_Invalidates; ---------------------------------------------------------------------------- - -- Suite (static suite object + elaboration-time registration) + -- Suite (static suite object + elaboration-time registration) ---------------------------------------------------------------------------- package Caller is new AUnit.Test_Caller (Fixture); diff --git a/wrapper/Ada/tests/src/support/test_support.adb b/wrapper/Ada/tests/src/support/test_support.adb index 4fbc8708ea5..5c65e646051 100644 --- a/wrapper/Ada/tests/src/support/test_support.adb +++ b/wrapper/Ada/tests/src/support/test_support.adb @@ -1,22 +1,20 @@ with AUnit.Assertions; -with WolfSSL; - package body Test_Support is ---------------------------------------------------------------------------- - -- Assertions + -- Assertions ---------------------------------------------------------------------------- procedure Assert_Success (Result : Integer; What : String) is begin AUnit.Assertions.Assert (Result = 0, - What & " failed, Result =" & Integer'Image (Result)); + What & " failed, Result = " & Integer'Image (Result)); end Assert_Success; ---------------------------------------------------------------------------- - -- Data helpers + -- Data helpers ---------------------------------------------------------------------------- function Bytes (S : String) return WolfSSL.Byte_Array is diff --git a/wrapper/Ada/tests/src/support/test_support.ads b/wrapper/Ada/tests/src/support/test_support.ads index 06b8c7c20e9..0be4f82915e 100644 --- a/wrapper/Ada/tests/src/support/test_support.ads +++ b/wrapper/Ada/tests/src/support/test_support.ads @@ -4,21 +4,21 @@ package Test_Support is -- Small helpers to reduce test boilerplate and keep data declarations concise. ----------------------------------------------------------------------------- - -- Assertions + -- Assertions ----------------------------------------------------------------------------- -- Assert that a WolfSSL binding call returned success (0). procedure Assert_Success (Result : Integer; What : String); ----------------------------------------------------------------------------- - -- Data helpers + -- Data helpers ----------------------------------------------------------------------------- -- Convert a String into a WolfSSL.Byte_Array, byte-for-byte. -- Intended for test vectors like keys/IVs/plaintext where ASCII is fine. function Bytes (S : String) return WolfSSL.Byte_Array; - -- Convert a hex string (e.g. "0A1bFF") into a Byte_Array. + -- Convert a hex string (for example "0A1bFF") into a Byte_Array. -- - Accepts both uppercase and lowercase hex. -- - Requires an even number of hex characters. function Hex_Bytes (Hex : String) return WolfSSL.Byte_Array; diff --git a/wrapper/Ada/tests/src/support/tests_root_suite.adb b/wrapper/Ada/tests/src/support/tests_root_suite.adb index 9be388f3ac3..a25320396d2 100644 --- a/wrapper/Ada/tests/src/support/tests_root_suite.adb +++ b/wrapper/Ada/tests/src/support/tests_root_suite.adb @@ -1,5 +1,3 @@ -with AUnit.Test_Suites; - with AES_Bindings_Tests; with RSA_Verify_Bindings_Tests; with SHA256_Bindings_Tests; From 05e9549933bf9ffb776fd417713a56e001203648 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 18:04:25 +0100 Subject: [PATCH 23/51] Ada: document test running with valgrind and using gprbuild/gprclean via alr exec --- wrapper/Ada/README.md | 8 ++++++++ wrapper/Ada/tests/README.md | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 wrapper/Ada/tests/README.md diff --git a/wrapper/Ada/README.md b/wrapper/Ada/README.md index ac98f71aee4..ba0829deb0a 100644 --- a/wrapper/Ada/README.md +++ b/wrapper/Ada/README.md @@ -91,6 +91,14 @@ cd obj/ ./tls_client_main 127.0.0.1 ``` +If you are using Alire, you can access `gprclean` and `gprbuild` through Alire's environment: + +```sh +alr exec -- gprclean +alr exec -- gprbuild default.gpr +alr exec -- gprbuild examples.gpr +``` + On Windows, build the executables with: ```sh gprbuild -XOS=Windows default.gpr diff --git a/wrapper/Ada/tests/README.md b/wrapper/Ada/tests/README.md new file mode 100644 index 00000000000..e6df50741ef --- /dev/null +++ b/wrapper/Ada/tests/README.md @@ -0,0 +1,21 @@ +# ADA Wrapper Tests + +This directory contains tests for the ADA wrapper. + +## Running the Tests + +To run the tests using [alire](https://alire.ada.dev/), execute the following command from this directory: + +``` +alr run +``` + +This will build and run all ADA wrapper tests. + +## Running the Tests with Valgrind + +After building the tests with `alr build`, you can run them with valgrind using the provided suppressions file: + +``` +valgrind --track-origins=yes --leak-check=full --suppressions=valgrind.supp ./bin/tests +``` From 0cd0210df610c6b29b25ded09ef47f90a6fd0465 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 23 Dec 2025 21:11:46 +0100 Subject: [PATCH 24/51] CI: add Ada AUnit tests --- .github/workflows/ada.yml | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ada.yml b/.github/workflows/ada.yml index 9691e425bce..dd80f000786 100644 --- a/.github/workflows/ada.yml +++ b/.github/workflows/ada.yml @@ -15,20 +15,26 @@ jobs: steps: - uses: actions/checkout@master - - name: Install gnat + - name: Install alire + uses: alire-project/setup-alire@v5 + + - name: Build wolfssl Ada + working-directory: ./wrapper/Ada run: | - sudo apt-get update - sudo apt-get install -y gnat gprbuild + alr exec -- gprbuild -j$(nproc) default.gpr + alr exec -- gprbuild -j$(nproc) examples.gpr - - name: Checkout wolfssl - uses: actions/checkout@master - with: - repository: wolfssl/wolfssl - path: wolfssl + - name: Run Ada wrapper tests (alire) + working-directory: ./wrapper/Ada + run: | + alr install + cd tests + alr run - - name: Build wolfssl Ada - working-directory: ./wolfssl/wrapper/Ada + - name: Run Ada wrapper tests (valgrind) + working-directory: ./wrapper/Ada/tests run: | - mkdir obj - gprbuild default.gpr - gprbuild examples.gpr + sudo apt-get update + sudo apt-get install -y valgrind + valgrind --leak-check=full --error-exitcode=1 \ + --suppressions=valgrind.supp ./bin/tests From bc77f7cd2dcbba8cf4c9f8806b46f5eaae90c511 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 29 Dec 2025 17:49:34 +0100 Subject: [PATCH 25/51] Ada: allow older aunit --- wrapper/Ada/tests/alire.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrapper/Ada/tests/alire.toml b/wrapper/Ada/tests/alire.toml index 4ac485eb8f9..f408f657fb8 100644 --- a/wrapper/Ada/tests/alire.toml +++ b/wrapper/Ada/tests/alire.toml @@ -12,4 +12,4 @@ tags = ["ssl", "tests"] executables = ["tests"] [[depends-on]] -aunit = "^26.0.0" +aunit = "^24.0.0" From 2c60c9672f149ce21fc9215ba9ff80dfb6619f1a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 29 Dec 2025 20:15:37 +0100 Subject: [PATCH 26/51] Ada: add Post conditions for Free_* --- wrapper/Ada/wolfssl.ads | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 1cdf3eb496f..958ed06ad2a 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -320,7 +320,8 @@ package WolfSSL with SPARK_Mode is -- be freed when the associated SSL object is freed. procedure Free_Arrays (Ssl : WolfSSL_Type) with - Pre => Is_Valid (Ssl); + Pre => Is_Valid (Ssl), + Post => not Is_Valid (Ssl); -- Normally, at the end of the SSL handshake, wolfSSL frees temporary -- arrays. If Keep_Arrays(..) has been called before the handshake, -- wolfSSL will not free temporary arrays. This function explicitly @@ -512,7 +513,8 @@ package WolfSSL with SPARK_Mode is -- If successful Result = 0. procedure Free_RNG (Key : in out RNG_Key_Type) with - Pre => Is_Valid (Key); + Pre => Is_Valid (Key), + Post => not Is_Valid (Key); -- Frees resources associated with RNG and releases the underlying C object. procedure RNG_Generate_Block (RNG : RNG_Key_Type; @@ -543,7 +545,8 @@ package WolfSSL with SPARK_Mode is -- If successful Result = 0. procedure Free_RSA (Key : in out RSA_Key_Type) with - Pre => Is_Valid (Key); + Pre => Is_Valid (Key), + Post => not Is_Valid (Key); -- Frees resources associated with RSA and releases the underlying C object. procedure Rsa_Public_Key_Decode (Input : Byte_Array; @@ -628,7 +631,8 @@ package WolfSSL with SPARK_Mode is -- If successful Result = 0. procedure Free_SHA256 (SHA256 : in out SHA256_Type) with - Pre => Is_Valid (SHA256); + Pre => Is_Valid (SHA256), + Post => not Is_Valid (SHA256); -- Frees resources associated with SHA256 and releases the underlying C object. -- If successful Result = 0. From f341065dc9c881342613a4c89cecf7efabf20e95 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 30 Dec 2025 10:08:16 +0100 Subject: [PATCH 27/51] Ada: document possible source of dependency error --- wrapper/Ada/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wrapper/Ada/README.md b/wrapper/Ada/README.md index ba0829deb0a..a35dfd3ccaa 100644 --- a/wrapper/Ada/README.md +++ b/wrapper/Ada/README.md @@ -62,6 +62,8 @@ ecosystem. The latest version is available for Windows, OSX, Linux and FreeBSD systems. It can install a complete Ada toolchain if needed, see `alr install` for more information. +**Note:** If you encounter a missing dependency error, it may be caused by the installed dependency being too old. In this case, either install a newer toolchain or decrease the required dependency version in your project. + In order to use WolfSSL in a project, just add WolfSSL as a dependency by running `alr with wolfssl` within your project's directory. From 44193d91eede6cecda941faf8dba93b73c9ae31c Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 29 Dec 2025 20:50:44 +0100 Subject: [PATCH 28/51] Ada: add GNATprove ownership annotations Ada: fix ownership predicate annotations --- wrapper/Ada/wolfssl.ads | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 958ed06ad2a..670231711e7 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -501,7 +501,8 @@ package WolfSSL with SPARK_Mode is -- Returns the value of the defined MAX_ERROR_SZ integer -- in wolfssl/wolfcrypt/error.h. - type RNG_Key_Type is limited private; + type RNG_Key_Type is limited private with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); function Is_Valid (Key : RNG_Key_Type) return Boolean; -- Indicates if the RSA has successfully been initialized. @@ -533,7 +534,8 @@ package WolfSSL with SPARK_Mode is HMAC : HMAC_Hash; Result : out Integer); - type RSA_Key_Type is limited private; + type RSA_Key_Type is limited private with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); function Is_Valid (Key : RSA_Key_Type) return Boolean; -- Indicates if the RSA has successfully been initialized. @@ -619,7 +621,8 @@ package WolfSSL with SPARK_Mode is Pre => Is_Valid (RSA); -- This functions provides private RSA decryption. - type SHA256_Type is limited private; + type SHA256_Type is limited private with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); function Is_Valid (SHA256 : SHA256_Type) return Boolean; -- Indicates if the SHA256 has successfully been initialized. @@ -657,7 +660,8 @@ package WolfSSL with SPARK_Mode is function Invalid_Device return Device_Identifier; - type AES_Type is limited private; + type AES_Type is limited private with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); function Is_Valid (AES : AES_Type) return Boolean; -- Indicates if the AES has successfully been initialized. From 04c495e2c935e4820d2fd89cdc79ef5ed70ccea1 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 30 Dec 2025 18:42:12 +0100 Subject: [PATCH 29/51] Ada: GNATprove is clean on examples.gpr GNATprove dependency added, GNATprove annotations updated, TLS server error message initialization fixed --- wrapper/Ada/alire.toml | 3 +++ wrapper/Ada/tls_client.adb | 4 ++-- wrapper/Ada/tls_client.ads | 3 ++- wrapper/Ada/tls_server.adb | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/wrapper/Ada/alire.toml b/wrapper/Ada/alire.toml index 1af7e82e5d1..4ddd4ac462e 100644 --- a/wrapper/Ada/alire.toml +++ b/wrapper/Ada/alire.toml @@ -12,3 +12,6 @@ tags = ["ssl", "tls", "embedded", "spark"] [configuration.variables] STATIC_PSK = {type = "Boolean", default = false} + +[[depends-on]] +gnatprove = "^13.2.1" diff --git a/wrapper/Ada/tls_client.adb b/wrapper/Ada/tls_client.adb index b00f49f1779..e31c969e5ea 100644 --- a/wrapper/Ada/tls_client.adb +++ b/wrapper/Ada/tls_client.adb @@ -112,7 +112,7 @@ package body Tls_Client with SPARK_Mode is procedure Put (Number : Natural) with - Always_Terminates => False + Annotate => (GNATprove, Might_Not_Return) is begin Natural_IO.Put (Item => Number, Width => 0, Base => 10); @@ -120,7 +120,7 @@ package body Tls_Client with SPARK_Mode is procedure Put (Number : Byte_Index) with - Always_Terminates => False + Annotate => (GNATprove, Might_Not_Return) is begin Natural_IO.Put (Item => Natural (Number), Width => 0, Base => 10); diff --git a/wrapper/Ada/tls_client.ads b/wrapper/Ada/tls_client.ads index 1d5525eaea8..02d286d7825 100644 --- a/wrapper/Ada/tls_client.ads +++ b/wrapper/Ada/tls_client.ads @@ -33,6 +33,7 @@ package Tls_Client with SPARK_Mode is WolfSSL.Is_Valid (Ssl) and not WolfSSL.Is_Valid (Ctx)), Post => (not Client.Exists and not WolfSSL.Is_Valid (Ssl) and not WolfSSL.Is_Valid (Ctx)), - Always_Terminates => False; + + Annotate => (GNATprove, Might_Not_Return); end Tls_Client; diff --git a/wrapper/Ada/tls_server.adb b/wrapper/Ada/tls_server.adb index 27fb6d40fbd..498ce26a5d7 100644 --- a/wrapper/Ada/tls_server.adb +++ b/wrapper/Ada/tls_server.adb @@ -349,7 +349,7 @@ package body Tls_Server with SPARK_Mode is if not WolfSSL.Is_Valid (Ssl) then Put_Line ("ERROR: failed to create WOLFSSL object."); declare - Error_Message : WolfSSL.Error_Message; + Error_Message : WolfSSL.Error_Message := (Text => (others => ' '), Last => 0); begin WolfSSL.Error (WolfSSL.Get_Error (Ssl, Result), Message => Error_Message); From 3794d7050bee8da351bd1c422197ba27310f1a80 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 13:51:00 +0100 Subject: [PATCH 30/51] Ada: move examples to sub-directory --- wrapper/Ada/examples/.gitignore | 4 ++++ wrapper/Ada/examples/alire.toml | 12 ++++++++++++ wrapper/Ada/{ => examples}/examples.gpr | 0 wrapper/Ada/{ => examples/src}/aes_verify_main.adb | 0 wrapper/Ada/{ => examples/src}/rsa_verify_main.adb | 0 wrapper/Ada/{ => examples/src}/sha256_main.adb | 0 wrapper/Ada/{ => examples/src}/spark_sockets.adb | 0 wrapper/Ada/{ => examples/src}/spark_sockets.ads | 0 wrapper/Ada/{ => examples/src}/spark_terminal.adb | 0 wrapper/Ada/{ => examples/src}/spark_terminal.ads | 0 wrapper/Ada/{ => examples/src}/tls_client.adb | 0 wrapper/Ada/{ => examples/src}/tls_client.ads | 0 wrapper/Ada/{ => examples/src}/tls_client_main.adb | 0 wrapper/Ada/{ => examples/src}/tls_server.adb | 0 wrapper/Ada/{ => examples/src}/tls_server.ads | 0 wrapper/Ada/{ => examples/src}/tls_server_main.adb | 0 16 files changed, 16 insertions(+) create mode 100644 wrapper/Ada/examples/.gitignore create mode 100644 wrapper/Ada/examples/alire.toml rename wrapper/Ada/{ => examples}/examples.gpr (100%) rename wrapper/Ada/{ => examples/src}/aes_verify_main.adb (100%) rename wrapper/Ada/{ => examples/src}/rsa_verify_main.adb (100%) rename wrapper/Ada/{ => examples/src}/sha256_main.adb (100%) rename wrapper/Ada/{ => examples/src}/spark_sockets.adb (100%) rename wrapper/Ada/{ => examples/src}/spark_sockets.ads (100%) rename wrapper/Ada/{ => examples/src}/spark_terminal.adb (100%) rename wrapper/Ada/{ => examples/src}/spark_terminal.ads (100%) rename wrapper/Ada/{ => examples/src}/tls_client.adb (100%) rename wrapper/Ada/{ => examples/src}/tls_client.ads (100%) rename wrapper/Ada/{ => examples/src}/tls_client_main.adb (100%) rename wrapper/Ada/{ => examples/src}/tls_server.adb (100%) rename wrapper/Ada/{ => examples/src}/tls_server.ads (100%) rename wrapper/Ada/{ => examples/src}/tls_server_main.adb (100%) diff --git a/wrapper/Ada/examples/.gitignore b/wrapper/Ada/examples/.gitignore new file mode 100644 index 00000000000..5866d7bfa6b --- /dev/null +++ b/wrapper/Ada/examples/.gitignore @@ -0,0 +1,4 @@ +/obj/ +/bin/ +/alire/ +/config/ diff --git a/wrapper/Ada/examples/alire.toml b/wrapper/Ada/examples/alire.toml new file mode 100644 index 00000000000..d298a6f05f7 --- /dev/null +++ b/wrapper/Ada/examples/alire.toml @@ -0,0 +1,12 @@ +name = "examples" +description = "Examples using the wolfSSL Ada bindings" +version = "0.1.0-dev" + +authors = ["Juliusz Sosinowicz"] +maintainers = ["Juliusz Sosinowicz "] +maintainers-logins = ["julek-wolfssl"] +licenses = "GPL-3.0-or-later" +website = "https://www.wolfssl.com/" +tags = [] + +executables = ["examples"] diff --git a/wrapper/Ada/examples.gpr b/wrapper/Ada/examples/examples.gpr similarity index 100% rename from wrapper/Ada/examples.gpr rename to wrapper/Ada/examples/examples.gpr diff --git a/wrapper/Ada/aes_verify_main.adb b/wrapper/Ada/examples/src/aes_verify_main.adb similarity index 100% rename from wrapper/Ada/aes_verify_main.adb rename to wrapper/Ada/examples/src/aes_verify_main.adb diff --git a/wrapper/Ada/rsa_verify_main.adb b/wrapper/Ada/examples/src/rsa_verify_main.adb similarity index 100% rename from wrapper/Ada/rsa_verify_main.adb rename to wrapper/Ada/examples/src/rsa_verify_main.adb diff --git a/wrapper/Ada/sha256_main.adb b/wrapper/Ada/examples/src/sha256_main.adb similarity index 100% rename from wrapper/Ada/sha256_main.adb rename to wrapper/Ada/examples/src/sha256_main.adb diff --git a/wrapper/Ada/spark_sockets.adb b/wrapper/Ada/examples/src/spark_sockets.adb similarity index 100% rename from wrapper/Ada/spark_sockets.adb rename to wrapper/Ada/examples/src/spark_sockets.adb diff --git a/wrapper/Ada/spark_sockets.ads b/wrapper/Ada/examples/src/spark_sockets.ads similarity index 100% rename from wrapper/Ada/spark_sockets.ads rename to wrapper/Ada/examples/src/spark_sockets.ads diff --git a/wrapper/Ada/spark_terminal.adb b/wrapper/Ada/examples/src/spark_terminal.adb similarity index 100% rename from wrapper/Ada/spark_terminal.adb rename to wrapper/Ada/examples/src/spark_terminal.adb diff --git a/wrapper/Ada/spark_terminal.ads b/wrapper/Ada/examples/src/spark_terminal.ads similarity index 100% rename from wrapper/Ada/spark_terminal.ads rename to wrapper/Ada/examples/src/spark_terminal.ads diff --git a/wrapper/Ada/tls_client.adb b/wrapper/Ada/examples/src/tls_client.adb similarity index 100% rename from wrapper/Ada/tls_client.adb rename to wrapper/Ada/examples/src/tls_client.adb diff --git a/wrapper/Ada/tls_client.ads b/wrapper/Ada/examples/src/tls_client.ads similarity index 100% rename from wrapper/Ada/tls_client.ads rename to wrapper/Ada/examples/src/tls_client.ads diff --git a/wrapper/Ada/tls_client_main.adb b/wrapper/Ada/examples/src/tls_client_main.adb similarity index 100% rename from wrapper/Ada/tls_client_main.adb rename to wrapper/Ada/examples/src/tls_client_main.adb diff --git a/wrapper/Ada/tls_server.adb b/wrapper/Ada/examples/src/tls_server.adb similarity index 100% rename from wrapper/Ada/tls_server.adb rename to wrapper/Ada/examples/src/tls_server.adb diff --git a/wrapper/Ada/tls_server.ads b/wrapper/Ada/examples/src/tls_server.ads similarity index 100% rename from wrapper/Ada/tls_server.ads rename to wrapper/Ada/examples/src/tls_server.ads diff --git a/wrapper/Ada/tls_server_main.adb b/wrapper/Ada/examples/src/tls_server_main.adb similarity index 100% rename from wrapper/Ada/tls_server_main.adb rename to wrapper/Ada/examples/src/tls_server_main.adb From 5874be0f7e7da39e82b25cd8bf755366bde991f9 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 13:53:32 +0100 Subject: [PATCH 31/51] Ada: fix wrapper/Ada after moving examples --- wrapper/Ada/wolfssl.gpr | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/wrapper/Ada/wolfssl.gpr b/wrapper/Ada/wolfssl.gpr index 060c2bc6a08..9f0df5ba36b 100644 --- a/wrapper/Ada/wolfssl.gpr +++ b/wrapper/Ada/wolfssl.gpr @@ -11,16 +11,6 @@ library project WolfSSL is "../../src", "../../wolfcrypt/src"); - -- Don't build the tls client or server application. - -- They are not needed in order to build the library. - for Excluded_Source_Files use - ("tls_client_main.adb", - "tls_client.ads", - "tls_client.adb", - "tls_server_main.adb", - "tls_server.ads", - "tls_server.adb"); - for Object_Dir use "obj"; for Library_Dir use "lib"; for Create_Missing_Dirs use "True"; From 22a7ea93d62831bb2a05597bb8ef78224d9e6485 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 13:56:34 +0100 Subject: [PATCH 32/51] Ada: fix examples after move --- wrapper/Ada/examples/examples.gpr | 46 ++++--------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/wrapper/Ada/examples/examples.gpr b/wrapper/Ada/examples/examples.gpr index 94d4b467d81..6e3b92622e6 100644 --- a/wrapper/Ada/examples/examples.gpr +++ b/wrapper/Ada/examples/examples.gpr @@ -1,14 +1,14 @@ +with "config/examples_config.gpr"; +with "../wolfssl.gpr"; + project Examples is type OS_Kind is ("Windows", "Linux_Or_Mac"); OS : OS_Kind := external ("OS", "Linux_Or_Mac"); - for Languages use ("C", "Ada"); + for Languages use ("Ada"); - for Source_Dirs use (".", - "../../", - "../../src", - "../../wolfcrypt/src"); + for Source_Dirs use ("src"); for Object_Dir use "obj"; @@ -23,42 +23,6 @@ project Examples is end Naming; package Compiler is - for Switches ("C") use - ("-DWOLFSSL_USER_SETTINGS", -- Use the user_settings.h file. - "-Wno-pragmas", - "-Wall", - "-Wextra", - "-Wunknown-pragmas", - "--param=ssp-buffer-size=1", - "-Waddress", - "-Warray-bounds", - "-Wbad-function-cast", - "-Wchar-subscripts", - "-Wcomment", - "-Wfloat-equal", - "-Wformat-security", - "-Wformat=2", - "-Wmaybe-uninitialized", - "-Wmissing-field-initializers", - "-Wmissing-noreturn", - "-Wmissing-prototypes", - "-Wnested-externs", - "-Wnormalized=id", - "-Woverride-init", - "-Wpointer-arith", - "-Wpointer-sign", - "-Wshadow", - "-Wsign-compare", - "-Wstrict-overflow=1", - "-Wstrict-prototypes", - "-Wswitch-enum", - "-Wundef", - "-Wunused", - "-Wunused-result", - "-Wunused-variable", - "-Wwrite-strings", - "-fwrapv"); - for Switches ("Ada") use ("-g"); end Compiler; From 0213170278593f2aaab0ce2d15b8173747d29e79 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 13:59:05 +0100 Subject: [PATCH 33/51] Ada: update include.am --- wrapper/Ada/include.am | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/wrapper/Ada/include.am b/wrapper/Ada/include.am index cc2001e9a11..9e497f5b689 100644 --- a/wrapper/Ada/include.am +++ b/wrapper/Ada/include.am @@ -3,15 +3,43 @@ # All paths should be given relative to the root EXTRA_DIST+= wrapper/Ada/README.md +EXTRA_DIST+= wrapper/Ada/ada_binding.c +EXTRA_DIST+= wrapper/Ada/alire.toml EXTRA_DIST+= wrapper/Ada/default.gpr EXTRA_DIST+= wrapper/Ada/restricted.adc -EXTRA_DIST+= wrapper/Ada/ada_binding.c -EXTRA_DIST+= wrapper/Ada/tls_client_main.adb -EXTRA_DIST+= wrapper/Ada/tls_client.adb -EXTRA_DIST+= wrapper/Ada/tls_client.ads -EXTRA_DIST+= wrapper/Ada/tls_server_main.adb -EXTRA_DIST+= wrapper/Ada/tls_server.adb -EXTRA_DIST+= wrapper/Ada/tls_server.ads EXTRA_DIST+= wrapper/Ada/user_settings.h +EXTRA_DIST+= wrapper/Ada/wolfssl-full_runtime.adb +EXTRA_DIST+= wrapper/Ada/wolfssl-full_runtime.ads EXTRA_DIST+= wrapper/Ada/wolfssl.adb EXTRA_DIST+= wrapper/Ada/wolfssl.ads +EXTRA_DIST+= wrapper/Ada/wolfssl.gpr +EXTRA_DIST+= wrapper/Ada/examples/alire.toml +EXTRA_DIST+= wrapper/Ada/examples/examples.gpr +EXTRA_DIST+= wrapper/Ada/examples/src/aes_verify_main.adb +EXTRA_DIST+= wrapper/Ada/examples/src/rsa_verify_main.adb +EXTRA_DIST+= wrapper/Ada/examples/src/sha256_main.adb +EXTRA_DIST+= wrapper/Ada/examples/src/spark_sockets.adb +EXTRA_DIST+= wrapper/Ada/examples/src/spark_sockets.ads +EXTRA_DIST+= wrapper/Ada/examples/src/spark_terminal.adb +EXTRA_DIST+= wrapper/Ada/examples/src/spark_terminal.ads +EXTRA_DIST+= wrapper/Ada/examples/src/tls_client.adb +EXTRA_DIST+= wrapper/Ada/examples/src/tls_client.ads +EXTRA_DIST+= wrapper/Ada/examples/src/tls_client_main.adb +EXTRA_DIST+= wrapper/Ada/examples/src/tls_server.adb +EXTRA_DIST+= wrapper/Ada/examples/src/tls_server.ads +EXTRA_DIST+= wrapper/Ada/examples/src/tls_server_main.adb +EXTRA_DIST+= wrapper/Ada/tests/README.md +EXTRA_DIST+= wrapper/Ada/tests/alire.toml +EXTRA_DIST+= wrapper/Ada/tests/src/aes_bindings_tests.adb +EXTRA_DIST+= wrapper/Ada/tests/src/aes_bindings_tests.ads +EXTRA_DIST+= wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb +EXTRA_DIST+= wrapper/Ada/tests/src/rsa_verify_bindings_tests.ads +EXTRA_DIST+= wrapper/Ada/tests/src/sha256_bindings_tests.adb +EXTRA_DIST+= wrapper/Ada/tests/src/sha256_bindings_tests.ads +EXTRA_DIST+= wrapper/Ada/tests/src/support/test_support.adb +EXTRA_DIST+= wrapper/Ada/tests/src/support/test_support.ads +EXTRA_DIST+= wrapper/Ada/tests/src/support/tests_root_suite.adb +EXTRA_DIST+= wrapper/Ada/tests/src/support/tests_root_suite.ads +EXTRA_DIST+= wrapper/Ada/tests/src/tests.adb +EXTRA_DIST+= wrapper/Ada/tests/tests.gpr +EXTRA_DIST+= wrapper/Ada/tests/valgrind.supp From 9670234d966f0a18052a881318748a63ca814819 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 14:03:27 +0100 Subject: [PATCH 34/51] Ada: update examples executables --- wrapper/Ada/examples/alire.toml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wrapper/Ada/examples/alire.toml b/wrapper/Ada/examples/alire.toml index d298a6f05f7..1951198a901 100644 --- a/wrapper/Ada/examples/alire.toml +++ b/wrapper/Ada/examples/alire.toml @@ -9,4 +9,10 @@ licenses = "GPL-3.0-or-later" website = "https://www.wolfssl.com/" tags = [] -executables = ["examples"] +executables = [ + "aes_verify_main", + "rsa_verify_main", + "sha256_main", + "tls_client_main", + "tls_server_main" +] From 597e6335de5276da13b021cc070c3636e0597222 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 14:08:10 +0100 Subject: [PATCH 35/51] Ada: update readme --- wrapper/Ada/README.md | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/wrapper/Ada/README.md b/wrapper/Ada/README.md index a35dfd3ccaa..1f091f943ab 100644 --- a/wrapper/Ada/README.md +++ b/wrapper/Ada/README.md @@ -28,9 +28,9 @@ been developed with maximum portability in mind. Not only can the WolfSSL Ada binding be used in Ada applications but also SPARK applications (a subset of the Ada language suitable for formal verification). To formally verify the Ada code in this repository -open the examples.gpr with GNAT Studio and then select +open the examples/examples.gpr with GNAT Studio and then select SPARK -> Prove All Sources and use Proof Level 2. Or when using the command -line, use `gnatprove -Pexamples.gpr --level=4 -j12` (`-j12` is there in +line, use `gnatprove -Pexamples/examples.gpr --level=4 -j12` (`-j12` is there in order to instruct the prover to use 12 CPUs if available). ``` @@ -86,6 +86,8 @@ and use gprbuild to build the source code. cd wrapper/Ada gprclean gprbuild default.gpr + +cd examples gprbuild examples.gpr cd obj/ @@ -93,29 +95,39 @@ cd obj/ ./tls_client_main 127.0.0.1 ``` -If you are using Alire, you can access `gprclean` and `gprbuild` through Alire's environment: +If you are using Alire, you can build the library and examples with: + +```sh +cd wrapper/Ada +alr install + +cd examples +alr build +``` + +You can also run the examples directly with Alire: ```sh -alr exec -- gprclean -alr exec -- gprbuild default.gpr -alr exec -- gprbuild examples.gpr +cd wrapper/Ada/examples +alr run tls_server_main & +alr run tls_client_main --args=127.0.0.1 ``` On Windows, build the executables with: ```sh -gprbuild -XOS=Windows default.gpr +cd wrapper/Ada/examples gprbuild -XOS=Windows examples.gpr ``` ## Files The (D)TLS v1.3 client example in the Ada/SPARK programming language using the WolfSSL library can be found in the files: -tls_client_main.adb -tls_client.ads -tls_client.adb +examples/src/tls_client_main.adb +examples/src/tls_client.ads +examples/src/tls_client.adb The (D)TLS v1.3 server example in the Ada/SPARK programming language using the WolfSSL library can be found in the files: -tls_server_main.adb -tls_server.ads -tls_server.adb +examples/src/tls_server_main.adb +examples/src/tls_server.ads +examples/src/tls_server.adb From 972ee56c525aa90a7ac6ccd83a1cc80e34058531 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 14:15:01 +0100 Subject: [PATCH 36/51] Ada: fix the client-server examples --- wrapper/Ada/examples/src/tls_client.adb | 6 +++--- wrapper/Ada/examples/src/tls_server.adb | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/wrapper/Ada/examples/src/tls_client.adb b/wrapper/Ada/examples/src/tls_client.adb index e31c969e5ea..bf87518fcc1 100644 --- a/wrapper/Ada/examples/src/tls_client.adb +++ b/wrapper/Ada/examples/src/tls_client.adb @@ -170,9 +170,9 @@ package body Tls_Client with SPARK_Mode is Any_Inet_Addr : Inet_Addr_Type renames SPARK_Sockets.Any_Inet_Addr; - CERT_FILE : constant String := "../../certs/client-cert.pem"; - KEY_FILE : constant String := "../../certs/client-key.pem"; - CA_FILE : constant String := "../../certs/ca-cert.pem"; + CERT_FILE : constant String := "../../../certs/client-cert.pem"; + KEY_FILE : constant String := "../../../certs/client-key.pem"; + CA_FILE : constant String := "../../../certs/ca-cert.pem"; subtype Byte_Array is WolfSSL.Byte_Array; diff --git a/wrapper/Ada/examples/src/tls_server.adb b/wrapper/Ada/examples/src/tls_server.adb index 498ce26a5d7..a5695e7b906 100644 --- a/wrapper/Ada/examples/src/tls_server.adb +++ b/wrapper/Ada/examples/src/tls_server.adb @@ -94,9 +94,9 @@ package body Tls_Server with SPARK_Mode is Any_Inet_Addr : Inet_Addr_Type renames SPARK_Sockets.Any_Inet_Addr; - CERT_FILE : constant String := "../../certs/server-cert.pem"; - KEY_FILE : constant String := "../../certs/server-key.pem"; - CA_FILE : constant String := "../../certs/client-cert.pem"; + CERT_FILE : constant String := "../../../certs/server-cert.pem"; + KEY_FILE : constant String := "../../../certs/server-key.pem"; + CA_FILE : constant String := "../../../certs/client-cert.pem"; subtype Byte_Array is WolfSSL.Byte_Array; @@ -324,7 +324,7 @@ package body Tls_Server with SPARK_Mode is (Context => Ctx, Callback => PSK_Server_Callback'Access); end if; - + while Shall_Continue loop pragma Loop_Invariant (not C.Exists); pragma Loop_Invariant (not WolfSSL.Is_Valid (Ssl)); From 039e08b56fec3917a17b8d162df058c490206429 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 14:23:13 +0100 Subject: [PATCH 37/51] Ada: add examples to ada.yml --- .github/workflows/ada.yml | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ada.yml b/.github/workflows/ada.yml index dd80f000786..7f0976c4783 100644 --- a/.github/workflows/ada.yml +++ b/.github/workflows/ada.yml @@ -18,18 +18,39 @@ jobs: - name: Install alire uses: alire-project/setup-alire@v5 - - name: Build wolfssl Ada + - name: Install wolfssl Ada working-directory: ./wrapper/Ada - run: | - alr exec -- gprbuild -j$(nproc) default.gpr - alr exec -- gprbuild -j$(nproc) examples.gpr + run: alr install - - name: Run Ada wrapper tests (alire) - working-directory: ./wrapper/Ada + - name: Run Ada wrapper tests + working-directory: ./wrapper/Ada/tests + run: alr run + + - name: Run Ada examples + id: examples + working-directory: ./wrapper/Ada/examples run: | - alr install - cd tests - alr run + alr build + + echo "Running sha256_main example..." + alr run sha256_main + + echo "Running aes_verify_main example..." + alr run aes_verify_main + + echo "Running rsa_verify_main example..." + alr run rsa_verify_main + + echo "Running TLS server/client example..." + alr run tls_server_main &> server.log & + SERVER_PID=$! + sleep 1 + echo "test message" | alr run tls_client_main -- 127.0.0.1 + kill $SERVER_PID || true + + - name: show errors + if: ${{ failure() && steps.examples.outcome == 'failure' }} + run: cat ./wrapper/Ada/examples/server.log - name: Run Ada wrapper tests (valgrind) working-directory: ./wrapper/Ada/tests From d8511f8484a82415956e6792990fb14224377898 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Dec 2025 17:44:59 +0100 Subject: [PATCH 38/51] Ada: leverage gnatprove to track memory - annotate Is_Valid functions to allow gnatprove to detect leaks --- wrapper/Ada/examples/alire.toml | 3 ++ wrapper/Ada/examples/src/tls_client.adb | 28 +++++++++--- wrapper/Ada/examples/src/tls_server.adb | 28 +++++++++--- wrapper/Ada/wolfssl.adb | 12 ++++- wrapper/Ada/wolfssl.ads | 61 ++++++++++++++++++------- 5 files changed, 99 insertions(+), 33 deletions(-) diff --git a/wrapper/Ada/examples/alire.toml b/wrapper/Ada/examples/alire.toml index 1951198a901..17b6be84cdd 100644 --- a/wrapper/Ada/examples/alire.toml +++ b/wrapper/Ada/examples/alire.toml @@ -16,3 +16,6 @@ executables = [ "tls_client_main", "tls_server_main" ] + +[[depends-on]] +gnatprove = "^13.2.1" diff --git a/wrapper/Ada/examples/src/tls_client.adb b/wrapper/Ada/examples/src/tls_client.adb index bf87518fcc1..8e1c7777385 100644 --- a/wrapper/Ada/examples/src/tls_client.adb +++ b/wrapper/Ada/examples/src/tls_client.adb @@ -270,17 +270,30 @@ package body Tls_Client with SPARK_Mode is end if; -- Create and initialize WOLFSSL_CTX. - WolfSSL.Create_Context - (Method => - (if DTLS then - WolfSSL.DTLSv1_3_Client_Method - else - WolfSSL.TLSv1_3_Client_Method), - Context => Ctx); + if DTLS then + declare + Method : WolfSSL.Method_Type := + WolfSSL.DTLSv1_3_Client_Method; + begin + pragma Warnings (Off, """Method"" is set by ""Create_Context"" but not used after the call"); + WolfSSL.Create_Context (Method => Method, Context => Ctx); + pragma Warnings (On, """Method"" is set by ""Create_Context"" but not used after the call"); + end; + else + declare + Method : WolfSSL.Method_Type := + WolfSSL.TLSv1_3_Client_Method; + begin + pragma Warnings (Off, """Method"" is set by ""Create_Context"" but not used after the call"); + WolfSSL.Create_Context (Method => Method, Context => Ctx); + pragma Warnings (On, """Method"" is set by ""Create_Context"" but not used after the call"); + end; + end if; if not WolfSSL.Is_Valid (Ctx) then Put_Line ("ERROR: failed to create WOLFSSL_CTX."); SPARK_Sockets.Close_Socket (C); + WolfSSL.Free (Context => Ctx); Set (Exit_Status_Failure); return; end if; @@ -343,6 +356,7 @@ package body Tls_Client with SPARK_Mode is if not WolfSSL.Is_Valid (Ssl) then Put_Line ("ERROR: failed to create WOLFSSL object."); SPARK_Sockets.Close_Socket (C); + WolfSSL.Free (Ssl); WolfSSL.Free (Context => Ctx); Set (Exit_Status_Failure); return; diff --git a/wrapper/Ada/examples/src/tls_server.adb b/wrapper/Ada/examples/src/tls_server.adb index a5695e7b906..fca256b372b 100644 --- a/wrapper/Ada/examples/src/tls_server.adb +++ b/wrapper/Ada/examples/src/tls_server.adb @@ -241,17 +241,30 @@ package body Tls_Server with SPARK_Mode is end if; -- Create and initialize WOLFSSL_CTX. - WolfSSL.Create_Context - (Method => - (if DTLS then - WolfSSL.DTLSv1_3_Server_Method - else - WolfSSL.TLSv1_3_Server_Method), - Context => Ctx); + if DTLS then + declare + Method : WolfSSL.Method_Type := + WolfSSL.DTLSv1_3_Server_Method; + begin + pragma Warnings (Off, """Method"" is set by ""Create_Context"" but not used after the call"); + WolfSSL.Create_Context (Method => Method, Context => Ctx); + pragma Warnings (On, """Method"" is set by ""Create_Context"" but not used after the call"); + end; + else + declare + Method : WolfSSL.Method_Type := + WolfSSL.TLSv1_3_Server_Method; + begin + pragma Warnings (Off, """Method"" is set by ""Create_Context"" but not used after the call"); + WolfSSL.Create_Context (Method => Method, Context => Ctx); + pragma Warnings (On, """Method"" is set by ""Create_Context"" but not used after the call"); + end; + end if; if not WolfSSL.Is_Valid (Ctx) then Put_Line ("ERROR: failed to create WOLFSSL_CTX."); SPARK_Sockets.Close_Socket (L); + WolfSSL.Free (Context => Ctx); Set (Exit_Status_Failure); return; end if; @@ -363,6 +376,7 @@ package body Tls_Server with SPARK_Mode is SPARK_Sockets.Close_Socket (C); end if; + WolfSSL.Free (Ssl); WolfSSL.Free (Context => Ctx); Set (Exit_Status_Failure); return; diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index 2c68cf4797b..0782c0f7f68 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -60,6 +60,11 @@ package body WolfSSL is return Context /= null; end Is_Valid; + function Is_Valid (Method : Method_Type) return Boolean is + begin + return Method /= null; + end Is_Valid; + function WolfTLSv1_2_Server_Method return Method_Type with Convention => C, External_Name => "wolfTLSv1_2_server_method", @@ -144,10 +149,11 @@ package body WolfSSL is return Context_Type with Convention => C, External_Name => "wolfSSL_CTX_new", Import => True; - procedure Create_Context (Method : Method_Type; + procedure Create_Context (Method : in out Method_Type; Context : out Context_Type) is begin Context := WolfSSL_CTX_new (Method); + Method := null; end Create_Context; procedure WolfSSL_CTX_free (Context : Context_Type) with @@ -155,7 +161,9 @@ package body WolfSSL is procedure Free (Context : in out Context_Type) is begin - WolfSSL_CTX_free (Context); + if Context /= null then + WolfSSL_CTX_free (Context); + end if; Context := null; end Free; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 670231711e7..e1527e3054f 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -54,15 +54,25 @@ package WolfSSL with SPARK_Mode is subtype Byte_Index is Interfaces.C.size_t range 0 .. 16_000; subtype Byte_Array is Interfaces.C.char_array; - type Context_Type is limited private; + type Context_Type is limited private with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Instances of this type are called SSL Contexts. - function Is_Valid (Context : Context_Type) return Boolean; + function Is_Valid (Context : Context_Type) return Boolean with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Indicates if the SSL Context has successfully been initialized. -- If initialized, the SSL Context has allocated resources -- that needs to be deallocated before application exit. + -- Annotation added for GNATprove ownership analysis. + -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type - type Method_Type is limited private; + type Method_Type is limited private with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); + + function Is_Valid (Method : Method_Type) return Boolean with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); + -- Annotation added for GNATprove ownership analysis. + -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type function TLSv1_2_Server_Method return Method_Type; -- This function is used to indicate that the application is a server @@ -96,16 +106,18 @@ package WolfSSL with SPARK_Mode is -- This function is used to indicate that the application is a client -- and will only support the DTLS 1.3 protocol. - procedure Create_Context (Method : Method_Type; - Context : out Context_Type); + procedure Create_Context (Method : in out Method_Type; + Context : out Context_Type) with + Post => not Is_Valid (Method); -- This function creates a new SSL context, taking a desired SSL/TLS -- protocol method for input. -- If successful Is_Valid (Context) = True, otherwise False. + -- The Method is consumed by this operation and set to null. procedure Free (Context : in out Context_Type) with - Pre => Is_Valid (Context), Post => not Is_Valid (Context); -- This function frees an allocated SSL Context object. + -- If Context is not valid, this is a no-op. type Mode_Type is private; @@ -240,13 +252,17 @@ package WolfSSL with SPARK_Mode is -- per buffer as long as the format is in PEM. -- Please see the examples for proper usage. - type WolfSSL_Type is limited private; + type WolfSSL_Type is limited private with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Instances of this type are called SSL Sessions. - function Is_Valid (Ssl : WolfSSL_Type) return Boolean; + function Is_Valid (Ssl : WolfSSL_Type) return Boolean with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Indicates if the SSL Session has successfully been initialized. -- If initialized, the SSL Session has allocated resources -- that needs to be deallocated before application exit. + -- Annotation added for GNATprove ownership analysis. + -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type procedure Create_WolfSSL (Context : Context_Type; Ssl : out WolfSSL_Type) with @@ -320,8 +336,7 @@ package WolfSSL with SPARK_Mode is -- be freed when the associated SSL object is freed. procedure Free_Arrays (Ssl : WolfSSL_Type) with - Pre => Is_Valid (Ssl), - Post => not Is_Valid (Ssl); + Pre => Is_Valid (Ssl); -- Normally, at the end of the SSL handshake, wolfSSL frees temporary -- arrays. If Keep_Arrays(..) has been called before the handshake, -- wolfSSL will not free temporary arrays. This function explicitly @@ -432,9 +447,9 @@ package WolfSSL with SPARK_Mode is -- the call to Shutdown() when the underlying I/O is ready. procedure Free (Ssl : in out WolfSSL_Type) with - Pre => Is_Valid (Ssl), Post => not Is_Valid (Ssl); -- Frees the resources allocated by the SSL session object. + -- If Ssl is not valid, this is a no-op. function Connect (Ssl : WolfSSL_Type) return Subprogram_Result with Pre => Is_Valid (Ssl); @@ -504,8 +519,11 @@ package WolfSSL with SPARK_Mode is type RNG_Key_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); - function Is_Valid (Key : RNG_Key_Type) return Boolean; - -- Indicates if the RSA has successfully been initialized. + function Is_Valid (Key : RNG_Key_Type) return Boolean with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); + -- Indicates if the RSA has successfully been initialized. + -- Annotation added for GNATprove ownership analysis. + -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type procedure Create_RNG (Key : in out RNG_Key_Type; Result : out Integer) with @@ -537,8 +555,11 @@ package WolfSSL with SPARK_Mode is type RSA_Key_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); - function Is_Valid (Key : RSA_Key_Type) return Boolean; - -- Indicates if the RSA has successfully been initialized. + function Is_Valid (Key : RSA_Key_Type) return Boolean with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); + -- Indicates if the RSA has successfully been initialized. + -- Annotation added for GNATprove ownership analysis. + -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type procedure Create_RSA (Key : in out RSA_Key_Type; Result : out Integer) with @@ -624,8 +645,11 @@ package WolfSSL with SPARK_Mode is type SHA256_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); - function Is_Valid (SHA256 : SHA256_Type) return Boolean; + function Is_Valid (SHA256 : SHA256_Type) return Boolean with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Indicates if the SHA256 has successfully been initialized. + -- Annotation added for GNATprove ownership analysis. + -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type procedure Create_SHA256 (SHA256 : in out SHA256_Type; Result : out Integer) with @@ -663,8 +687,11 @@ package WolfSSL with SPARK_Mode is type AES_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); - function Is_Valid (AES : AES_Type) return Boolean; + function Is_Valid (AES : AES_Type) return Boolean with + Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Indicates if the AES has successfully been initialized. + -- Annotation added for GNATprove ownership analysis. + -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type procedure Create_AES (Device : Device_Identifier; AES : in out AES_Type; From 56ac0a6203ddedd71d11561a042c9d536146c94a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 5 Jan 2026 18:34:43 +0100 Subject: [PATCH 39/51] Ada: fix length proofs in gnatprove --- wrapper/Ada/examples/src/tls_client.adb | 16 +++++----------- wrapper/Ada/wolfssl.ads | 2 ++ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/wrapper/Ada/examples/src/tls_client.adb b/wrapper/Ada/examples/src/tls_client.adb index 8e1c7777385..3ba6abc43b2 100644 --- a/wrapper/Ada/examples/src/tls_client.adb +++ b/wrapper/Ada/examples/src/tls_client.adb @@ -437,23 +437,17 @@ package body Tls_Client with SPARK_Mode is end if; WolfSSL.Read (Ssl => Ssl, Result => Input); - if not Input.Success then - Put_Line ("Read error."); + if not Input.Success or Input.Last > Text'Length then + Put_Line ("Read error or response too long."); Set (Exit_Status_Failure); SPARK_Sockets.Close_Socket (C); WolfSSL.Free (Ssl); WolfSSL.Free (Context => Ctx); return; end if; - if Input.Buffer'Length > Text'Length then - SPARK_Sockets.To_Ada (Item => Input.Buffer (1 .. 200), - Target => Text, - Count => Last); - else - SPARK_Sockets.To_Ada (Item => Input.Buffer, - Target => Text, - Count => Last); - end if; + SPARK_Sockets.To_Ada (Item => Input.Buffer, + Target => Text, + Count => Last); Put ("Server: "); Put (Text (1 .. Last)); New_Line; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index e1527e3054f..f4ed6e4262f 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -54,6 +54,8 @@ package WolfSSL with SPARK_Mode is subtype Byte_Index is Interfaces.C.size_t range 0 .. 16_000; subtype Byte_Array is Interfaces.C.char_array; + use type Interfaces.C.size_t; + type Context_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Instances of this type are called SSL Contexts. From b0fea88d049a76527697ccc36a465d4e4fea6c3f Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 6 Jan 2026 12:41:14 +0100 Subject: [PATCH 40/51] Ada: add gnatprove to CI --- .github/workflows/ada.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ada.yml b/.github/workflows/ada.yml index 7f0976c4783..56330829575 100644 --- a/.github/workflows/ada.yml +++ b/.github/workflows/ada.yml @@ -59,3 +59,11 @@ jobs: sudo apt-get install -y valgrind valgrind --leak-check=full --error-exitcode=1 \ --suppressions=valgrind.supp ./bin/tests + + - name: Run gnatprove on wolfssl + working-directory: ./wrapper/Ada + run: alr gnatprove --level=4 -P wolfssl.gpr -j 0 --warnings=error --checks-as-errors --proof-warnings -U + + - name: Run gnatprove on examples + working-directory: ./wrapper/Ada/examples + run: alr gnatprove --level=4 -P examples.gpr -j 0 --warnings=error --checks-as-errors --proof-warnings -U From 6f115098d189021799d1d59e7850e047d1bd7554 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 6 Jan 2026 12:49:56 +0100 Subject: [PATCH 41/51] Ada: update editorconfig --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 0ea0cc46c76..2a54ec49758 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,3 +8,6 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +[*.{ads,adb,gpr}] +indent_size = 3 From 9a07720a47a5178dc95a70a87dd2fc84bb548f7a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 6 Jan 2026 12:51:22 +0100 Subject: [PATCH 42/51] Ada: update gitignore to match others --- wrapper/Ada/.gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wrapper/Ada/.gitignore b/wrapper/Ada/.gitignore index b672fdeaf35..5866d7bfa6b 100644 --- a/wrapper/Ada/.gitignore +++ b/wrapper/Ada/.gitignore @@ -1 +1,4 @@ -obj +/obj/ +/bin/ +/alire/ +/config/ From ac2c7e5bbcebfbbb1b0fad8a3888ac4992857e2f Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 6 Jan 2026 13:35:04 +0100 Subject: [PATCH 43/51] Ada: fix default.gpr --- wrapper/Ada/default.gpr | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/wrapper/Ada/default.gpr b/wrapper/Ada/default.gpr index 1909f317b1e..d5705e60c12 100644 --- a/wrapper/Ada/default.gpr +++ b/wrapper/Ada/default.gpr @@ -11,19 +11,6 @@ project Default is "../../src", "../../wolfcrypt/src"); - -- Don't build the tls application examples because they make use - -- of the Secondary Stack due to usage of the Ada.Command_Line - -- package. All other Ada source code does not use the secondary stack. - for Excluded_Source_Files use - ("tls_client_main.adb", - "tls_client.ads", - "tls_client.adb", - "tls_server_main.adb", - "tls_server.ads", - "tls_server.adb", - "sha256_main.adb", - "rsa_verify_main.adb"); - for Object_Dir use "obj"; package Naming is From 515c8e6b463ed4fb4fffe6e0845904583bbc5c37 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 6 Jan 2026 13:37:56 +0100 Subject: [PATCH 44/51] Ada: build default.gpr in CI --- .github/workflows/ada.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ada.yml b/.github/workflows/ada.yml index 56330829575..6368c2e3869 100644 --- a/.github/workflows/ada.yml +++ b/.github/workflows/ada.yml @@ -22,6 +22,10 @@ jobs: working-directory: ./wrapper/Ada run: alr install + - name: Build default.gpr + working-directory: ./wrapper/Ada + run: alr exec -- gprbuild default.gpr -j$(nproc) + - name: Run Ada wrapper tests working-directory: ./wrapper/Ada/tests run: alr run From 7ac27009be97412bba9d7e31b44fc451b7d20133 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 6 Jan 2026 13:56:38 +0100 Subject: [PATCH 45/51] Ada: fix tls_client call in CI --- .github/workflows/ada.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ada.yml b/.github/workflows/ada.yml index 6368c2e3869..d1d51d82b47 100644 --- a/.github/workflows/ada.yml +++ b/.github/workflows/ada.yml @@ -49,7 +49,7 @@ jobs: alr run tls_server_main &> server.log & SERVER_PID=$! sleep 1 - echo "test message" | alr run tls_client_main -- 127.0.0.1 + echo "test message" | alr run tls_client_main --args=127.0.0.1 kill $SERVER_PID || true - name: show errors From 56d6d289262c50e7414cf3922d16762001637716 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 8 Jan 2026 11:52:33 +0100 Subject: [PATCH 46/51] Ada: use XMALLOC and XFREE for dynamic allocation --- wolfssl/wolfcrypt/types.h | 1 + wrapper/Ada/ada_binding.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 2c048d44b42..e2d829e0967 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1361,6 +1361,7 @@ enum { DYNAMIC_TYPE_X509_ACERT = 103, DYNAMIC_TYPE_OS_BUF = 104, DYNAMIC_TYPE_ASCON = 105, + DYNAMIC_TYPE_SHA = 106, DYNAMIC_TYPE_SNIFFER_SERVER = 1000, DYNAMIC_TYPE_SNIFFER_SESSION = 1001, DYNAMIC_TYPE_SNIFFER_PB = 1002, diff --git a/wrapper/Ada/ada_binding.c b/wrapper/Ada/ada_binding.c index 6e7e91c9bb8..c4d177fc9bf 100644 --- a/wrapper/Ada/ada_binding.c +++ b/wrapper/Ada/ada_binding.c @@ -155,12 +155,12 @@ extern void ada_free_rsa (void* key) extern void* ada_new_sha256 (void) { - return malloc(sizeof(wc_Sha256)); + return XMALLOC(sizeof(wc_Sha256), NULL, DYNAMIC_TYPE_SHA); } extern void ada_free_sha256 (void* sha256) { - free(sha256); + XFREE(sha256, NULL, DYNAMIC_TYPE_SHA); } From b533ac8a1870f675a7fd799c3de374b6b066676d Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 8 Jan 2026 12:43:01 +0100 Subject: [PATCH 47/51] Ada wrapper: update .gitignore tracking, clarify RNG comment, remove unused exception, and clean up result initialization in wolfssl.adb --- wrapper/Ada/include.am | 2 ++ wrapper/Ada/wolfssl.adb | 7 ++----- wrapper/Ada/wolfssl.ads | 4 +--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/wrapper/Ada/include.am b/wrapper/Ada/include.am index 9e497f5b689..051fb65cc47 100644 --- a/wrapper/Ada/include.am +++ b/wrapper/Ada/include.am @@ -13,6 +13,7 @@ EXTRA_DIST+= wrapper/Ada/wolfssl-full_runtime.ads EXTRA_DIST+= wrapper/Ada/wolfssl.adb EXTRA_DIST+= wrapper/Ada/wolfssl.ads EXTRA_DIST+= wrapper/Ada/wolfssl.gpr +EXTRA_DIST+= wrapper/Ada/examples/.gitignore EXTRA_DIST+= wrapper/Ada/examples/alire.toml EXTRA_DIST+= wrapper/Ada/examples/examples.gpr EXTRA_DIST+= wrapper/Ada/examples/src/aes_verify_main.adb @@ -28,6 +29,7 @@ EXTRA_DIST+= wrapper/Ada/examples/src/tls_client_main.adb EXTRA_DIST+= wrapper/Ada/examples/src/tls_server.adb EXTRA_DIST+= wrapper/Ada/examples/src/tls_server.ads EXTRA_DIST+= wrapper/Ada/examples/src/tls_server_main.adb +EXTRA_DIST+= wrapper/Ada/tests/.gitignore EXTRA_DIST+= wrapper/Ada/tests/README.md EXTRA_DIST+= wrapper/Ada/tests/alire.toml EXTRA_DIST+= wrapper/Ada/tests/src/aes_bindings_tests.adb diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index 0782c0f7f68..81cc6243a0d 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -29,6 +29,8 @@ package body WolfSSL is subtype long is Interfaces.C.long; subtype unsigned_long is Interfaces.C.unsigned_long; + -- The first value in the Byte_Type range (Byte_Type'First), + -- used as the null byte (0). nul : constant Byte_Type := Byte_Type'First; -- WOLFSSL_SUCCESS : constant int := Get_WolfSSL_Success; @@ -860,7 +862,6 @@ package body WolfSSL is procedure Create_RNG (Key : in out RNG_Key_Type; Result : out Integer) is begin - Result := -121212; declare R : int; begin @@ -892,7 +893,6 @@ package body WolfSSL is Output : out Byte_Array; Result : out Integer) is begin - Result := -121212; declare R : int; begin @@ -976,8 +976,6 @@ package body WolfSSL is HMAC : HMAC_Hash; Result : out Integer) is begin - Result := -121212; - Output := (others => To_C (0)); declare R : int; H : int; @@ -1018,7 +1016,6 @@ package body WolfSSL is RNG : in out RNG_Key_Type; Result : out Integer) is begin - Result := -121212; declare R : int; begin diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index f4ed6e4262f..50acf4b6767 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -25,8 +25,6 @@ with Interfaces.C; -- the API of this package is used correctly. package WolfSSL with SPARK_Mode is - Terminator_Error : exception; - type Subprogram_Result is new Integer; Success : constant Subprogram_Result; -- Indicates success for some functions. @@ -523,7 +521,7 @@ package WolfSSL with SPARK_Mode is function Is_Valid (Key : RNG_Key_Type) return Boolean with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); - -- Indicates if the RSA has successfully been initialized. + -- Indicates if the RNG has successfully been initialized. -- Annotation added for GNATprove ownership analysis. -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type From 22b98bcea6ac60d7f52ecc1b130335997c55c055 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 20 Jan 2026 14:47:48 +0100 Subject: [PATCH 48/51] Ada: `RNG_Key_Type` => `RNG_Type` --- wrapper/Ada/examples/src/aes_verify_main.adb | 28 ++--- wrapper/Ada/examples/src/rsa_verify_main.adb | 42 ++++---- .../tests/src/rsa_verify_bindings_tests.adb | 2 +- wrapper/Ada/wolfssl.adb | 26 ++--- wrapper/Ada/wolfssl.ads | 100 +++++++++--------- 5 files changed, 99 insertions(+), 99 deletions(-) diff --git a/wrapper/Ada/examples/src/aes_verify_main.adb b/wrapper/Ada/examples/src/aes_verify_main.adb index 582a9f35d65..1a9cb7a9dff 100644 --- a/wrapper/Ada/examples/src/aes_verify_main.adb +++ b/wrapper/Ada/examples/src/aes_verify_main.adb @@ -2,9 +2,9 @@ with Ada.Text_IO; with Ada.Integer_Text_IO; with WolfSSL; procedure AES_Verify_Main is - + use type WolfSSL.Byte_Type; - + procedure Put (Text : String) renames Ada.Text_IO.Put; procedure Put (Value : Integer) is @@ -16,21 +16,21 @@ procedure AES_Verify_Main is begin Ada.Text_IO.New_Line; end New_Line; - - type Unsigned_8 is mod 2 ** 8; - + + type Unsigned_8 is mod 2 ** 8; + function To_C (Value : Unsigned_8) return WolfSSL.Byte_Type is begin return WolfSSL.Byte_Type'Val (Value); end To_C; - - RNG : WolfSSL.RNG_Key_Type; - - + + RNG : WolfSSL.RNG_Type; + + Salt_Size : constant := 8; - + Salt : WolfSSL.Byte_Array (1 .. 8); - + AES : WolfSSL.AES_Type; R : Integer; Pad : Integer := 3; @@ -56,7 +56,7 @@ begin Cleanup; return; end if; - + WolfSSL.RNG_Generate_Block (RNG => RNG, Output => Salt, Result => R); @@ -66,13 +66,13 @@ begin Cleanup; return; end if; - + if Pad = 0 then Salt (1) := To_C (0); elsif Salt (1) = To_C (0) then Salt (1) := To_C (1); end if; - + -- Create_AES signature no longer requires Index when AES objects are -- dynamically allocated. WolfSSL.Create_AES (Device => WolfSSL.Invalid_Device, diff --git a/wrapper/Ada/examples/src/rsa_verify_main.adb b/wrapper/Ada/examples/src/rsa_verify_main.adb index 73b0285102f..90b92c1acbd 100644 --- a/wrapper/Ada/examples/src/rsa_verify_main.adb +++ b/wrapper/Ada/examples/src/rsa_verify_main.adb @@ -7,16 +7,16 @@ with WolfSSL; -- Successful verification of RSA based digital signature. -- Successfully encrypted and decrypted using RSA. procedure Rsa_Verify_Main is - + use type WolfSSL.Byte_Array; - + type Unsigned_8 is mod 2 ** 8; - + function To_C (Value : Unsigned_8) return WolfSSL.Byte_Type is begin return WolfSSL.Byte_Type'Val (Value); end To_C; - + -- RSA public key to verify with. Rsa_Public_key_2048 : constant WolfSSL.Byte_Array := (To_C (16#30#), To_C (16#82#), To_C (16#01#), To_C (16#22#), To_C (16#30#), @@ -320,45 +320,45 @@ procedure Rsa_Verify_Main is To_C (16#45#), To_C (16#5D#), To_C (16#13#), To_C (16#39#), To_C (16#65#), To_C (16#42#), To_C (16#46#), To_C (16#A1#), To_C (16#9F#), To_C (16#CD#), To_C (16#F5#), To_C (16#BF#)); - + procedure Put (Text : String) renames Ada.Text_IO.Put; procedure Put (Value : Integer) is begin Ada.Integer_Text_IO.Put (Value); end Put; - + procedure New_Line is begin Ada.Text_IO.New_Line; end New_Line; use type WolfSSL.Subprogram_Result; - + Original_AES_Key : constant WolfSSL.Byte_Array (1 .. 32) := "Thisismyfakeaeskeythatis32bytes!"; Digital_Signature_Of_AES_Key : WolfSSL.Byte_Array (1 .. 256); Decrypted_Digital_Signature : WolfSSL.Byte_Array (1 .. 256); - + Encrypted : WolfSSL.Byte_Array (1 .. 1_024); -- Actually only needs to be at least 256 bytes. -- The purpose is to store the Original_AES_Key encrypted. - + Decrypted : WolfSSL.Byte_Array (1 .. 1_024); -- Actually only needs to be at least 32 bytes. -- The purpose is to store the Original_AES_Key after -- first being encrypted and then decrypted. -- After the process, this byte array should contain the same -- contents as Original_AES_KEY. - + Hash : WolfSSL.SHA256_Hash; SHA256 : WolfSSL.SHA256_Type; R : Integer; - RNG : WolfSSL.RNG_Key_Type; - + RNG : WolfSSL.RNG_Type; + RSA_Encrypt_Key : WolfSSL.RSA_Key_Type; RSA_Decrypt_Key : WolfSSL.RSA_Key_Type; Index : WolfSSL.Byte_Index; @@ -388,7 +388,7 @@ begin Cleanup; return; end if; - + WolfSSL.Create_RSA (Key => RSA_Encrypt_Key, Result => R); if R /= 0 then @@ -397,7 +397,7 @@ begin Cleanup; return; end if; - + WolfSSL.Rsa_Set_RNG (Key => RSA_Encrypt_Key, RNG => RNG, Result => R); @@ -407,7 +407,7 @@ begin Cleanup; return; end if; - + Index := Client_Private_Key_2048'First; WolfSSL.Rsa_Private_Key_Decode (Input => Client_Private_Key_2048, Index => Index, @@ -434,7 +434,7 @@ begin Cleanup; return; end if; - + WolfSSL.Create_RSA (Key => RSA_Decrypt_Key, Result => R); if R /= 0 then @@ -457,7 +457,7 @@ begin Cleanup; return; end if; - + WolfSSL.Rsa_SSL_Verify (Input => Digital_Signature_Of_AES_Key, Output => Decrypted_Digital_Signature, RSA => RSA_Decrypt_Key, @@ -471,13 +471,13 @@ begin end if; Put ("Successful verification of RSA based digital signature."); New_Line; - + WolfSSL.RSA_Public_Encrypt (Input => Original_AES_Key, Output => Encrypted, Index => Index, RSA => RSA_Decrypt_Key, RNG => RNG, - Result => R); + Result => R); if R < 0 then Put ("Failed to encrypt the original AES key"); Put (R); @@ -485,7 +485,7 @@ begin Cleanup; return; end if; - + WolfSSL.RSA_Private_Decrypt (Input => Encrypted (1 .. Index), Output => Decrypted, Index => Index, @@ -498,7 +498,7 @@ begin Cleanup; return; end if; - + if Integer (Index) /= 32 then Put ("Decryption of the encrypted original AES key, wrong size"); New_Line; diff --git a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb index 48e4218d742..cb5b3b8104b 100644 --- a/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb +++ b/wrapper/Ada/tests/src/rsa_verify_bindings_tests.adb @@ -331,7 +331,7 @@ package body RSA_Verify_Bindings_Tests is procedure Test_RSA_Sign_Verify_And_Encrypt_Decrypt (F : in out Fixture) is pragma Unreferenced (F); - RNG : WolfSSL.RNG_Key_Type; + RNG : WolfSSL.RNG_Type; RSA_Encrypt_Key : WolfSSL.RSA_Key_Type; RSA_Decrypt_Key : WolfSSL.RSA_Key_Type; diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index 81cc6243a0d..b6092caef31 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -829,24 +829,24 @@ package body WolfSSL is return Natural (Get_WolfSSL_Max_Error_Size); end Max_Error_Size; - function Is_Valid (Key : RNG_Key_Type) return Boolean is + function Is_Valid (Key : RNG_Type) return Boolean is begin return Key /= null; end Is_Valid; - function Ada_New_RNG return RNG_Key_Type with + function Ada_New_RNG return RNG_Type with Convention => C, External_Name => "ada_new_rng", Import => True; - procedure Ada_Free_RNG (Key : in RNG_Key_Type) with + procedure Ada_Free_RNG (Key : in RNG_Type) with Convention => C, External_Name => "ada_free_rng", Import => True; - procedure Free_RNG (Key : in out RNG_Key_Type) is + procedure Free_RNG (Key : in out RNG_Type) is begin if Key = null then return; @@ -859,7 +859,7 @@ package body WolfSSL is Key := null; end Free_RNG; - procedure Create_RNG (Key : in out RNG_Key_Type; + procedure Create_RNG (Key : in out RNG_Type; Result : out Integer) is begin declare @@ -882,14 +882,14 @@ package body WolfSSL is Result := Exception_Error; end Create_RNG; - function WC_RNG_Generate_Block (RNG : not null RNG_Key_Type; + function WC_RNG_Generate_Block (RNG : not null RNG_Type; Output : out Byte_Array; Size : int) return int with Convention => C, External_Name => "wc_RNG_GenerateBlock", Import => True; - procedure RNG_Generate_Block (RNG : RNG_Key_Type; + procedure RNG_Generate_Block (RNG : RNG_Type; Output : out Byte_Array; Result : out Integer) is begin @@ -1007,13 +1007,13 @@ package body WolfSSL is end PBKDF2; function Ada_RSA_Set_RNG (Key : not null RSA_Key_Type; - RNG : not null RNG_Key_Type) return int with + RNG : not null RNG_Type) return int with Convention => C, External_Name => "ada_RsaSetRNG", Import => True; procedure Rsa_Set_RNG (Key : in out Rsa_Key_Type; - RNG : in out RNG_Key_Type; + RNG : in out RNG_Type; Result : out Integer) is begin declare @@ -1139,7 +1139,7 @@ package body WolfSSL is Output : in out Byte_Array; Out_Length : int; RSA : not null RSA_Key_Type; - RNG : not null RNG_Key_Type) + RNG : not null RNG_Type) return int with Convention => C, External_Name => "wc_RsaSSL_Sign", @@ -1148,7 +1148,7 @@ package body WolfSSL is procedure Rsa_SSL_Sign (Input : Byte_Array; Output : in out Byte_Array; RSA : in out RSA_Key_Type; - RNG : in out RNG_Key_Type; + RNG : in out RNG_Type; Result : out Integer) is begin declare @@ -1202,7 +1202,7 @@ package body WolfSSL is Output : in out Byte_Array; Out_Length : int; RSA : not null RSA_Key_Type; - RNG : not null RNG_Key_Type) + RNG : not null RNG_Type) return int with Convention => C, External_Name => "wc_RsaPublicEncrypt", @@ -1212,7 +1212,7 @@ package body WolfSSL is Output : in out Byte_Array; Index : out Byte_Index; RSA : in out RSA_Key_Type; - RNG : in out RNG_Key_Type; + RNG : in out RNG_Type; Result : out Integer) is begin Index := 0; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index 50acf4b6767..e502c12b4a9 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -29,14 +29,14 @@ package WolfSSL with SPARK_Mode is Success : constant Subprogram_Result; -- Indicates success for some functions. -- Do not use, unless you know what you do. - + Failure : constant Subprogram_Result; - -- Indicates failure for some functions. - -- Do not use, unless you know what you do. + -- Inidcates failure for some functions. + -- Do not use, unless you know what you do. Exception_Error : constant := -1234567; -- Indicates an exception was raised during a subprogram call. - + function Initialize return Subprogram_Result; -- Initializes the wolfSSL library for use. Must be called once per -- application and before any other call to the library. @@ -47,7 +47,7 @@ package WolfSSL with SPARK_Mode is -- used by the library. subtype unsigned is Interfaces.C.unsigned; - + subtype Byte_Type is Interfaces.C.char; subtype Byte_Index is Interfaces.C.size_t range 0 .. 16_000; subtype Byte_Array is Interfaces.C.char_array; @@ -68,7 +68,7 @@ package WolfSSL with SPARK_Mode is type Method_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); - + function Is_Valid (Method : Method_Type) return Boolean with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Annotation added for GNATprove ownership analysis. @@ -313,7 +313,7 @@ package WolfSSL with SPARK_Mode is -- of a file. The buffer is provided by the Input argument. -- Format specifies the format type of the buffer; ASN1 or PEM. -- Please see the examples for proper usage. - + function Attach (Ssl : WolfSSL_Type; Socket : Integer) return Subprogram_Result with @@ -516,31 +516,31 @@ package WolfSSL with SPARK_Mode is -- Returns the value of the defined MAX_ERROR_SZ integer -- in wolfssl/wolfcrypt/error.h. - type RNG_Key_Type is limited private with + type RNG_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); - function Is_Valid (Key : RNG_Key_Type) return Boolean with + function Is_Valid (Key : RNG_Type) return Boolean with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); -- Indicates if the RNG has successfully been initialized. -- Annotation added for GNATprove ownership analysis. - -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type - - procedure Create_RNG (Key : in out RNG_Key_Type; + -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type + + procedure Create_RNG (Key : in out RNG_Type; Result : out Integer) with Pre => not Is_Valid (Key), Post => (if Result = 0 then Is_Valid (Key)); -- If successful Result = 0. - - procedure Free_RNG (Key : in out RNG_Key_Type) with + + procedure Free_RNG (Key : in out RNG_Type) with Pre => Is_Valid (Key), Post => not Is_Valid (Key); -- Frees resources associated with RNG and releases the underlying C object. - - procedure RNG_Generate_Block (RNG : RNG_Key_Type; + + procedure RNG_Generate_Block (RNG : RNG_Type; Output : out Byte_Array; Result : out Integer) with Pre => Is_Valid (RNG); - + type HMAC_Hash is (MD5, SHA, SHA256, SHA384, SHA512, SHA3_224, SHA3_256, SHA3_384, SHA3_512); @@ -551,7 +551,7 @@ package WolfSSL with SPARK_Mode is Key_Length : Positive; HMAC : HMAC_Hash; Result : out Integer); - + type RSA_Key_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); @@ -560,7 +560,7 @@ package WolfSSL with SPARK_Mode is -- Indicates if the RSA has successfully been initialized. -- Annotation added for GNATprove ownership analysis. -- https://docs.adacore.com/spark2014-docs/html/ug/en/appendix/additional_annotate_pragmas.html#annotation-for-enforcing-ownership-checking-on-a-private-type - + procedure Create_RSA (Key : in out RSA_Key_Type; Result : out Integer) with Pre => not Is_Valid (Key), @@ -571,7 +571,7 @@ package WolfSSL with SPARK_Mode is Pre => Is_Valid (Key), Post => not Is_Valid (Key); -- Frees resources associated with RSA and releases the underlying C object. - + procedure Rsa_Public_Key_Decode (Input : Byte_Array; Index : in out Byte_Index; Key : in out RSA_Key_Type; @@ -599,20 +599,20 @@ package WolfSSL with SPARK_Mode is -- one public and one private key. procedure Rsa_Set_RNG (Key : in out Rsa_Key_Type; - RNG : in out RNG_Key_Type; - Result : out Integer); + RNG : in out RNG_Type; + Result : out Integer); procedure Rsa_SSL_Sign (Input : Byte_Array; Output : in out Byte_Array; RSA : in out RSA_Key_Type; - RNG : in out RNG_Key_Type; + RNG : in out RNG_Type; Result : out Integer) with Pre => Is_Valid (RSA) and Is_Valid (RNG); -- The Output buffer must have the same size as the RSA key. -- If successful Result = 0. -- If Result < 0, then failure. -- If Result > 0, then Success and is the size of the RSA key in bytes. - + procedure Rsa_SSL_Verify (Input : Byte_Array; Output : in out Byte_Array; RSA : in out RSA_Key_Type; @@ -621,19 +621,19 @@ package WolfSSL with SPARK_Mode is -- If Result < 0, then failure. -- If Result > 0, then digital signature in Input -- successfully verified. - + procedure RSA_Public_Encrypt (Input : Byte_Array; Output : in out Byte_Array; Index : out Byte_Index; RSA : in out RSA_Key_Type; - RNG : in out RNG_Key_Type; + RNG : in out RNG_Type; Result : out Integer) with Pre => Is_Valid (RSA); -- This function encrypts a message from Input and stores the result -- in Output. It requires an initialized public key and a random -- number generator. As a side effect, this function will return -- the bytes written to Output in Index. - + procedure RSA_Private_Decrypt (Input : Byte_Array; Output : in out Byte_Array; Index : out Byte_Index; @@ -670,20 +670,20 @@ package WolfSSL with SPARK_Mode is -- If successful Result = 0. subtype SHA256_As_String is String (1 .. 64); - + subtype SHA256_Hash is Byte_Array (1 .. 32); - + procedure Finalize_SHA256 (SHA256 : in out SHA256_Type; Hash : out SHA256_Hash; Text : out SHA256_As_String; Result : out Integer) with Pre => Is_Valid (SHA256); -- If successful Result = 0. - + type Device_Identifier is new Integer; - + function Invalid_Device return Device_Identifier; - + type AES_Type is limited private with Annotate => (GNATprove, Ownership, "Needs_Reclamation"); @@ -718,14 +718,14 @@ package WolfSSL with SPARK_Mode is IV : Byte_Array; Result : out Integer) with Pre => Is_Valid (AES); - + procedure AES_Set_Cbc_Encrypt (AES : AES_Type; Output : out Byte_Array; Input : Byte_Array; Size : Integer; Result : out Integer) with Pre => Is_Valid (AES); - + procedure AES_Set_Cbc_Decrypt (AES : AES_Type; Output : out Byte_Array; Input : Byte_Array; @@ -734,7 +734,7 @@ package WolfSSL with SPARK_Mode is Pre => Is_Valid (AES); -- (Removed duplicate AES_Free declaration) - + private pragma SPARK_Mode (Off); @@ -744,8 +744,8 @@ private pragma No_Strict_Aliasing (chars_ptr); -- Since this type is used for external interfacing, with the pointer -- coming from who knows where, it seems a good idea to turn off any - -- strict aliasing assumptions for this type. - + -- strict aliasing assumptions for this type. + subtype int is Interfaces.C.int; use type int; type Opaque_Method is limited null record; @@ -810,7 +810,7 @@ private -- Footprint run-time. The constants exposed here in the Ada binding -- have valid values defined in the WolfSSL library but the compiler -- cannot know this since the values become known during run-time. - + Verify_None : constant Mode_Type := Mode_Type (WolfSSL_Verify_None); Verify_Peer : constant Mode_Type := Mode_Type (WolfSSL_Verify_Peer); @@ -852,7 +852,7 @@ private -- propagation if this code is compiled with the Zero -- Footprint run-time. The constants exposed here in the Ada binding -- have valid values defined in the WolfSSL library but the compiler - -- cannot know this since the values become known during run-time. + -- cannot know this since the values become known during run-time. Format_Asn1 : constant File_Format := File_Format (WolfSSL_Filetype_Asn1); @@ -862,7 +862,7 @@ private Format_Default : constant File_Format := File_Format (WolfSSL_Filetype_Default); pragma Warnings (On, "pragma Restrictions (No_Exception_Propagation)"); - + function Get_WolfSSL_Success return int with Convention => C, External_Name => "get_wolfssl_success", @@ -880,7 +880,7 @@ private Failure : constant Subprogram_Result := Subprogram_Result (Get_WolfSSL_Failure); - + function Get_WolfSSL_Error_Want_Read return int with Convention => C, External_Name => "get_wolfssl_error_want_read", @@ -897,16 +897,16 @@ private Error_Want_Write : constant Error_Code := Error_Code (Get_WolfSSL_Error_Want_Write); - type Opaque_RNG is limited null record; - type RNG_Key_Type is access Opaque_RNG with Convention => C; - - type Opaque_RSA is limited null record; + type Opaque_RNG is limited null record; + type RNG_Type is access Opaque_RNG with Convention => C; + + type Opaque_RSA is limited null record; type RSA_Key_Type is access Opaque_RSA with Convention => C; - - type Opaque_Sha256 is limited null record; + + type Opaque_Sha256 is limited null record; type SHA256_Type is access Opaque_Sha256 with Convention => C; - + type Opaque_AES is limited null record; - type AES_Type is access Opaque_AES with Convention => C; - + type AES_Type is access Opaque_AES with Convention => C; + end WolfSSL; From 23a937f1264adf479b528d33832b288d25f98a37 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 20 Jan 2026 15:58:09 +0100 Subject: [PATCH 49/51] Ada: Use `nul` for clarity --- wrapper/Ada/wolfssl.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index b6092caef31..11d4930dbd8 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -319,7 +319,7 @@ package body WolfSSL is for I in File'Range loop F (F'First + Byte_Index (I - File'First)) := Byte_Type (File (I)); end loop; - F (F'Last) := Byte_Type'Val (0); + F (F'Last) := nul; Result := Use_Private_Key_File (Ctx, F, int (Format)); return Subprogram_Result (Result); end; From c36e33b795f512fdddefe379c524d3f929cb6ebb Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 20 Jan 2026 16:44:47 +0100 Subject: [PATCH 50/51] Ada: Remove `Text` from `Finalize_SHA256` --- wrapper/Ada/examples/src/sha256_main.adb | 4 +- .../Ada/tests/src/sha256_bindings_tests.adb | 117 ++++++------------ wrapper/Ada/wolfssl.adb | 15 --- wrapper/Ada/wolfssl.ads | 1 - 4 files changed, 39 insertions(+), 98 deletions(-) diff --git a/wrapper/Ada/examples/src/sha256_main.adb b/wrapper/Ada/examples/src/sha256_main.adb index ac6f90bf7f9..10615bfffc6 100644 --- a/wrapper/Ada/examples/src/sha256_main.adb +++ b/wrapper/Ada/examples/src/sha256_main.adb @@ -18,7 +18,6 @@ procedure SHA256_Main is 4 => 'f'); SHA256 : WolfSSL.SHA256_Type; R : Integer; - S : WolfSSL.SHA256_As_String; begin WolfSSL.Create_SHA256 (SHA256 => SHA256, Result => R); if R /= 0 then @@ -34,10 +33,9 @@ begin end if; WolfSSL.Finalize_SHA256 (SHA256 => SHA256, Hash => Hash, - Text => S, Result => R); if R = 0 then - Put (S); + Put ("SHA256 hash computed successfully"); New_Line; else Put ("Finalization of SHA256 instance failed"); diff --git a/wrapper/Ada/tests/src/sha256_bindings_tests.adb b/wrapper/Ada/tests/src/sha256_bindings_tests.adb index bc674e0b443..81e69e04c1e 100644 --- a/wrapper/Ada/tests/src/sha256_bindings_tests.adb +++ b/wrapper/Ada/tests/src/sha256_bindings_tests.adb @@ -11,63 +11,9 @@ package body SHA256_Bindings_Tests is -- Helpers ---------------------------------------------------------------------------- - procedure Assert_Text_Matches_Hash - (Hash : WolfSSL.SHA256_Hash; - Text : WolfSSL.SHA256_As_String; - Msg : String); - procedure Compute_SHA256 (Input : WolfSSL.Byte_Array; Hash : out WolfSSL.SHA256_Hash; - Text : out WolfSSL.SHA256_As_String; - Result : out Integer); - - procedure Assert_Text_Matches_Hash - (Hash : WolfSSL.SHA256_Hash; - Text : WolfSSL.SHA256_As_String; - Msg : String) - is - use type WolfSSL.Byte_Array; - - Expected : constant WolfSSL.Byte_Array := Test_Support.Hex_Bytes (Text); - Actual : WolfSSL.Byte_Array (Expected'Range); - H : WolfSSL.Byte_Index := Hash'First; - begin - -- Copy bytes out of the hash into the expected-range buffer. - -- Do not assume Hash and Expected share the same index range. - for I in Actual'Range loop - Actual (I) := Hash (H); - H := WolfSSL.Byte_Index'Succ (H); - end loop; - AUnit.Assertions.Assert - (Text'Length = 64, - Msg & ": expected 64 hex chars, got" & Integer'Image (Text'Length)); - - -- `Finalize_SHA256` should generate uppercase hex, validate that expectation. - for J in Text'Range loop - declare - C : constant Character := Text (J); - begin - if C in '0' .. '9' or else C in 'A' .. 'F' then - null; - else - AUnit.Assertions.Assert - (False, - Msg & ": expected uppercase hex at pos" & - Integer'Image (J)); - end if; - end; - end loop; - - AUnit.Assertions.Assert - (Actual = Expected, - Msg & ": Text/Hash mismatch"); - end Assert_Text_Matches_Hash; - - procedure Compute_SHA256 - (Input : WolfSSL.Byte_Array; - Hash : out WolfSSL.SHA256_Hash; - Text : out WolfSSL.SHA256_As_String; Result : out Integer) is SHA256 : WolfSSL.SHA256_Type; @@ -90,7 +36,6 @@ package body SHA256_Bindings_Tests is WolfSSL.Finalize_SHA256 (SHA256 => SHA256, Hash => Hash, - Text => Text, Result => R); Result := R; @@ -106,53 +51,67 @@ package body SHA256_Bindings_Tests is pragma Unreferenced (F); Hash : WolfSSL.SHA256_Hash; - Text : WolfSSL.SHA256_As_String; R : Integer; Input : constant WolfSSL.Byte_Array := Test_Support.Bytes ("asdf"); - Expected_Text : constant WolfSSL.SHA256_As_String := - Test_Support.SHA256_Text - ("F0E4C2F76C58916EC258F246851BEA091D14D4247A2FC3E18694461B1816E13B"); + Expected_Hash : constant WolfSSL.Byte_Array := + Test_Support.Hex_Bytes + (Test_Support.SHA256_Text + ("F0E4C2F76C58916EC258F246851BEA091D14D4247A2FC3E18694461B1816E13B")); begin - Compute_SHA256 (Input => Input, Hash => Hash, Text => Text, Result => R); + Compute_SHA256 (Input => Input, Hash => Hash, Result => R); Test_Support.Assert_Success (R, "SHA256(asdf)"); - AUnit.Assertions.Assert - (Text = Expected_Text, - "SHA256('asdf') hex mismatch. Got: " & Text); - - Assert_Text_Matches_Hash - (Hash => Hash, Text => Text, Msg => "SHA256('asdf')"); + -- Compare the hash bytes + declare + use type WolfSSL.Byte_Array; + Hash_Bytes : WolfSSL.Byte_Array (1 .. 32); + J : WolfSSL.Byte_Index := 1; + begin + for I in Hash'Range loop + Hash_Bytes (J) := Hash (I); + J := WolfSSL.Byte_Index'Succ (J); + end loop; + AUnit.Assertions.Assert + (Hash_Bytes = Expected_Hash, + "SHA256('asdf') hash mismatch"); + end; end Test_SHA256_Asdf_Known_Vector; procedure Test_SHA256_Empty_Message (F : in out Fixture) is pragma Unreferenced (F); Hash : WolfSSL.SHA256_Hash; - Text : WolfSSL.SHA256_As_String; R : Integer; -- Represent empty input as a null range, matching the existing test style. Empty : constant WolfSSL.Byte_Array := (1 .. 0 => <>); - Expected_Text : constant WolfSSL.SHA256_As_String := - Test_Support.SHA256_Text - ("E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"); + Expected_Hash : constant WolfSSL.Byte_Array := + Test_Support.Hex_Bytes + (Test_Support.SHA256_Text + ("E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855")); begin - Compute_SHA256 (Input => Empty, Hash => Hash, Text => Text, Result => R); + Compute_SHA256 (Input => Empty, Hash => Hash, Result => R); Test_Support.Assert_Success (R, "SHA256(empty)"); - AUnit.Assertions.Assert - (Text = Expected_Text, - "SHA256('') hex mismatch. Got: " & Text); - - Assert_Text_Matches_Hash - (Hash => Hash, - Text => Text, - Msg => "SHA256('')"); + -- Compare the hash bytes + declare + use type WolfSSL.Byte_Array; + Hash_Bytes : WolfSSL.Byte_Array (1 .. 32); + J : WolfSSL.Byte_Index := 1; + begin + for I in Hash'Range loop + Hash_Bytes (J) := Hash (I); + J := WolfSSL.Byte_Index'Succ (J); + end loop; + AUnit.Assertions.Assert + (Hash_Bytes = Expected_Hash, + "SHA256('') hash mismatch"); + end; end Test_SHA256_Empty_Message; ---------------------------------------------------------------------------- diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index 11d4930dbd8..0d886f7b660 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -1367,26 +1367,11 @@ package body WolfSSL is procedure Finalize_SHA256 (SHA256 : in out SHA256_Type; Hash : out SHA256_Hash; - Text : out SHA256_As_String; Result : out Integer) is - subtype Unsigned_8 is Interfaces.Unsigned_8; - - use type Unsigned_8; - R : int; - Hex_Chars : constant array (Unsigned_8 range 0 .. 15) of Character := - "0123456789ABCDEF"; - I : Integer; - C : Integer; begin R := SHA256_Final (SHA256, Hash); Result := Integer (R); - for Index in Positive range 1 .. 32 loop - I := 2 * (Index - 1) + 1; - C := Interfaces.C.char'Pos (Hash (size_t (Index))); - Text (I+0) := Hex_Chars ((Unsigned_8 (C) and 16#F0#) / 16); - Text (I+1) := Hex_Chars (Unsigned_8 (C) and 16#0F#); - end loop; exception when others => Result := Exception_Error; diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index e502c12b4a9..a061e64d2e4 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -675,7 +675,6 @@ package WolfSSL with SPARK_Mode is procedure Finalize_SHA256 (SHA256 : in out SHA256_Type; Hash : out SHA256_Hash; - Text : out SHA256_As_String; Result : out Integer) with Pre => Is_Valid (SHA256); -- If successful Result = 0. From af9086a6baa24b9dd7bd15740c50610cc4b128d2 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 22 Jan 2026 10:09:54 +0100 Subject: [PATCH 51/51] Ada: fix typo --- wrapper/Ada/wolfssl.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index a061e64d2e4..258144642a7 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -31,7 +31,7 @@ package WolfSSL with SPARK_Mode is -- Do not use, unless you know what you do. Failure : constant Subprogram_Result; - -- Inidcates failure for some functions. + -- Indicates failure for some functions. -- Do not use, unless you know what you do. Exception_Error : constant := -1234567;