@@ -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));
0 commit comments