Skip to content

Commit 1f61ed3

Browse files
Merge pull request #7397 from dalybrown/expose-dtsl-in-ada
Expose DTLS in Ada wrapper and update examples
2 parents 73a85af + 707e60a commit 1f61ed3

11 files changed

Lines changed: 318 additions & 66 deletions

wrapper/Ada/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
obj

wrapper/Ada/README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
The source code for the Ada/SPARK binding of the WolfSSL library
33
is the WolfSSL Ada package in the wolfssl.ads and wolfssl.adb files.
44

5-
The source code here also demonstrates a TLS v1.3 server and client
5+
The source code here also demonstrates a (D)TLS v1.3 server and client
66
using the WolfSSL Ada binding. The implementation is cross-platform
77
and compiles on Linux, Mac OS X and Windows.
88

@@ -15,7 +15,8 @@ for the secondary stack. The GNAT User's Guide recommends
1515
avoiding the secondary stack using the restriction
1616
No_Secondary_Stack (see the GNAT configuration file gnat.adc
1717
which instructs compilation of the WolfSSL Ada binding under
18-
this restriction).
18+
this restriction). Note, however, that the examples do make use of the
19+
secondary stack.
1920

2021
Portability: The WolfSSL Ada binding makes no usage of controlled types
2122
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
9192
and use gprbuild to build the source code.
9293

9394
## Files
94-
The TLS v1.3 client example in the Ada/SPARK programming language
95+
The (D)TLS v1.3 client example in the Ada/SPARK programming language
9596
using the WolfSSL library can be found in the files:
9697
tls_client_main.adb
9798
tls_client.ads
9899
tls_client.adb
99100

100-
The TLS v1.3 server example in the Ada/SPARK programming language
101+
The (D)TLS v1.3 server example in the Ada/SPARK programming language
101102
using the WolfSSL library can be found in the files:
102103
tls_server_main.adb
103104
tls_server.ads

wrapper/Ada/default.gpr

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ project Default is
2626
for Spec_Suffix ("C") use ".h";
2727
end Naming;
2828

