1 /* wolfSSL-Example-IOCallbacks.cs
2  *
3  * Copyright (C) 2006-2021 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 
23 
24 using System;
25 using System.Collections.Generic;
26 using System.Linq;
27 using System.Text;
28 using System.Threading.Tasks;
29 using System.Net;
30 using System.Net.Sockets;
31 using System.Runtime.InteropServices;
32 using System.IO;
33 using wolfSSL.CSharp;
34 
35 
36 class wolfSSL_Example_IOCallbacks
37 {
38     /// <summary>
39     /// Example call back to allow receiving TLS information
40     /// </summary>
41     /// <param name="ssl">structure of ssl passed in</param>
42     /// <param name="buf">buffer to contain received msg</param>
43     /// <param name="sz">size of buffer for receiving</param>
44     /// <param name="ctx">information passed in from set_fd</param>
45     /// <returns>size of message received</returns>
wolfSSLCbIORecv(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx)46     private static int wolfSSLCbIORecv(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx)
47     {
48         if (sz <= 0)
49         {
50             wolfssl.log(wolfssl.ERROR_LOG, "wolfssl receive error, size less than 0");
51             return wolfssl.CBIO_ERR_GENERAL;
52         }
53 
54         int amtRecv = 0;
55 
56         try
57         {
58             System.Runtime.InteropServices.GCHandle gch;
59             gch = GCHandle.FromIntPtr(ctx);
60             Socket con = (System.Net.Sockets.Socket)gch.Target;
61 
62             Byte[] msg = new Byte[sz];
63             amtRecv = con.Receive(msg, msg.Length, 0);
64             Marshal.Copy(msg, 0, buf, sz);
65         }
66         catch (Exception e)
67         {
68             wolfssl.log(wolfssl.ENTER_LOG, "Error in receive " + e.ToString());
69             return wolfssl.CBIO_ERR_CONN_CLOSE;
70         }
71 
72         Console.WriteLine("Example custom receive got {0:D} bytes", amtRecv);
73         return amtRecv;
74     }
75 
76 
77     /// <summary>
78     /// Example call back used for sending TLS information
79     /// </summary>
80     /// <param name="ssl">pointer to ssl struct</param>
81     /// <param name="buf">buffer containing information to send</param>
82     /// <param name="sz">size of buffer to send</param>
83     /// <param name="ctx">object that was set as fd</param>
84     /// <returns>amount of information sent</returns>
wolfSSLCbIOSend(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx)85     private static int wolfSSLCbIOSend(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx)
86     {
87         if (sz <= 0)
88         {
89             wolfssl.log(wolfssl.ERROR_LOG, "wolfssl send error, size less than 0");
90             return wolfssl.CBIO_ERR_GENERAL;
91         }
92 
93         try
94         {
95             System.Runtime.InteropServices.GCHandle gch;
96             gch = GCHandle.FromIntPtr(ctx);
97             Socket con = (System.Net.Sockets.Socket)gch.Target;
98 
99             Byte[] msg = new Byte[sz];
100             Marshal.Copy(buf, msg, 0, sz);
101 
102             con.Send(msg, 0, msg.Length, SocketFlags.None);
103             Console.WriteLine("Example custom send sent {0:D} bytes", sz);
104             return sz;
105         }
106         catch (Exception e)
107         {
108             wolfssl.log(wolfssl.ERROR_LOG, "socket connection issue " + e.ToString());
109             return wolfssl.CBIO_ERR_CONN_CLOSE;
110         }
111     }
112 
113 
114     /// <summary>
115     /// Example of a PSK function call back
116     /// </summary>
117     /// <param name="ssl">pointer to ssl structure</param>
118     /// <param name="identity">identity of client connecting</param>
119     /// <param name="key">buffer to hold key</param>
120     /// <param name="max_key">max key size</param>
121     /// <returns>size of key set</returns>
my_psk_server_cb(IntPtr ssl, string identity, IntPtr key, uint max_key)122     public static uint my_psk_server_cb(IntPtr ssl, string identity, IntPtr key, uint max_key)
123     {
124         /* perform a check on the identity sent across
125          * log function must be set for print out of logging information
126          */
127         wolfssl.log(wolfssl.INFO_LOG, "PSK Client Identity = " + identity);
128 
129         /* Use desired key, note must be a key smaller than max key size parameter
130             Replace this with desired key. Is trivial one for testing */
131         if (max_key < 4)
132             return 0;
133         byte[] tmp = { 26, 43, 60, 77 };
134         Marshal.Copy(tmp, 0, key, 4);
135 
136         return (uint)4;
137     }
138 
139     /// <summary>
140     /// Example of a certificate verify function
141     /// </summary>
142     /// <param name="preverify"></param>
143     /// <param name="store">pointer to a WOLFSSL_X509_STORE_CTX</param>
144     /// <returns>size of key set</returns>
my_verify_cb(int preverify, IntPtr store)145     public static int my_verify_cb(int preverify, IntPtr store)
146     {
147         if (store == IntPtr.Zero)
148         {
149             Console.WriteLine("store is null");
150         }
151 
152         Console.WriteLine("Status of certificate verify = " + preverify);
153         Console.WriteLine("Error value for cert store is " + wolfssl.X509_STORE_CTX_get_error(store));
154 
155         /* look at the current cert in store */
156         try
157         {
158 
159             X509 x509 = wolfssl.X509_STORE_CTX_get_current_cert(store);
160 
161 
162             Console.WriteLine("Issuer : " + x509.Issuer);
163             Console.WriteLine("Subject : " + x509.Subject);
164 
165             Console.WriteLine("PEM of certificate:");
166             Console.WriteLine(System.Text.Encoding.UTF8.GetString(x509.Export()));
167 
168             Console.WriteLine("DER of certificate:");
169             Console.WriteLine(BitConverter.ToString(x509.Export(wolfssl.SSL_FILETYPE_ASN1)));
170 
171             Console.WriteLine("Public key:");
172             Console.WriteLine(BitConverter.ToString(x509.GetPublicKey()));
173         }
174         catch (Exception e)
175         {
176             Console.WriteLine("Unable to get X509's" + e);
177         }
178 
179         /* list all certs in store */
180         try
181         {
182             int i;
183             X509[] x509 = wolfssl.X509_STORE_CTX_get_certs(store);
184 
185             for (i = 0; i < x509.Length; i++)
186             {
187                 Console.WriteLine("CERT[" + i + "]");
188                 Console.WriteLine("Issuer : " + x509[i].Issuer);
189                 Console.WriteLine("Subject : " + x509[i].Subject);
190                 Console.WriteLine("");
191             }
192         }
193         catch (Exception e)
194         {
195             Console.WriteLine("Unable to get X509's" + e);
196         }
197 
198         /* by returning 1 here we override any failure and report success */
199         return preverify;
200     }
201 
clean(IntPtr ssl, IntPtr ctx)202     private static void clean(IntPtr ssl, IntPtr ctx)
203     {
204         wolfssl.free(ssl);
205         wolfssl.CTX_free(ctx);
206         wolfssl.Cleanup();
207     }
208 
209 
Main(string[] args)210     static void Main(string[] args)
211     {
212         IntPtr ctx;
213         IntPtr ssl;
214         Socket fd;
215 
216         wolfssl.psk_delegate psk_cb = new wolfssl.psk_delegate(my_psk_server_cb);
217         wolfssl.CallbackVerify_delegate verify_cb = new wolfssl.CallbackVerify_delegate(my_verify_cb);
218 
219         /* These paths should be changed according to use */
220         string fileCert = @"server-cert.pem";
221         string fileKey = @"server-key.pem";
222 
223         StringBuilder buff = new StringBuilder(1024);
224         StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper");
225 
226         wolfssl.Init();
227 
228         Console.WriteLine("Calling ctx Init from wolfSSL");
229         ctx = wolfssl.CTX_new(wolfssl.useTLSv1_2_server());
230         if (ctx == IntPtr.Zero)
231         {
232             Console.WriteLine("Error creating ctx structure");
233             return;
234         }
235         Console.WriteLine("Finished init of ctx .... now load in cert and key");
236 
237         if (!File.Exists(fileCert) || !File.Exists(fileKey))
238         {
239             Console.WriteLine("Could not find cert or key file");
240             wolfssl.CTX_free(ctx);
241             return;
242         }
243 
244         if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS)
245         {
246             Console.WriteLine("Error in setting cert file");
247             wolfssl.CTX_free(ctx);
248             return;
249         }
250 
251         if (wolfssl.CTX_use_PrivateKey_file(ctx, fileKey, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS)
252         {
253             Console.WriteLine("Error in setting key file");
254             wolfssl.CTX_free(ctx);
255             return;
256         }
257 
258         wolfssl.CTX_set_verify(ctx, wolfssl.SSL_VERIFY_PEER, verify_cb);
259 
260         /* Set using custom IO callbacks
261            delegate memory is allocated when calling SetIO**** function and freed with ctx free
262          */
263         wolfssl.SetIORecv(ctx, new wolfssl.CallbackIORecv_delegate(wolfSSLCbIORecv));
264         wolfssl.SetIOSend(ctx, new wolfssl.CallbackIOSend_delegate(wolfSSLCbIOSend));
265 
266         /* set up TCP socket */
267         IPAddress ip = IPAddress.Parse("0.0.0.0"); //bind to any
268         TcpListener tcp = new TcpListener(ip, 11111);
269         tcp.Start();
270 
271         Console.WriteLine("Started TCP and waiting for a connection");
272         fd = tcp.AcceptSocket();
273         ssl = wolfssl.new_ssl(ctx);
274 
275         Console.WriteLine("Connection made wolfSSL_accept ");
276         if (wolfssl.set_fd(ssl, fd) != wolfssl.SUCCESS)
277         {
278             /* get and print out the error */
279             Console.WriteLine(wolfssl.get_error(ssl));
280             tcp.Stop();
281             clean(ssl, ctx);
282             return;
283         }
284 
285         if (wolfssl.accept(ssl) != wolfssl.SUCCESS)
286         {
287             /* get and print out the error */
288             Console.WriteLine(wolfssl.get_error(ssl));
289             tcp.Stop();
290             clean(ssl, ctx);
291             return;
292         }
293 
294         /* print out results of TLS/SSL accept */
295         Console.WriteLine("SSL version is " + wolfssl.get_version(ssl));
296         Console.WriteLine("SSL cipher suite is " + wolfssl.get_current_cipher(ssl));
297 
298         /* read and print out the message then reply */
299         if (wolfssl.read(ssl, buff, 1023) < 0)
300         {
301             Console.WriteLine("Error in read");
302             tcp.Stop();
303             clean(ssl, ctx);
304             return;
305         }
306         Console.WriteLine(buff);
307 
308         if (wolfssl.write(ssl, reply, reply.Length) != reply.Length)
309         {
310             Console.WriteLine("Error in write");
311             tcp.Stop();
312             clean(ssl, ctx);
313             return;
314         }
315 
316         wolfssl.shutdown(ssl);
317         fd.Close();
318         tcp.Stop();
319         clean(ssl, ctx);
320     }
321 }
322