Skip to content

Commit f49ffc0

Browse files
The implementations of the tls client and server applications can now be formally verified by the SPARK tools.
1 parent 45d8a5b commit f49ffc0

10 files changed

Lines changed: 603 additions & 145 deletions

wrapper/Ada/spark_sockets.adb

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
-- spark_sockets.adb
2+
--
3+
-- Copyright (C) 2006-2023 wolfSSL Inc.
4+
--
5+
-- This file is part of wolfSSL.
6+
--
7+
-- wolfSSL is free software; you can redistribute it and/or modify
8+
-- it under the terms of the GNU General Public License as published by
9+
-- the Free Software Foundation; either version 2 of the License, or
10+
-- (at your option) any later version.
11+
--
12+
-- wolfSSL is distributed in the hope that it will be useful,
13+
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
-- GNU General Public License for more details.
16+
--
17+
-- You should have received a copy of the GNU General Public License
18+
-- along with this program; if not, write to the Free Software
19+
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
--
21+
22+
with Interfaces.C;
23+
24+
package body SPARK_Sockets is
25+
26+
function Inet_Addr (Image : String) return Optional_Inet_Addr is
27+
A : Inet_Addr_Type;
28+
begin
29+
A := GNAT.Sockets.Inet_Addr (Image);
30+
return (Exists => True, Addr => A);
31+
exception
32+
when others =>
33+
return (Exists => False);
34+
end Inet_Addr;
35+
36+
procedure Create_Socket (Socket : in out Optional_Socket) is
37+
S : Socket_Type;
38+
begin
39+
GNAT.Sockets.Create_Socket (S);
40+
Socket := (Exists => True, Socket => S);
41+
exception
42+
when others =>
43+
Socket := (Exists => False);
44+
end Create_Socket;
45+
46+
function Connect_Socket (Socket : Socket_Type;
47+
Server : Sock_Addr_Type)
48+
return Subprogram_Result is
49+
begin
50+
GNAT.Sockets.Connect_Socket (Socket, Server);
51+
return Success;
52+
exception
53+
when others =>
54+
return Failure;
55+
end Connect_Socket;
56+
57+
function To_C (Socket : Socket_Type) return Integer is
58+
begin
59+
-- The call to GNAT.Sockets.To_C can never raise an exception.
60+
return GNAT.Sockets.To_C (Socket);
61+
end To_C;
62+
63+
procedure Close_Socket (Socket : in out Optional_Socket) is
64+
begin
65+
GNAT.Sockets.Close_Socket (Socket.Socket);
66+
Socket := (Exists => False);
67+
end Close_Socket;
68+
69+
function Set_Socket_Option (Socket : Socket_Type;
70+
Level : Level_Type;
71+
Option : Option_Type)
72+
return Subprogram_Result is
73+
begin
74+
GNAT.Sockets.Set_Socket_Option (Socket, Level, Option);
75+
return Success;
76+
exception
77+
when others =>
78+
return Failure;
79+
end Set_Socket_Option;
80+
81+
function Bind_Socket (Socket : Socket_Type;
82+
Address : Sock_Addr_Type)
83+
return Subprogram_Result is
84+
begin
85+
GNAT.Sockets.Bind_Socket (Socket, Address);
86+
return Success;
87+
exception
88+
when others =>
89+
return Failure;
90+
end Bind_Socket;
91+
92+
function Listen_Socket (Socket : Socket_Type;
93+
Length : Natural) return Subprogram_Result is
94+
begin
95+
GNAT.Sockets.Listen_Socket (Socket, Length);
96+
return Success;
97+
exception
98+
when others =>
99+
return Failure;
100+
end Listen_Socket;
101+
102+
procedure Accept_Socket (Server : Socket_Type;
103+
Socket : out Optional_Socket;
104+
Address : out Sock_Addr_Type;
105+
Result : out Subprogram_Result) is
106+
C : Socket_Type;
107+
begin
108+
GNAT.Sockets.Accept_Socket (Server, C, Address);
109+
Socket := (Exists => True, Socket => C);
110+
Result := Success;
111+
exception
112+
when others =>
113+
Socket := (Exists => False);
114+
Address := (Family => GNAT.Sockets.Family_Unspec);
115+
Result := Failure;
116+
end Accept_Socket;
117+
118+
procedure To_C (Item : String;
119+
Target : out Byte_Array;
120+
Count : out Byte_Index) is
121+
begin
122+
Interfaces.C.To_C (Item => Item,
123+
Target => Target,
124+
Count => Count,
125+
Append_Nul => False);
126+
end To_C;
127+
128+
procedure To_Ada (Item : Byte_Array;
129+
Target : out String;
130+
Count : out Natural) is
131+
begin
132+
Interfaces.C.To_Ada (Item => Item,
133+
Target => Target,
134+
Count => Count,
135+
Trim_Nul => False);
136+
end To_Ada;
137+
138+
end SPARK_Sockets;

