Skip to content

Commit

Permalink
Ada binding: add support for PSK client callback
Browse files Browse the repository at this point in the history
Tested with:
`wolfSSL/wolfssl-examples/psk/server-psk.c`
after changing `DTLSv1_3_Client_Method` to `DTLSv1_2_Client_Method` to comply with the server example.
  • Loading branch information
mgrojo committed Jan 4, 2025
1 parent 239b85c commit 11a40a6
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 43 deletions.
152 changes: 110 additions & 42 deletions wrapper/Ada/tls_client.adb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
with Ada.Characters.Handling;
with Ada.Strings.Bounded;
with Ada.Text_IO;
with Interfaces.C;
with Ada.Directories;
with Interfaces.C.Strings;

with SPARK_Terminal;

Expand All @@ -40,8 +41,62 @@ package body Tls_Client with SPARK_Mode is

subtype Byte_Type is WolfSSL.Byte_Type;

subtype chars_ptr is WolfSSL.chars_ptr;
subtype unsigned is WolfSSL.unsigned;

package Natural_IO is new Ada.Text_IO.Integer_IO (Natural);

function PSK_Client_Callback
(Unused : WolfSSL.WolfSSL_Type;
Hint : chars_ptr;
Identity : chars_ptr;
Id_Max_Length : unsigned;
Key : chars_ptr;
Key_Max_Length : unsigned) return unsigned
with Convention => C;

function PSK_Client_Callback
(Unused : WolfSSL.WolfSSL_Type;
Hint : chars_ptr;
Identity : chars_ptr;
Id_Max_Length : unsigned;
Key : chars_ptr;
Key_Max_Length : unsigned) return unsigned
with
SPARK_Mode => Off
is
use type Interfaces.C.unsigned;

Hint_String : constant String := Interfaces.C.Strings.Value (Hint);
Identity_String : constant String := "Client_identity";
Key_String : constant String :=
Character'Val (26)
& Character'Val (43)
& Character'Val (60)
& Character'Val (77);
begin

Ada.Text_IO.Put_Line ("Hint: " & Hint_String);

pragma Assert (Id_Max_Length >= Identity_String'Length);

Interfaces.C.Strings.Update
(Item => Identity,
Offset => 0,
Str => Identity_String,
Check => False);

pragma Assert (Key_Max_Length >= Key_String'Length);

Interfaces.C.Strings.Update
(Item => Key,
Offset => 0,
Str => Key_String,
Check => False);

return Key_String'Length;
end PSK_Client_Callback;

procedure Put (Text : String) is
begin
Ada.Text_IO.Put (Text);
Expand Down Expand Up @@ -221,49 +276,53 @@ package body Tls_Client with SPARK_Mode is
(Context => Ctx,
Mode => WolfSSL.Verify_Peer or WolfSSL.Verify_Fail_If_No_Peer_Cert);

-- Load client certificate into WOLFSSL_CTX.
Result := WolfSSL.Use_Certificate_File (Context => Ctx,
File => CERT_FILE,
Format => WolfSSL.Format_Pem);
if Result /= Success then
Put ("ERROR: failed to load ");
Put (CERT_FILE);
Put (", please check the file.");
New_Line;
SPARK_Sockets.Close_Socket (C);
WolfSSL.Free (Context => Ctx);
Set (Exit_Status_Failure);
return;
end if;
if Ada.Directories.Exists (CERT_FILE) and then
Ada.Directories.Exists (KEY_FILE) then

-- Load client key into WOLFSSL_CTX.
Result := WolfSSL.Use_Private_Key_File (Context => Ctx,
File => KEY_FILE,
Format => WolfSSL.Format_Pem);
if Result /= Success then
Put ("ERROR: failed to load ");
Put (KEY_FILE);
Put (", please check the file.");
New_Line;
SPARK_Sockets.Close_Socket (C);
WolfSSL.Free (Context => Ctx);
Set (Exit_Status_Failure);
return;
end if;
-- Load client certificate into WOLFSSL_CTX.
Result := WolfSSL.Use_Certificate_File (Context => Ctx,
File => CERT_FILE,
Format => WolfSSL.Format_Pem);
if Result /= Success then
Put ("ERROR: failed to load ");
Put (CERT_FILE);
Put (", please check the file.");
New_Line;
SPARK_Sockets.Close_Socket (C);
WolfSSL.Free (Context => Ctx);
Set (Exit_Status_Failure);
return;
end if;

-- Load CA certificate into WOLFSSL_CTX.
Result := WolfSSL.Load_Verify_Locations (Context => Ctx,
File => CA_FILE,
Path => "");
if Result /= Success then
Put ("ERROR: failed to load ");
Put (CA_FILE);
Put (", please check the file.");
New_Line;
SPARK_Sockets.Close_Socket (C);
WolfSSL.Free (Context => Ctx);
Set (Exit_Status_Failure);
return;
-- Load client key into WOLFSSL_CTX.
Result := WolfSSL.Use_Private_Key_File (Context => Ctx,
File => KEY_FILE,
Format => WolfSSL.Format_Pem);
if Result /= Success then
Put ("ERROR: failed to load ");
Put (KEY_FILE);
Put (", please check the file.");
New_Line;
SPARK_Sockets.Close_Socket (C);
WolfSSL.Free (Context => Ctx);
Set (Exit_Status_Failure);
return;
end if;

-- Load CA certificate into WOLFSSL_CTX.
Result := WolfSSL.Load_Verify_Locations (Context => Ctx,
File => CA_FILE,
Path => "");
if Result /= Success then
Put ("ERROR: failed to load ");
Put (CA_FILE);
Put (", please check the file.");
New_Line;
SPARK_Sockets.Close_Socket (C);
WolfSSL.Free (Context => Ctx);
Set (Exit_Status_Failure);
return;
end if;
end if;

-- Create a WOLFSSL object.
Expand All @@ -276,6 +335,15 @@ package body Tls_Client with SPARK_Mode is
return;
end if;

if not (Ada.Directories.Exists (CERT_FILE) and then
Ada.Directories.Exists (KEY_FILE)) then

-- Use PSK for authentication.
WolfSSL.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);
Expand Down
15 changes: 15 additions & 0 deletions wrapper/Ada/wolfssl.adb
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,21 @@ package body WolfSSL is

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;

function WolfSSL_Set_Fd (Ssl : WolfSSL_Type; Fd : int) return int with
Convention => C,
External_Name => "wolfSSL_set_fd",
Expand Down
30 changes: 29 additions & 1 deletion wrapper/Ada/wolfssl.ads
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
--

with GNAT.Sockets;
with Interfaces.C;
with Interfaces.C.Strings;

-- This package is annotated "with SPARK_Mode" that SPARK can verify
-- the API of this package is used correctly.
Expand All @@ -39,7 +39,10 @@ package WolfSSL with SPARK_Mode is
-- Doesn't have to be called, though it will free any resources
-- 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;
Expand Down Expand Up @@ -297,6 +300,31 @@ package WolfSSL with SPARK_Mode is
-- 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.

procedure Set_PSK_Client_Callback
(Ssl : WolfSSL_Type;
Callback : PSK_Client_Callback) with
Pre => Is_Valid (Ssl);
-- Sets the PSK client side callback.

function Attach (Ssl : WolfSSL_Type;
Socket : Integer)
return Subprogram_Result with
Expand Down

0 comments on commit 11a40a6

Please sign in to comment.