29-
package Builder is
30-
for Global_Configuration_Pragmas use "gnat.adc";
31-
end Builder;
32-
3329
package Compiler is
3430
for Switches ("C") use
3531
("-DWOLFSSL_USER_SETTINGS", -- Use the user_settings.h file.

wrapper/Ada/spark_sockets.adb

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
2020
--
2121

22+
with Ada.Streams;
2223
with Interfaces.C;
2324

2425
package body SPARK_Sockets is
@@ -33,16 +34,35 @@ package body SPARK_Sockets is
3334
return (Exists => False);
3435
end Inet_Addr;
3536

36-
procedure Create_Socket (Socket : in out Optional_Socket) is
37+
procedure Create_Socket
38+
(Socket : in out Optional_Socket;
39+
Family : GNAT.Sockets.Family_Type;
40+
Mode : GNAT.Sockets.Mode_Type) is
3741
S : Socket_Type;
3842
begin
39-
GNAT.Sockets.Create_Socket (S);
43+
GNAT.Sockets.Create_Socket (S, Family, Mode);
4044
Socket := (Exists => True, Socket => S);
4145
exception
4246
when others =>
4347
Socket := (Exists => False);
4448
end Create_Socket;
4549

50+
procedure Create_Stream_Socket (Socket : in out Optional_Socket) is
51+
begin
52+
Create_Socket
53+
(Socket => Socket,
54+
Family => GNAT.Sockets.Family_Inet,
55+
Mode => GNAT.Sockets.Socket_Stream);
56+
end Create_Stream_Socket;
57+
58+
procedure Create_Datagram_Socket (Socket : in out Optional_Socket) is
59+
begin
60+
Create_Socket
61+
(Socket => Socket,
62+
Family => GNAT.Sockets.Family_Inet,
63+
Mode => GNAT.Sockets.Socket_Datagram);
64+
end Create_Datagram_Socket;
65+
4666
function Connect_Socket (Socket : Socket_Type;
4767
Server : Sock_Addr_Type)
4868
return Subprogram_Result is
@@ -99,6 +119,22 @@ package body SPARK_Sockets is
99119
return Failure;
100120
end Listen_Socket;
101121

122+
function Receive_Socket
123+
(Socket : Socket_Type)
124+
return Subprogram_Result is
125+
126+
Item : Ada.Streams.Stream_Element_Array (1 .. 4096);
127+
Last : Ada.Streams.Stream_Element_Offset;
128+
From : GNAT.Sockets.Sock_Addr_Type;
129+
130+
begin
131+
GNAT.Sockets.Receive_Socket (Socket, Item, Last, From);
132+
return Success;
133+
exception
134+
when others =>
135+
return Failure;
136+
end Receive_Socket;
137+
102138
procedure Accept_Socket (Server : Socket_Type;
103139
Socket : out Optional_Socket;
104140
Address : out Sock_Addr_Type;

wrapper/Ada/spark_sockets.ads

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ package SPARK_Sockets with SPARK_Mode is
8383
end case;
8484
end record;
8585

86-
procedure Create_Socket (Socket : in out Optional_Socket) with
86+
procedure Create_Stream_Socket (Socket : in out Optional_Socket) with
87+
Pre => not Socket.Exists;
88+
89+
procedure Create_Datagram_Socket (Socket : in out Optional_Socket) with
8790
Pre => not Socket.Exists;
8891

8992
function Connect_Socket (Socket : Socket_Type;
@@ -116,6 +119,8 @@ package SPARK_Sockets with SPARK_Mode is
116119
-- appropriate in usual cases. It can be adjusted according to each
117120
-- application's particular requirements.
118121

122+
function Receive_Socket (Socket : Socket_Type) return Subprogram_Result;
123+
119124
procedure Accept_Socket (Server : Socket_Type;
120125
Socket : out Optional_Socket;
121126
Address : out Sock_Addr_Type;

wrapper/Ada/tls_client.adb

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,18 @@ package body Tls_Client with SPARK_Mode is
4747
Ada.Text_IO.Put (Text);
4848
end Put;
4949

50-
procedure Put (Number : Natural) is
50+
procedure Put (Number : Natural)
51+
with
52+
Annotate => (GNATprove, Might_Not_Return)
53+
is
5154
begin
5255
Natural_IO.Put (Item => Number, Width => 0, Base => 10);
5356
end Put;
5457

55-
procedure Put (Number : Byte_Index) is
58+
procedure Put (Number : Byte_Index)
59+
with
60+
Annotate => (GNATprove, Might_Not_Return)
61+
is
5662
begin
5763
Natural_IO.Put (Item => Natural (Number), Width => 0, Base => 10);
5864
end Put;
@@ -137,21 +143,37 @@ package body Tls_Client with SPARK_Mode is
137143
Output : WolfSSL.Write_Result;
138144

139145
Result : WolfSSL.Subprogram_Result;
146+
DTLS : Boolean;
140147
begin
141148
Result := WolfSSL.Initialize;
142149
if Result /= Success then
143150
Put_Line ("ERROR: Failed to initialize the WolfSSL library.");
144151
return;
145152
end if;
146153

147-
if Argument_Count < 1 then
148-
Put_Line ("usage: tcl_client <IPv4 address>");
154+
if Argument_Count < 1
155+
or Argument_Count > 2
156+
or (Argument_Count = 2 and then Argument (2) /= "--dtls")
157+
then
158+
Put_Line ("usage: tls_client_main <IPv4 address> [--dtls]");
149159
return;
150160
end if;
151-
SPARK_Sockets.Create_Socket (C);
161+
162+
DTLS := (SPARK_Terminal.Argument_Count = 2);
163+
164+
if DTLS then
165+
SPARK_Sockets.Create_Datagram_Socket (C);
166+
else
167+
SPARK_Sockets.Create_Stream_Socket (C);
168+
end if;
169+
152170
if not C.Exists then
153-
Put_Line ("ERROR: Failed to create socket.");
154-
return;
171+
declare
172+
Mode : constant String := (if DTLS then "datagram" else "stream");
173+
begin
174+
Put_Line ("ERROR: Failed to create " & Mode & " socket.");
175+
return;
176+
end;
155177
end if;
156178

157179
Addr := SPARK_Sockets.Inet_Addr (Argument (1));
@@ -167,25 +189,38 @@ package body Tls_Client with SPARK_Mode is
167189
Addr => Addr.Addr,
168190
Port => P);
169191

170-
Result := SPARK_Sockets.Connect_Socket (Socket => C.Socket,
171-
Server => A);
172-
if Result /= Success then
173-
Put_Line ("ERROR: Failed to connect to server.");
174-
SPARK_Sockets.Close_Socket (C);
175-
Set (Exit_Status_Failure);
176-
return;
192+
if not DTLS then
193+
Result := SPARK_Sockets.Connect_Socket (Socket => C.Socket,
194+
Server => A);
195+
if Result /= Success then
196+
Put_Line ("ERROR: Failed to connect to server.");
197+
SPARK_Sockets.Close_Socket (C);
198+
Set (Exit_Status_Failure);
199+
return;
200+
end if;
177201
end if;
178202

179203
-- Create and initialize WOLFSSL_CTX.
180-
WolfSSL.Create_Context (Method => WolfSSL.TLSv1_3_Client_Method,
181-
Context => Ctx);
204+
WolfSSL.Create_Context
205+
(Method =>
206+
(if DTLS then
207+
WolfSSL.DTLSv1_3_Client_Method
208+
else
209+
WolfSSL.TLSv1_3_Client_Method),
210+
Context => Ctx);
211+
182212
if not WolfSSL.Is_Valid (Ctx) then
183213
Put_Line ("ERROR: failed to create WOLFSSL_CTX.");
184214
SPARK_Sockets.Close_Socket (C);
185215
Set (Exit_Status_Failure);
186216
return;
187217
end if;
188218

219+
-- Require mutual authentication.
220+
WolfSSL.Set_Verify
221+
(Context => Ctx,
222+
Mode => WolfSSL.Verify_Peer & WolfSSL.Verify_Fail_If_No_Peer_Cert);
223+
189224
-- Load client certificate into WOLFSSL_CTX.
190225
Result := WolfSSL.Use_Certificate_File (Context => Ctx,
191226
File => CERT_FILE,
@@ -241,6 +276,19 @@ package body Tls_Client with SPARK_Mode is
241276
return;
242277
end if;
243278

279+
if DTLS then
280+
Result := WolfSSL.DTLS_Set_Peer(Ssl => Ssl,
281+
Address => A);
282+
if Result /= Success then
283+
Put_Line ("ERROR: Failed to set the DTLS peer.");
284+
SPARK_Sockets.Close_Socket (C);
285+
WolfSSL.Free (Ssl);
286+
WolfSSL.Free (Context => Ctx);
287+
Set (Exit_Status_Failure);
288+
return;
289+
end if;
290+
end if;
291+
244292
-- Attach wolfSSL to the socket.
245293
Result := WolfSSL.Attach (Ssl => Ssl,
246294
Socket => SPARK_Sockets.To_C (C.Socket));

wrapper/Ada/tls_client.ads

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ package Tls_Client with SPARK_Mode is
3232
Pre => (not Client.Exists and not
3333
WolfSSL.Is_Valid (Ssl) and not WolfSSL.Is_Valid (Ctx)),
3434
Post => (not Client.Exists and not WolfSSL.Is_Valid (Ssl) and
35-
not WolfSSL.Is_Valid (Ctx));
35+
not WolfSSL.Is_Valid (Ctx)),
36+
Annotate => (GNATprove, Might_Not_Return);
3637

3738
end Tls_Client;

0 commit comments

Comments
 (0)