wrapper/Ada/spark_sockets.ads

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
-- spark_sockets.ads
2+
--
3+
-- Copyright (C) 2006-2023 wolfSSL Inc.
4+
--
5+
-- This file is part of wolfSSL.
6+
--
7+
-- wolfSSL is free software; you can redistribute it and/or modify
8+
-- it under the terms of the GNU General Public License as published by
9+
-- the Free Software Foundation; either version 2 of the License, or
10+
-- (at your option) any later version.
11+
--
12+
-- wolfSSL is distributed in the hope that it will be useful,
13+
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
-- GNU General Public License for more details.
16+
--
17+
-- You should have received a copy of the GNU General Public License
18+
-- along with this program; if not, write to the Free Software
19+
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
--
21+
22+
-- GNAT Library packages.
23+
with GNAT.Sockets;
24+
25+
-- The WolfSSL package.
26+
with WolfSSL;
27+
28+
-- This is a wrapper package around the GNAT.Sockets package.
29+
-- GNAT.Sockets raises exceptions to signal errors but exceptions
30+
-- are not supported by SPARK. This package converts raised exceptions
31+
-- into returned enumeration values by functions indicating success
32+
-- or failure.
33+
--
34+
-- The intended use of this package is to demonstrate the usage
35+
-- of the WolfSSL Ada binding in Ada/SPARK code.
36+
package SPARK_Sockets with SPARK_Mode is
37+
38+
subtype Byte_Array is WolfSSL.Byte_Array;
39+
subtype Byte_Index is WolfSSL.Byte_Index; use type Byte_Index;
40+
41+
subtype Port_Type is GNAT.Sockets.Port_Type;
42+
43+
subtype Level_Type is GNAT.Sockets.Level_Type;
44+
45+
subtype Socket_Type is GNAT.Sockets.Socket_Type;
46+
subtype Option_Name is GNAT.Sockets.Option_Name;
47+
subtype Option_Type is GNAT.Sockets.Option_Type;
48+
subtype Family_Type is GNAT.Sockets.Family_Type;
49+
50+
subtype Sock_Addr_Type is GNAT.Sockets.Sock_Addr_Type;
51+
subtype Inet_Addr_Type is GNAT.Sockets.Inet_Addr_Type;
52+
53+
Socket_Error : exception renames GNAT.Sockets.Socket_Error;
54+
55+
Reuse_Address : Option_Name renames GNAT.Sockets.Reuse_Address;
56+
57+
Socket_Level : Level_Type renames GNAT.Sockets.Socket_Level;
58+
59+
Family_Inet : Family_Type renames GNAT.Sockets.Family_Inet;
60+
use type GNAT.Sockets.Family_Type;
61+
62+
Any_Inet_Addr : Inet_Addr_Type renames GNAT.Sockets.Any_Inet_Addr;
63+
64+
subtype Subprogram_Result is WolfSSL.Subprogram_Result;
65+
use type Subprogram_Result;
66+
67+
Success : Subprogram_Result renames WolfSSL.Success;
68+
Failure : Subprogram_Result renames WolfSSL.Failure;
69+
70+
type Optional_Inet_Addr (Exists : Boolean := False) is record
71+
case Exists is
72+
when True => Addr : Inet_Addr_Type;
73+
when False => null;
74+
end case;
75+
end record;
76+
77+
function Inet_Addr (Image : String) return Optional_Inet_Addr;
78+
79+
type Optional_Socket (Exists : Boolean := False) is record
80+
case Exists is
81+
when True => Socket : Socket_Type;
82+
when False => null;
83+
end case;
84+
end record;
85+
86+
procedure Create_Socket (Socket : in out Optional_Socket) with
87+
Pre => not Socket.Exists;
88+
89+
function Connect_Socket (Socket : Socket_Type;
90+
Server : Sock_Addr_Type)
91+
return Subprogram_Result;
92+
93+
function To_C (Socket : Socket_Type) return Integer with Inline;
94+
95+
-- Close a socket and more specifically a non-connected socket.
96+
procedure Close_Socket (Socket : in out Optional_Socket) with
97+
Pre => Socket.Exists,
98+
Post => not Socket.Exists;
99+
100+
function Set_Socket_Option (Socket : Socket_Type;
101+
Level : Level_Type;
102+
Option : Option_Type)
103+
return Subprogram_Result;
104+
-- Manipulate socket options.
105+
106+
function Bind_Socket (Socket : Socket_Type;
107+
Address : Sock_Addr_Type)
108+
return Subprogram_Result;
109+
110+
function Listen_Socket (Socket : Socket_Type;
111+
Length : Natural) return Subprogram_Result;
112+
-- To accept connections, a socket is first created with
113+
-- Create_Socket, a willingness to accept incoming connections and
114+
-- a queue Length for incoming connections are specified.
115+
-- The queue length of 15 is an example value that should be
116+
-- appropriate in usual cases. It can be adjusted according to each
117+
-- application's particular requirements.
118+
119+
procedure Accept_Socket (Server : Socket_Type;
120+
Socket : out Optional_Socket;
121+
Address : out Sock_Addr_Type;
122+
Result : out Subprogram_Result) with
123+
Post => (if Result = Success then Socket.Exists else not Socket.Exists);
124+
125+
procedure To_C (Item : String;
126+
Target : out Byte_Array;
127+
Count : out Byte_Index) with
128+
Pre => Item'Length <= Target'Length,
129+
Post => Count <= Target'Last;
130+
131+
procedure To_Ada (Item : Byte_Array;
132+
Target : out String;
133+
Count : out Natural) with
134+
Pre => Item'Length <= Target'Length,
135+
Post => Count <= Target'Last;
136+
137+
end SPARK_Sockets;

