2323with Ada.Characters.Handling ;
2424with Ada.Strings.Bounded ;
2525with Ada.Text_IO ;
26- with Interfaces.C ;
26+ with Ada.Directories ;
27+ with Interfaces.C.Strings ;
2728
2829with SPARK_Terminal ;
2930
@@ -40,8 +41,62 @@ package body Tls_Client with SPARK_Mode is
4041
4142 subtype Byte_Type is WolfSSL.Byte_Type;
4243
44+ subtype chars_ptr is WolfSSL.chars_ptr;
45+ subtype unsigned is WolfSSL.unsigned;
46+
4347 package Natural_IO is new Ada.Text_IO.Integer_IO (Natural);
4448
49+ function PSK_Client_Callback
50+ (Unused : WolfSSL.WolfSSL_Type;
51+ Hint : chars_ptr;
52+ Identity : chars_ptr;
53+ Id_Max_Length : unsigned;
54+ Key : chars_ptr;
55+ Key_Max_Length : unsigned) return unsigned
56+ with Convention => C;
57+
58+ function PSK_Client_Callback
59+ (Unused : WolfSSL.WolfSSL_Type;
60+ Hint : chars_ptr;
61+ Identity : chars_ptr;
62+ Id_Max_Length : unsigned;
63+ Key : chars_ptr;
64+ Key_Max_Length : unsigned) return unsigned
65+ with
66+ SPARK_Mode => Off
67+ is
68+ use type Interfaces.C.unsigned;
69+
70+ Hint_String : constant String := Interfaces.C.Strings.Value (Hint);
71+ Identity_String : constant String := " Client_identity" ;
72+ Key_String : constant String :=
73+ Character'Val (26 )
74+ & Character'Val (43 )
75+ & Character'Val (60 )
76+ & Character'Val (77 );
77+ begin
78+
79+ Ada.Text_IO.Put_Line (" Hint: " & Hint_String);
80+
81+ pragma Assert (Id_Max_Length >= Identity_String'Length);
82+
83+ Interfaces.C.Strings.Update
84+ (Item => Identity,
85+ Offset => 0 ,
86+ Str => Identity_String,
87+ Check => False);
88+
89+ pragma Assert (Key_Max_Length >= Key_String'Length);
90+
91+ Interfaces.C.Strings.Update
92+ (Item => Key,
93+ Offset => 0 ,
94+ Str => Key_String,
95+ Check => False);
96+
97+ return Key_String'Length;
98+ end PSK_Client_Callback ;
99+
45100 procedure Put (Text : String) is
46101 begin
47102 Ada.Text_IO.Put (Text);
@@ -221,49 +276,53 @@ package body Tls_Client with SPARK_Mode is
221276 (Context => Ctx,
222277 Mode => WolfSSL.Verify_Peer or WolfSSL.Verify_Fail_If_No_Peer_Cert);
223278
224- -- Load client certificate into WOLFSSL_CTX.
225- Result := WolfSSL.Use_Certificate_File (Context => Ctx,
226- File => CERT_FILE,
227- Format => WolfSSL.Format_Pem);
228- if Result /= Success then
229- Put (" ERROR: failed to load " );
230- Put (CERT_FILE);
231- Put (" , please check the file." );
232- New_Line;
233- SPARK_Sockets.Close_Socket (C);
234- WolfSSL.Free (Context => Ctx);
235- Set (Exit_Status_Failure);
236- return ;
237- end if ;
279+ if Ada.Directories.Exists (CERT_FILE) and then
280+ Ada.Directories.Exists (KEY_FILE) then
238281
239- -- Load client key into WOLFSSL_CTX.
240- Result := WolfSSL.Use_Private_Key_File (Context => Ctx,
241- File => KEY_FILE ,
242- Format => WolfSSL.Format_Pem);
243- if Result /= Success then
244- Put (" ERROR: failed to load " );
245- Put (KEY_FILE );
246- Put (" , please check the file." );
247- New_Line;
248- SPARK_Sockets.Close_Socket (C);
249- WolfSSL.Free (Context => Ctx);
250- Set (Exit_Status_Failure);
251- return ;
252- end if ;
282+ -- Load client certificate into WOLFSSL_CTX.
283+ Result := WolfSSL.Use_Certificate_File (Context => Ctx,
284+ File => CERT_FILE ,
285+ Format => WolfSSL.Format_Pem);
286+ if Result /= Success then
287+ Put (" ERROR: failed to load " );
288+ Put (CERT_FILE );
289+ Put (" , please check the file." );
290+ New_Line;
291+ SPARK_Sockets.Close_Socket (C);
292+ WolfSSL.Free (Context => Ctx);
293+ Set (Exit_Status_Failure);
294+ return ;
295+ end if ;
253296
254- -- Load CA certificate into WOLFSSL_CTX.
255- Result := WolfSSL.Load_Verify_Locations (Context => Ctx,
256- File => CA_FILE,
257- Path => " " );
258- if Result /= Success then
259- Put (" ERROR: failed to load " );
260- Put (CA_FILE);
261- Put (" , please check the file." );
262- New_Line;
263- SPARK_Sockets.Close_Socket (C);
264- WolfSSL.Free (Context => Ctx);
265- Set (Exit_Status_Failure);
266- return ;
297+ -- Load client key into WOLFSSL_CTX.
298+ Result := WolfSSL.Use_Private_Key_File (Context => Ctx,
299+ File => KEY_FILE,
300+ Format => WolfSSL.Format_Pem);
301+ if Result /= Success then
302+ Put (" ERROR: failed to load " );
303+ Put (KEY_FILE);
304+ Put (" , please check the file." );
305+ New_Line;
306+ SPARK_Sockets.Close_Socket (C);
307+ WolfSSL.Free (Context => Ctx);
308+ Set (Exit_Status_Failure);
309+ return ;
310+ end if ;
311+
312+ -- Load CA certificate into WOLFSSL_CTX.
313+ Result := WolfSSL.Load_Verify_Locations (Context => Ctx,
314+ File => CA_FILE,
315+ Path => " " );
316+ if Result /= Success then
317+ Put (" ERROR: failed to load " );
318+ Put (CA_FILE);
319+ Put (" , please check the file." );
320+ New_Line;
321+ SPARK_Sockets.Close_Socket (C);
322+ WolfSSL.Free (Context => Ctx);
323+ Set (Exit_Status_Failure);
324+ return ;
325+ end if ;
267326 end if ;
268327
269328 -- Create a WOLFSSL object.
@@ -276,6 +335,15 @@ package body Tls_Client with SPARK_Mode is
276335 return ;
277336 end if ;
278337
338+ if not (Ada.Directories.Exists (CERT_FILE) and then
339+ Ada.Directories.Exists (KEY_FILE)) then
340+
341+ -- Use PSK for authentication.
342+ WolfSSL.Set_PSK_Client_Callback
343+ (Ssl => Ssl,
344+ Callback => PSK_Client_Callback'Access );
345+ end if ;
346+
279347 if DTLS then
280348 Result := WolfSSL.DTLS_Set_Peer(Ssl => Ssl,
281349 Address => A);
0 commit comments