forked from wolfSSL/wolfssl
Merge pull request #7397 from dalybrown/expose-dtsl-in-ada
Expose DTLS in Ada wrapper and update examples
This commit is contained in:
1
wrapper/Ada/.gitignore
vendored
Normal file
1
wrapper/Ada/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
obj
|
@@ -2,7 +2,7 @@
|
|||||||
The source code for the Ada/SPARK binding of the WolfSSL library
|
The source code for the Ada/SPARK binding of the WolfSSL library
|
||||||
is the WolfSSL Ada package in the wolfssl.ads and wolfssl.adb files.
|
is the WolfSSL Ada package in the wolfssl.ads and wolfssl.adb files.
|
||||||
|
|
||||||
The source code here also demonstrates a TLS v1.3 server and client
|
The source code here also demonstrates a (D)TLS v1.3 server and client
|
||||||
using the WolfSSL Ada binding. The implementation is cross-platform
|
using the WolfSSL Ada binding. The implementation is cross-platform
|
||||||
and compiles on Linux, Mac OS X and Windows.
|
and compiles on Linux, Mac OS X and Windows.
|
||||||
|
|
||||||
@@ -15,7 +15,8 @@ for the secondary stack. The GNAT User's Guide recommends
|
|||||||
avoiding the secondary stack using the restriction
|
avoiding the secondary stack using the restriction
|
||||||
No_Secondary_Stack (see the GNAT configuration file gnat.adc
|
No_Secondary_Stack (see the GNAT configuration file gnat.adc
|
||||||
which instructs compilation of the WolfSSL Ada binding under
|
which instructs compilation of the WolfSSL Ada binding under
|
||||||
this restriction).
|
this restriction). Note, however, that the examples do make use of the
|
||||||
|
secondary stack.
|
||||||
|
|
||||||
Portability: The WolfSSL Ada binding makes no usage of controlled types
|
Portability: The WolfSSL Ada binding makes no usage of controlled types
|
||||||
and has no dependency upon the Ada.Finalization package.
|
and has no dependency upon the Ada.Finalization package.
|
||||||
@@ -91,13 +92,13 @@ Make sure the executables for the compiler and GPRBuild are on the PATH
|
|||||||
and use gprbuild to build the source code.
|
and use gprbuild to build the source code.
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
The TLS v1.3 client example in the Ada/SPARK programming language
|
The (D)TLS v1.3 client example in the Ada/SPARK programming language
|
||||||
using the WolfSSL library can be found in the files:
|
using the WolfSSL library can be found in the files:
|
||||||
tls_client_main.adb
|
tls_client_main.adb
|
||||||
tls_client.ads
|
tls_client.ads
|
||||||
tls_client.adb
|
tls_client.adb
|
||||||
|
|
||||||
The TLS v1.3 server example in the Ada/SPARK programming language
|
The (D)TLS v1.3 server example in the Ada/SPARK programming language
|
||||||
using the WolfSSL library can be found in the files:
|
using the WolfSSL library can be found in the files:
|
||||||
tls_server_main.adb
|
tls_server_main.adb
|
||||||
tls_server.ads
|
tls_server.ads
|
||||||
|
@@ -26,10 +26,6 @@ project Default is
|
|||||||
for Spec_Suffix ("C") use ".h";
|
for Spec_Suffix ("C") use ".h";
|
||||||
end Naming;
|
end Naming;
|
||||||
|
|
||||||
package Builder is
|
|
||||||
for Global_Configuration_Pragmas use "gnat.adc";
|
|
||||||
end Builder;
|
|
||||||
|
|
||||||
package Compiler is
|
package Compiler is
|
||||||
for Switches ("C") use
|
for Switches ("C") use
|
||||||
("-DWOLFSSL_USER_SETTINGS", -- Use the user_settings.h file.
|
("-DWOLFSSL_USER_SETTINGS", -- Use the user_settings.h file.
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||||
--
|
--
|
||||||
|
|
||||||
|
with Ada.Streams;
|
||||||
with Interfaces.C;
|
with Interfaces.C;
|
||||||
|
|
||||||
package body SPARK_Sockets is
|
package body SPARK_Sockets is
|
||||||
@@ -33,16 +34,35 @@ package body SPARK_Sockets is
|
|||||||
return (Exists => False);
|
return (Exists => False);
|
||||||
end Inet_Addr;
|
end Inet_Addr;
|
||||||
|
|
||||||
procedure Create_Socket (Socket : in out Optional_Socket) is
|
procedure Create_Socket
|
||||||
|
(Socket : in out Optional_Socket;
|
||||||
|
Family : GNAT.Sockets.Family_Type;
|
||||||
|
Mode : GNAT.Sockets.Mode_Type) is
|
||||||
S : Socket_Type;
|
S : Socket_Type;
|
||||||
begin
|
begin
|
||||||
GNAT.Sockets.Create_Socket (S);
|
GNAT.Sockets.Create_Socket (S, Family, Mode);
|
||||||
Socket := (Exists => True, Socket => S);
|
Socket := (Exists => True, Socket => S);
|
||||||
exception
|
exception
|
||||||
when others =>
|
when others =>
|
||||||
Socket := (Exists => False);
|
Socket := (Exists => False);
|
||||||
end Create_Socket;
|
end Create_Socket;
|
||||||
|
|
||||||
|
procedure Create_Stream_Socket (Socket : in out Optional_Socket) is
|
||||||
|
begin
|
||||||
|
Create_Socket
|
||||||
|
(Socket => Socket,
|
||||||
|
Family => GNAT.Sockets.Family_Inet,
|
||||||
|
Mode => GNAT.Sockets.Socket_Stream);
|
||||||
|
end Create_Stream_Socket;
|
||||||
|
|
||||||
|
procedure Create_Datagram_Socket (Socket : in out Optional_Socket) is
|
||||||
|
begin
|
||||||
|
Create_Socket
|
||||||
|
(Socket => Socket,
|
||||||
|
Family => GNAT.Sockets.Family_Inet,
|
||||||
|
Mode => GNAT.Sockets.Socket_Datagram);
|
||||||
|
end Create_Datagram_Socket;
|
||||||
|
|
||||||
function Connect_Socket (Socket : Socket_Type;
|
function Connect_Socket (Socket : Socket_Type;
|
||||||
Server : Sock_Addr_Type)
|
Server : Sock_Addr_Type)
|
||||||
return Subprogram_Result is
|
return Subprogram_Result is
|
||||||
@@ -99,6 +119,22 @@ package body SPARK_Sockets is
|
|||||||
return Failure;
|
return Failure;
|
||||||
end Listen_Socket;
|
end Listen_Socket;
|
||||||
|
|
||||||
|
function Receive_Socket
|
||||||
|
(Socket : Socket_Type)
|
||||||
|
return Subprogram_Result is
|
||||||
|
|
||||||
|
Item : Ada.Streams.Stream_Element_Array (1 .. 4096);
|
||||||
|
Last : Ada.Streams.Stream_Element_Offset;
|
||||||
|
From : GNAT.Sockets.Sock_Addr_Type;
|
||||||
|
|
||||||
|
begin
|
||||||
|
GNAT.Sockets.Receive_Socket (Socket, Item, Last, From);
|
||||||
|
return Success;
|
||||||
|
exception
|
||||||
|
when others =>
|
||||||
|
return Failure;
|
||||||
|
end Receive_Socket;
|
||||||
|
|
||||||
procedure Accept_Socket (Server : Socket_Type;
|
procedure Accept_Socket (Server : Socket_Type;
|
||||||
Socket : out Optional_Socket;
|
Socket : out Optional_Socket;
|
||||||
Address : out Sock_Addr_Type;
|
Address : out Sock_Addr_Type;
|
||||||
|
@@ -83,7 +83,10 @@ package SPARK_Sockets with SPARK_Mode is
|
|||||||
end case;
|
end case;
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
procedure Create_Socket (Socket : in out Optional_Socket) with
|
procedure Create_Stream_Socket (Socket : in out Optional_Socket) with
|
||||||
|
Pre => not Socket.Exists;
|
||||||
|
|
||||||
|
procedure Create_Datagram_Socket (Socket : in out Optional_Socket) with
|
||||||
Pre => not Socket.Exists;
|
Pre => not Socket.Exists;
|
||||||
|
|
||||||
function Connect_Socket (Socket : Socket_Type;
|
function Connect_Socket (Socket : Socket_Type;
|
||||||
@@ -116,6 +119,8 @@ package SPARK_Sockets with SPARK_Mode is
|
|||||||
-- appropriate in usual cases. It can be adjusted according to each
|
-- appropriate in usual cases. It can be adjusted according to each
|
||||||
-- application's particular requirements.
|
-- application's particular requirements.
|
||||||
|
|
||||||
|
function Receive_Socket (Socket : Socket_Type) return Subprogram_Result;
|
||||||
|
|
||||||
procedure Accept_Socket (Server : Socket_Type;
|
procedure Accept_Socket (Server : Socket_Type;
|
||||||
Socket : out Optional_Socket;
|
Socket : out Optional_Socket;
|
||||||
Address : out Sock_Addr_Type;
|
Address : out Sock_Addr_Type;
|
||||||
|
@@ -47,12 +47,18 @@ package body Tls_Client with SPARK_Mode is
|
|||||||
Ada.Text_IO.Put (Text);
|
Ada.Text_IO.Put (Text);
|
||||||
end Put;
|
end Put;
|
||||||
|
|
||||||
procedure Put (Number : Natural) is
|
procedure Put (Number : Natural)
|
||||||
|
with
|
||||||
|
Annotate => (GNATprove, Might_Not_Return)
|
||||||
|
is
|
||||||
begin
|
begin
|
||||||
Natural_IO.Put (Item => Number, Width => 0, Base => 10);
|
Natural_IO.Put (Item => Number, Width => 0, Base => 10);
|
||||||
end Put;
|
end Put;
|
||||||
|
|
||||||
procedure Put (Number : Byte_Index) is
|
procedure Put (Number : Byte_Index)
|
||||||
|
with
|
||||||
|
Annotate => (GNATprove, Might_Not_Return)
|
||||||
|
is
|
||||||
begin
|
begin
|
||||||
Natural_IO.Put (Item => Natural (Number), Width => 0, Base => 10);
|
Natural_IO.Put (Item => Natural (Number), Width => 0, Base => 10);
|
||||||
end Put;
|
end Put;
|
||||||
@@ -137,6 +143,7 @@ package body Tls_Client with SPARK_Mode is
|
|||||||
Output : WolfSSL.Write_Result;
|
Output : WolfSSL.Write_Result;
|
||||||
|
|
||||||
Result : WolfSSL.Subprogram_Result;
|
Result : WolfSSL.Subprogram_Result;
|
||||||
|
DTLS : Boolean;
|
||||||
begin
|
begin
|
||||||
Result := WolfSSL.Initialize;
|
Result := WolfSSL.Initialize;
|
||||||
if Result /= Success then
|
if Result /= Success then
|
||||||
@@ -144,14 +151,29 @@ package body Tls_Client with SPARK_Mode is
|
|||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if Argument_Count < 1 then
|
if Argument_Count < 1
|
||||||
Put_Line ("usage: tcl_client <IPv4 address>");
|
or Argument_Count > 2
|
||||||
|
or (Argument_Count = 2 and then Argument (2) /= "--dtls")
|
||||||
|
then
|
||||||
|
Put_Line ("usage: tls_client_main <IPv4 address> [--dtls]");
|
||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
SPARK_Sockets.Create_Socket (C);
|
|
||||||
|
DTLS := (SPARK_Terminal.Argument_Count = 2);
|
||||||
|
|
||||||
|
if DTLS then
|
||||||
|
SPARK_Sockets.Create_Datagram_Socket (C);
|
||||||
|
else
|
||||||
|
SPARK_Sockets.Create_Stream_Socket (C);
|
||||||
|
end if;
|
||||||
|
|
||||||
if not C.Exists then
|
if not C.Exists then
|
||||||
Put_Line ("ERROR: Failed to create socket.");
|
declare
|
||||||
return;
|
Mode : constant String := (if DTLS then "datagram" else "stream");
|
||||||
|
begin
|
||||||
|
Put_Line ("ERROR: Failed to create " & Mode & " socket.");
|
||||||
|
return;
|
||||||
|
end;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Addr := SPARK_Sockets.Inet_Addr (Argument (1));
|
Addr := SPARK_Sockets.Inet_Addr (Argument (1));
|
||||||
@@ -167,18 +189,26 @@ package body Tls_Client with SPARK_Mode is
|
|||||||
Addr => Addr.Addr,
|
Addr => Addr.Addr,
|
||||||
Port => P);
|
Port => P);
|
||||||
|
|
||||||
Result := SPARK_Sockets.Connect_Socket (Socket => C.Socket,
|
if not DTLS then
|
||||||
Server => A);
|
Result := SPARK_Sockets.Connect_Socket (Socket => C.Socket,
|
||||||
if Result /= Success then
|
Server => A);
|
||||||
Put_Line ("ERROR: Failed to connect to server.");
|
if Result /= Success then
|
||||||
SPARK_Sockets.Close_Socket (C);
|
Put_Line ("ERROR: Failed to connect to server.");
|
||||||
Set (Exit_Status_Failure);
|
SPARK_Sockets.Close_Socket (C);
|
||||||
return;
|
Set (Exit_Status_Failure);
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Create and initialize WOLFSSL_CTX.
|
-- Create and initialize WOLFSSL_CTX.
|
||||||
WolfSSL.Create_Context (Method => WolfSSL.TLSv1_3_Client_Method,
|
WolfSSL.Create_Context
|
||||||
Context => Ctx);
|
(Method =>
|
||||||
|
(if DTLS then
|
||||||
|
WolfSSL.DTLSv1_3_Client_Method
|
||||||
|
else
|
||||||
|
WolfSSL.TLSv1_3_Client_Method),
|
||||||
|
Context => Ctx);
|
||||||
|
|
||||||
if not WolfSSL.Is_Valid (Ctx) then
|
if not WolfSSL.Is_Valid (Ctx) then
|
||||||
Put_Line ("ERROR: failed to create WOLFSSL_CTX.");
|
Put_Line ("ERROR: failed to create WOLFSSL_CTX.");
|
||||||
SPARK_Sockets.Close_Socket (C);
|
SPARK_Sockets.Close_Socket (C);
|
||||||
@@ -186,6 +216,11 @@ package body Tls_Client with SPARK_Mode is
|
|||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
-- Require mutual authentication.
|
||||||
|
WolfSSL.Set_Verify
|
||||||
|
(Context => Ctx,
|
||||||
|
Mode => WolfSSL.Verify_Peer & WolfSSL.Verify_Fail_If_No_Peer_Cert);
|
||||||
|
|
||||||
-- Load client certificate into WOLFSSL_CTX.
|
-- Load client certificate into WOLFSSL_CTX.
|
||||||
Result := WolfSSL.Use_Certificate_File (Context => Ctx,
|
Result := WolfSSL.Use_Certificate_File (Context => Ctx,
|
||||||
File => CERT_FILE,
|
File => CERT_FILE,
|
||||||
@@ -241,6 +276,19 @@ package body Tls_Client with SPARK_Mode is
|
|||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
if DTLS then
|
||||||
|
Result := WolfSSL.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);
|
||||||
|
WolfSSL.Free (Ssl);
|
||||||
|
WolfSSL.Free (Context => Ctx);
|
||||||
|
Set (Exit_Status_Failure);
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
-- Attach wolfSSL to the socket.
|
-- Attach wolfSSL to the socket.
|
||||||
Result := WolfSSL.Attach (Ssl => Ssl,
|
Result := WolfSSL.Attach (Ssl => Ssl,
|
||||||
Socket => SPARK_Sockets.To_C (C.Socket));
|
Socket => SPARK_Sockets.To_C (C.Socket));
|
||||||
|
@@ -32,6 +32,7 @@ package Tls_Client with SPARK_Mode is
|
|||||||
Pre => (not Client.Exists and not
|
Pre => (not Client.Exists and not
|
||||||
WolfSSL.Is_Valid (Ssl) and not WolfSSL.Is_Valid (Ctx)),
|
WolfSSL.Is_Valid (Ssl) and not WolfSSL.Is_Valid (Ctx)),
|
||||||
Post => (not Client.Exists and not WolfSSL.Is_Valid (Ssl) and
|
Post => (not Client.Exists and not WolfSSL.Is_Valid (Ssl) and
|
||||||
not WolfSSL.Is_Valid (Ctx));
|
not WolfSSL.Is_Valid (Ctx)),
|
||||||
|
Annotate => (GNATprove, Might_Not_Return);
|
||||||
|
|
||||||
end Tls_Client;
|
end Tls_Client;
|
||||||
|
@@ -105,6 +105,7 @@ package body Tls_Server with SPARK_Mode is
|
|||||||
Ch : Character;
|
Ch : Character;
|
||||||
|
|
||||||
Result : WolfSSL.Subprogram_Result;
|
Result : WolfSSL.Subprogram_Result;
|
||||||
|
DTLS : Boolean;
|
||||||
Shall_Continue : Boolean := True;
|
Shall_Continue : Boolean := True;
|
||||||
|
|
||||||
Input : WolfSSL.Read_Result;
|
Input : WolfSSL.Read_Result;
|
||||||
@@ -117,12 +118,31 @@ package body Tls_Server with SPARK_Mode is
|
|||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
SPARK_Sockets.Create_Socket (Socket => L);
|
if SPARK_Terminal.Argument_Count > 1
|
||||||
if not L.Exists then
|
or (SPARK_Terminal.Argument_Count = 1
|
||||||
Put_Line ("ERROR: Failed to create socket.");
|
and then SPARK_Terminal.Argument (1) /= "--dtls")
|
||||||
|
then
|
||||||
|
Put_Line ("usage: tls_server_main [--dtls]");
|
||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
DTLS := (SPARK_Terminal.Argument_Count = 1);
|
||||||
|
|
||||||
|
if DTLS then
|
||||||
|
SPARK_Sockets.Create_Datagram_Socket (Socket => L);
|
||||||
|
else
|
||||||
|
SPARK_Sockets.Create_Stream_Socket (Socket => L);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if not L.Exists then
|
||||||
|
declare
|
||||||
|
Mode : constant String := (if DTLS then "datagram" else "stream");
|
||||||
|
begin
|
||||||
|
Put_Line ("ERROR: Failed to create " & Mode & " socket.");
|
||||||
|
return;
|
||||||
|
end;
|
||||||
|
end if;
|
||||||
|
|
||||||
Option := (Name => Reuse_Address, Enabled => True);
|
Option := (Name => Reuse_Address, Enabled => True);
|
||||||
Result := SPARK_Sockets.Set_Socket_Option (Socket => L.Socket,
|
Result := SPARK_Sockets.Set_Socket_Option (Socket => L.Socket,
|
||||||
Level => Socket_Level,
|
Level => Socket_Level,
|
||||||
@@ -144,17 +164,32 @@ package body Tls_Server with SPARK_Mode is
|
|||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Result := SPARK_Sockets.Listen_Socket (Socket => L.Socket,
|
if DTLS then
|
||||||
Length => 5);
|
Result := SPARK_Sockets.Receive_Socket (Socket => L.Socket);
|
||||||
|
else
|
||||||
|
Result := SPARK_Sockets.Listen_Socket (Socket => L.Socket,
|
||||||
|
Length => 5);
|
||||||
|
end if;
|
||||||
|
|
||||||
if Result /= Success then
|
if Result /= Success then
|
||||||
Put_Line ("ERROR: Failed to configure listener socket.");
|
declare
|
||||||
SPARK_Sockets.Close_Socket (L);
|
Operation : constant String := (if DTLS then "receiver" else "listener");
|
||||||
return;
|
begin
|
||||||
|
Put_Line ("ERROR: Failed to configure " & Operation & " socket.");
|
||||||
|
SPARK_Sockets.Close_Socket (L);
|
||||||
|
return;
|
||||||
|
end;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Create and initialize WOLFSSL_CTX.
|
-- Create and initialize WOLFSSL_CTX.
|
||||||
WolfSSL.Create_Context (Method => WolfSSL.TLSv1_3_Server_Method,
|
WolfSSL.Create_Context
|
||||||
Context => Ctx);
|
(Method =>
|
||||||
|
(if DTLS then
|
||||||
|
WolfSSL.DTLSv1_3_Server_Method
|
||||||
|
else
|
||||||
|
WolfSSL.TLSv1_3_Server_Method),
|
||||||
|
Context => Ctx);
|
||||||
|
|
||||||
if not WolfSSL.Is_Valid (Ctx) then
|
if not WolfSSL.Is_Valid (Ctx) then
|
||||||
Put_Line ("ERROR: failed to create WOLFSSL_CTX.");
|
Put_Line ("ERROR: failed to create WOLFSSL_CTX.");
|
||||||
SPARK_Sockets.Close_Socket (L);
|
SPARK_Sockets.Close_Socket (L);
|
||||||
@@ -217,16 +252,18 @@ package body Tls_Server with SPARK_Mode is
|
|||||||
pragma Loop_Invariant (not WolfSSL.Is_Valid (Ssl));
|
pragma Loop_Invariant (not WolfSSL.Is_Valid (Ssl));
|
||||||
pragma Loop_Invariant (WolfSSL.Is_Valid (Ctx));
|
pragma Loop_Invariant (WolfSSL.Is_Valid (Ctx));
|
||||||
|
|
||||||
Put_Line ("Waiting for a connection...");
|
if not DTLS then
|
||||||
SPARK_Sockets.Accept_Socket (Server => L.Socket,
|
Put_Line ("Waiting for a connection...");
|
||||||
Socket => C,
|
SPARK_Sockets.Accept_Socket (Server => L.Socket,
|
||||||
Address => A,
|
Socket => C,
|
||||||
Result => Result);
|
Address => A,
|
||||||
if Result /= Success then
|
Result => Result);
|
||||||
Put_Line ("ERROR: failed to accept the connection.");
|
if Result /= Success then
|
||||||
SPARK_Sockets.Close_Socket (L);
|
Put_Line ("ERROR: failed to accept the connection.");
|
||||||
WolfSSL.Free (Context => Ctx);
|
SPARK_Sockets.Close_Socket (L);
|
||||||
return;
|
WolfSSL.Free (Context => Ctx);
|
||||||
|
return;
|
||||||
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Create a WOLFSSL object.
|
-- Create a WOLFSSL object.
|
||||||
@@ -234,32 +271,45 @@ package body Tls_Server with SPARK_Mode is
|
|||||||
if not WolfSSL.Is_Valid (Ssl) then
|
if not WolfSSL.Is_Valid (Ssl) then
|
||||||
Put_Line ("ERROR: failed to create WOLFSSL object.");
|
Put_Line ("ERROR: failed to create WOLFSSL object.");
|
||||||
SPARK_Sockets.Close_Socket (L);
|
SPARK_Sockets.Close_Socket (L);
|
||||||
SPARK_Sockets.Close_Socket (C);
|
|
||||||
|
if not DTLS then
|
||||||
|
SPARK_Sockets.Close_Socket (C);
|
||||||
|
end if;
|
||||||
|
|
||||||
WolfSSL.Free (Context => Ctx);
|
WolfSSL.Free (Context => Ctx);
|
||||||
Set (Exit_Status_Failure);
|
Set (Exit_Status_Failure);
|
||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Attach wolfSSL to the socket.
|
-- Attach wolfSSL to the socket.
|
||||||
Result := WolfSSL.Attach (Ssl => Ssl,
|
Result := WolfSSL.Attach
|
||||||
Socket => SPARK_Sockets.To_C (C.Socket));
|
(Ssl => Ssl,
|
||||||
|
Socket => SPARK_Sockets.To_C (if DTLS then L.Socket else C.Socket));
|
||||||
if Result /= Success then
|
if Result /= Success then
|
||||||
Put_Line ("ERROR: Failed to set the file descriptor.");
|
Put_Line ("ERROR: Failed to set the file descriptor.");
|
||||||
WolfSSL.Free (Ssl);
|
WolfSSL.Free (Ssl);
|
||||||
SPARK_Sockets.Close_Socket (L);
|
SPARK_Sockets.Close_Socket (L);
|
||||||
SPARK_Sockets.Close_Socket (C);
|
|
||||||
|
if not DTLS then
|
||||||
|
SPARK_Sockets.Close_Socket (C);
|
||||||
|
end if;
|
||||||
|
|
||||||
WolfSSL.Free (Context => Ctx);
|
WolfSSL.Free (Context => Ctx);
|
||||||
Set (Exit_Status_Failure);
|
Set (Exit_Status_Failure);
|
||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Establish TLS connection.
|
-- Establish (D)TLS connection.
|
||||||
Result := WolfSSL.Accept_Connection (Ssl);
|
Result := WolfSSL.Accept_Connection (Ssl);
|
||||||
if Result /= Success then
|
if Result /= Success then
|
||||||
Put_Line ("Accept error.");
|
Put_Line ("Accept error.");
|
||||||
WolfSSL.Free (Ssl);
|
WolfSSL.Free (Ssl);
|
||||||
SPARK_Sockets.Close_Socket (L);
|
SPARK_Sockets.Close_Socket (L);
|
||||||
SPARK_Sockets.Close_Socket (C);
|
|
||||||
|
if not DTLS then
|
||||||
|
SPARK_Sockets.Close_Socket (C);
|
||||||
|
end if;
|
||||||
|
|
||||||
WolfSSL.Free (Context => Ctx);
|
WolfSSL.Free (Context => Ctx);
|
||||||
Set (Exit_Status_Failure);
|
Set (Exit_Status_Failure);
|
||||||
return;
|
return;
|
||||||
@@ -268,11 +318,15 @@ package body Tls_Server with SPARK_Mode is
|
|||||||
Put_Line ("Client connected successfully.");
|
Put_Line ("Client connected successfully.");
|
||||||
|
|
||||||
Input := WolfSSL.Read (Ssl);
|
Input := WolfSSL.Read (Ssl);
|
||||||
if not Input.Success then
|
if not Input.Success then
|
||||||
Put_Line ("Read error.");
|
Put_Line ("Read error.");
|
||||||
WolfSSL.Free (Ssl);
|
WolfSSL.Free (Ssl);
|
||||||
SPARK_Sockets.Close_Socket (L);
|
SPARK_Sockets.Close_Socket (L);
|
||||||
SPARK_Sockets.Close_Socket (C);
|
|
||||||
|
if not DTLS then
|
||||||
|
SPARK_Sockets.Close_Socket (C);
|
||||||
|
end if;
|
||||||
|
|
||||||
WolfSSL.Free (Context => Ctx);
|
WolfSSL.Free (Context => Ctx);
|
||||||
Set (Exit_Status_Failure);
|
Set (Exit_Status_Failure);
|
||||||
return;
|
return;
|
||||||
@@ -306,15 +360,24 @@ package body Tls_Server with SPARK_Mode is
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
for I in 1 .. 3 loop
|
for I in 1 .. 3 loop
|
||||||
|
|
||||||
Result := WolfSSL.Shutdown (Ssl);
|
Result := WolfSSL.Shutdown (Ssl);
|
||||||
exit when Result = Success;
|
|
||||||
|
exit when DTLS or Result = Success;
|
||||||
delay 0.001; -- Delay is expressed in seconds.
|
delay 0.001; -- Delay is expressed in seconds.
|
||||||
|
|
||||||
end loop;
|
end loop;
|
||||||
if Result /= Success then
|
if not DTLS and then Result /= Success then
|
||||||
Put_Line ("ERROR: Failed to shutdown WolfSSL context.");
|
Put_Line ("ERROR: Failed to shutdown WolfSSL context.");
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
WolfSSL.Free (Ssl);
|
WolfSSL.Free (Ssl);
|
||||||
SPARK_Sockets.Close_Socket (C);
|
|
||||||
|
if DTLS then
|
||||||
|
Shall_Continue := False;
|
||||||
|
else
|
||||||
|
SPARK_Sockets.Close_Socket (C);
|
||||||
|
end if;
|
||||||
|
|
||||||
Put_Line ("Shutdown complete.");
|
Put_Line ("Shutdown complete.");
|
||||||
end loop;
|
end loop;
|
||||||
|
@@ -75,13 +75,9 @@ extern "C" {
|
|||||||
#define WOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE
|
#define WOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE
|
||||||
|
|
||||||
/* DTLS */
|
/* DTLS */
|
||||||
#if 0
|
#define WOLFSSL_DTLS
|
||||||
#define WOLFSSL_DTLS
|
// #define WOLFSSL_MULTICAST
|
||||||
#define WOLFSSL_MULTICAST
|
#define WOLFSSL_DTLS13
|
||||||
|
|
||||||
/* DTLS v1.3 is not yet included with enable-all */
|
|
||||||
//#define WOLFSSL_DTLS13
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* DG Disabled SSLv3 and TLSv1.0 - should avoid using */
|
/* DG Disabled SSLv3 and TLSv1.0 - should avoid using */
|
||||||
//#define WOLFSSL_ALLOW_SSLV3
|
//#define WOLFSSL_ALLOW_SSLV3
|
||||||
|
@@ -19,7 +19,12 @@
|
|||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||||
--
|
--
|
||||||
|
|
||||||
|
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 Interfaces.C.Strings;
|
||||||
|
with System;
|
||||||
|
|
||||||
package body WolfSSL is
|
package body WolfSSL is
|
||||||
|
|
||||||
@@ -97,6 +102,46 @@ package body WolfSSL is
|
|||||||
return WolfTLSv1_3_Client_Method;
|
return WolfTLSv1_3_Client_Method;
|
||||||
end TLSv1_3_Client_Method;
|
end TLSv1_3_Client_Method;
|
||||||
|
|
||||||
|
function WolfDTLSv1_2_Server_Method return Method_Type with
|
||||||
|
Convention => C,
|
||||||
|
External_Name => "wolfDTLSv1_2_server_method",
|
||||||
|
Import => True;
|
||||||
|
|
||||||
|
function DTLSv1_2_Server_Method return Method_Type is
|
||||||
|
begin
|
||||||
|
return WolfDTLSv1_2_Server_Method;
|
||||||
|
end DTLSv1_2_Server_Method;
|
||||||
|
|
||||||
|
function WolfDTLSv1_2_Client_Method return Method_Type with
|
||||||
|
Convention => C,
|
||||||
|
External_Name => "wolfDTLSv1_2_client_method",
|
||||||
|
Import => True;
|
||||||
|
|
||||||
|
function DTLSv1_2_Client_Method return Method_Type is
|
||||||
|
begin
|
||||||
|
return WolfDTLSv1_2_Client_Method;
|
||||||
|
end DTLSv1_2_Client_Method;
|
||||||
|
|
||||||
|
function WolfDTLSv1_3_Server_Method return Method_Type with
|
||||||
|
Convention => C,
|
||||||
|
External_Name => "wolfDTLSv1_3_server_method",
|
||||||
|
Import => True;
|
||||||
|
|
||||||
|
function DTLSv1_3_Server_Method return Method_Type is
|
||||||
|
begin
|
||||||
|
return WolfDTLSv1_3_Server_Method;
|
||||||
|
end DTLSv1_3_Server_Method;
|
||||||
|
|
||||||
|
function WolfDTLSv1_3_Client_Method return Method_Type with
|
||||||
|
Convention => C,
|
||||||
|
External_Name => "wolfDTLSv1_3_client_method",
|
||||||
|
Import => True;
|
||||||
|
|
||||||
|
function DTLSv1_3_Client_Method return Method_Type is
|
||||||
|
begin
|
||||||
|
return WolfDTLSv1_3_Client_Method;
|
||||||
|
end DTLSv1_3_Client_Method;
|
||||||
|
|
||||||
function WolfSSL_CTX_new (Method : Method_Type)
|
function WolfSSL_CTX_new (Method : Method_Type)
|
||||||
return Context_Type with
|
return Context_Type with
|
||||||
Convention => C, External_Name => "wolfSSL_CTX_new", Import => True;
|
Convention => C, External_Name => "wolfSSL_CTX_new", Import => True;
|
||||||
@@ -487,6 +532,41 @@ package body WolfSSL is
|
|||||||
return Subprogram_Result (Result);
|
return Subprogram_Result (Result);
|
||||||
end Use_Private_Key_Buffer;
|
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;
|
||||||
|
|
||||||
function WolfSSL_Set_Fd (Ssl : WolfSSL_Type; Fd : int) return int with
|
function WolfSSL_Set_Fd (Ssl : WolfSSL_Type; Fd : int) return int with
|
||||||
Convention => C,
|
Convention => C,
|
||||||
External_Name => "wolfSSL_set_fd",
|
External_Name => "wolfSSL_set_fd",
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||||
--
|
--
|
||||||
|
|
||||||
|
with GNAT.Sockets;
|
||||||
with Interfaces.C;
|
with Interfaces.C;
|
||||||
|
|
||||||
-- This package is annotated "with SPARK_Mode" that SPARK can verify
|
-- This package is annotated "with SPARK_Mode" that SPARK can verify
|
||||||
@@ -70,6 +71,22 @@ package WolfSSL with SPARK_Mode is
|
|||||||
-- This function is used to indicate that the application is a client
|
-- This function is used to indicate that the application is a client
|
||||||
-- and will only support the TLS 1.3 protocol.
|
-- and will only support the TLS 1.3 protocol.
|
||||||
|
|
||||||
|
function DTLSv1_2_Server_Method return Method_Type;
|
||||||
|
-- This function is used to indicate that the application is a server
|
||||||
|
-- and will only support the DTLS 1.2 protocol.
|
||||||
|
|
||||||
|
function DTLSv1_2_Client_Method return Method_Type;
|
||||||
|
-- This function is used to indicate that the application is a client
|
||||||
|
-- and will only support the DTLS 1.2 protocol.
|
||||||
|
|
||||||
|
function DTLSv1_3_Server_Method return Method_Type;
|
||||||
|
-- This function is used to indicate that the application is a server
|
||||||
|
-- and will only support the DTLS 1.3 protocol.
|
||||||
|
|
||||||
|
function DTLSv1_3_Client_Method return Method_Type;
|
||||||
|
-- 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;
|
procedure Create_Context (Method : Method_Type;
|
||||||
Context : out Context_Type);
|
Context : out Context_Type);
|
||||||
-- This function creates a new SSL context, taking a desired SSL/TLS
|
-- This function creates a new SSL context, taking a desired SSL/TLS
|
||||||
@@ -270,6 +287,14 @@ package WolfSSL with SPARK_Mode is
|
|||||||
-- Format specifies the format type of the buffer; ASN1 or PEM.
|
-- Format specifies the format type of the buffer; ASN1 or PEM.
|
||||||
-- Please see the examples for proper usage.
|
-- 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.
|
||||||
|
|
||||||
function Attach (Ssl : WolfSSL_Type;
|
function Attach (Ssl : WolfSSL_Type;
|
||||||
Socket : Integer)
|
Socket : Integer)
|
||||||
return Subprogram_Result with
|
return Subprogram_Result with
|
||||||
|
Reference in New Issue
Block a user