wrapper/Ada/spark_terminal.adb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package body SPARK_Terminal is
2+
3+
procedure Set_Exit_Status (Status : Exit_Status) is
4+
begin
5+
Ada.Command_Line.Set_Exit_Status (Status);
6+
end Set_Exit_Status;
7+
8+
function Argument_Count return Natural is
9+
begin
10+
return Ada.Command_Line.Argument_Count;
11+
end Argument_Count;
12+
13+
function Argument (Number : Positive) return String is
14+
begin
15+
return Ada.Command_Line.Argument (Number);
16+
end Argument;
17+
18+
end SPARK_Terminal;

wrapper/Ada/spark_terminal.ads

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
-- spark_sockets.ads
2+
--
3+
-- Copyright (C) 2006-2023 wolfSSL Inc.
4+
--
5+
-- This file is part of wolfSSL.
6+
--
7+
-- wolfSSL is free software; you can redistribute it and/or modify
8+
-- it under the terms of the GNU General Public License as published by
9+
-- the Free Software Foundation; either version 2 of the License, or
10+
-- (at your option) any later version.
11+
--
12+
-- wolfSSL is distributed in the hope that it will be useful,
13+
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
-- GNU General Public License for more details.
16+
--
17+
-- You should have received a copy of the GNU General Public License
18+
-- along with this program; if not, write to the Free Software
19+
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
--
21+
22+
with Ada.Command_Line;
23+
24+
-- SPARK wrapper package around Ada.Command_Line and Interfaces.C
25+
-- packages because these packages lack contracts in their specification
26+
-- files that SPARK can use to verify the context in which
27+
-- subprograms can safely be called.
28+
package SPARK_Terminal with SPARK_Mode is
29+
30+
subtype Exit_Status is Ada.Command_Line.Exit_Status;
31+
32+
Exit_Status_Success : Exit_Status renames Ada.Command_Line.Success;
33+
Exit_Status_Failure : Exit_Status renames Ada.Command_Line.Failure;
34+
35+
procedure Set_Exit_Status (Status : Exit_Status) with
36+
Global => null;
37+
38+
function Argument_Count return Natural;
39+
40+
function Argument (Number : Positive) return String with
41+
Pre => Number <= Argument_Count;
42+
43+
end SPARK_Terminal;

0 commit comments

Comments
 (0)