Skip to content

Commit 40d3bef

Browse files
Extend Ada bindings
Add Ada bindings for SHA-256, RSA sign/verify, and AES-CBC from wolfCrypt. Use XMALLOC/XFREE for dynamic allocation and add GNATprove ownership annotations to enable static leak detection. Refactor the Ada wrapper into a base package (wolfssl.ads) and a child package (wolfssl-full_runtime) to separate code that depends on Interfaces.C.Strings and GNAT.Sockets from zero-footprint-compatible code. Add standalone examples for SHA-256 hashing, RSA signature verification, and AES encryption under wrapper/Ada/examples/. Add AUnit test suites for SHA-256, RSA, and AES bindings under wrapper/Ada/tests/ with Valgrind suppressions and Alire integration. Move TLS client/server examples into wrapper/Ada/examples/src/ and update build files (default.gpr, examples.gpr, include.am) accordingly. Update CI (ada.yml) to build default.gpr, run AUnit tests, run the client-server examples, and run GNATprove. Co-authored-by: Joakim Strandberg <joakim@mequinox.se>
1 parent ca5b484 commit 40d3bef

47 files changed

Lines changed: 3723 additions & 555 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ end_of_line = lf
88
charset = utf-8
99
trim_trailing_whitespace = true
1010
insert_final_newline = true
11+
12+
[*.{ads,adb,gpr}]
13+
indent_size = 3

.github/workflows/ada.yml

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,59 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@master
1717

18-
- name: Install gnat
18+
- name: Install alire
19+
uses: alire-project/setup-alire@v5
20+
21+
- name: Install wolfssl Ada
22+
working-directory: ./wrapper/Ada
23+
run: alr install
24+
25+
- name: Build default.gpr
26+
working-directory: ./wrapper/Ada
27+
run: alr exec -- gprbuild default.gpr -j$(nproc)
28+
29+
- name: Run Ada wrapper tests
30+
working-directory: ./wrapper/Ada/tests
31+
run: alr run
32+
33+
- name: Run Ada examples
34+
id: examples
35+
working-directory: ./wrapper/Ada/examples
1936
run: |
20-
sudo apt-get update
21-
sudo apt-get install -y gnat gprbuild
37+
alr build
38+
39+
echo "Running sha256_main example..."
40+
alr run sha256_main
2241
23-
- name: Checkout wolfssl
24-
uses: actions/checkout@master
25-
with:
26-
repository: wolfssl/wolfssl
27-
path: wolfssl
42+
echo "Running aes_verify_main example..."
43+
alr run aes_verify_main
2844
29-
- name: Build wolfssl Ada
30-
working-directory: ./wolfssl/wrapper/Ada
45+
echo "Running rsa_verify_main example..."
46+
alr run rsa_verify_main
47+
48+
echo "Running TLS server/client example..."
49+
alr run tls_server_main &> server.log &
50+
SERVER_PID=$!
51+
sleep 1
52+
echo "test message" | alr run tls_client_main --args=127.0.0.1
53+
kill $SERVER_PID || true
54+
55+
- name: show errors
56+
if: ${{ failure() && steps.examples.outcome == 'failure' }}
57+
run: cat ./wrapper/Ada/examples/server.log
58+
59+
- name: Run Ada wrapper tests (valgrind)
60+
working-directory: ./wrapper/Ada/tests
3161
run: |
32-
mkdir obj
33-
gprbuild default.gpr
34-
gprbuild examples.gpr
62+
sudo apt-get update
63+
sudo apt-get install -y valgrind
64+
valgrind --leak-check=full --error-exitcode=1 \
65+
--suppressions=valgrind.supp ./bin/tests
66+
67+
- name: Run gnatprove on wolfssl
68+
working-directory: ./wrapper/Ada
69+
run: alr gnatprove --level=4 -P wolfssl.gpr -j 0 --warnings=error --checks-as-errors --proof-warnings -U
70+
71+
- name: Run gnatprove on examples
72+
working-directory: ./wrapper/Ada/examples
73+
run: alr gnatprove --level=4 -P examples.gpr -j 0 --warnings=error --checks-as-errors --proof-warnings -U

wolfssl/wolfcrypt/types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,7 @@ enum {
13611361
DYNAMIC_TYPE_X509_ACERT = 103,
13621362
DYNAMIC_TYPE_OS_BUF = 104,
13631363
DYNAMIC_TYPE_ASCON = 105,
1364+
DYNAMIC_TYPE_SHA = 106,
13641365
DYNAMIC_TYPE_SNIFFER_SERVER = 1000,
13651366
DYNAMIC_TYPE_SNIFFER_SESSION = 1001,
13661367
DYNAMIC_TYPE_SNIFFER_PB = 1002,

wrapper/Ada/.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
obj
1+
/obj/
2+
/bin/
3+
/alire/
4+
/config/

wrapper/Ada/README.md

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ been developed with maximum portability in mind.
2828
Not only can the WolfSSL Ada binding be used in Ada applications but
2929
also SPARK applications (a subset of the Ada language suitable for
3030
formal verification). To formally verify the Ada code in this repository
31-
open the examples.gpr with GNAT Studio and then select
31+
open the examples/examples.gpr with GNAT Studio and then select
3232
SPARK -> Prove All Sources and use Proof Level 2. Or when using the command
33-
line, use `gnatprove -Pexamples.gpr --level=4 -j12` (`-j12` is there in
33+
line, use `gnatprove -Pexamples/examples.gpr --level=4 -j12` (`-j12` is there in
3434
order to instruct the prover to use 12 CPUs if available).
3535

3636
```
@@ -62,6 +62,8 @@ ecosystem. The latest version is available for Windows, OSX, Linux and FreeBSD
6262
systems. It can install a complete Ada toolchain if needed, see `alr install`
6363
for more information.
6464

65+
**Note:** If you encounter a missing dependency error, it may be caused by the installed dependency being too old. In this case, either install a newer toolchain or decrease the required dependency version in your project.
66+
6567
In order to use WolfSSL in a project, just add WolfSSL as a dependency by
6668
running `alr with wolfssl` within your project's directory.
6769

@@ -84,28 +86,48 @@ and use gprbuild to build the source code.
8486
cd wrapper/Ada
8587
gprclean
8688
gprbuild default.gpr
89+
90+
cd examples
8791
gprbuild examples.gpr
8892

8993
cd obj/
9094
./tls_server_main &
9195
./tls_client_main 127.0.0.1
9296
```
9397

98+
If you are using Alire, you can build the library and examples with:
99+
100+
```sh
101+
cd wrapper/Ada
102+
alr install
103+
104+
cd examples
105+
alr build
106+
```
107+
108+
You can also run the examples directly with Alire:
109+
110+
```sh
111+
cd wrapper/Ada/examples
112+
alr run tls_server_main &
113+
alr run tls_client_main --args=127.0.0.1
114+
```
115+
94116
On Windows, build the executables with:
95117
```sh
96-
gprbuild -XOS=Windows default.gpr
118+
cd wrapper/Ada/examples
97119
gprbuild -XOS=Windows examples.gpr
98120
```
99121

100122
## Files
101123
The (D)TLS v1.3 client example in the Ada/SPARK programming language
102124
using the WolfSSL library can be found in the files:
103-
tls_client_main.adb
104-
tls_client.ads
105-
tls_client.adb
125+
examples/src/tls_client_main.adb
126+
examples/src/tls_client.ads
127+
examples/src/tls_client.adb
106128

107129
The (D)TLS v1.3 server example in the Ada/SPARK programming language
108130
using the WolfSSL library can be found in the files:
109-
tls_server_main.adb
110-
tls_server.ads
111-
tls_server.adb
131+
examples/src/tls_server_main.adb
132+
examples/src/tls_server.ads
133+
examples/src/tls_server.adb

wrapper/Ada/ada_binding.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,15 @@
2626
/* wolfSSL */
2727
#include <wolfssl/wolfcrypt/settings.h>
2828
#include <wolfssl/ssl.h>
29+
#include <wolfssl/wolfcrypt/rsa.h>
30+
#include <wolfssl/wolfcrypt/sha256.h>
31+
#include <wolfssl/wolfcrypt/aes.h>
2932

33+
#include <stdlib.h>
34+
35+
/* RSA instances are now dynamically allocated (no fixed pool). */
36+
/* SHA256 instances are now dynamically allocated (no fixed pool). */
37+
/* AES instances are now dynamically allocated (no fixed pool). */
3038
/* These functions give access to the integer values of the enumeration
3139
constants used in WolfSSL. These functions make it possible
3240
for the WolfSSL implementation to change the values of the constants
@@ -48,6 +56,31 @@ extern int get_wolfssl_filetype_asn1(void);
4856
extern int get_wolfssl_filetype_pem(void);
4957
extern int get_wolfssl_filetype_default(void);
5058

59+
extern void* ada_new_rsa (void);
60+
extern void ada_free_rsa (void* key);
61+
62+
extern void *ada_new_sha256 (void);
63+
extern void ada_free_sha256 (void* sha256);
64+
65+
extern void* ada_new_aes (int devId);
66+
extern void ada_free_aes (void* aes);
67+
68+
extern void* ada_new_rng (void);
69+
extern void ada_free_rng (void* rng);
70+
extern int ada_RsaSetRNG (RsaKey* key, WC_RNG* rng);
71+
72+
extern int get_wolfssl_invalid_devid (void);
73+
74+
extern int ada_md5 (void);
75+
extern int ada_sha (void);
76+
extern int ada_sha256 (void);
77+
extern int ada_sha384 (void);
78+
extern int ada_sha512 (void);
79+
extern int ada_sha3_224 (void);
80+
extern int ada_sha3_256 (void);
81+
extern int ada_sha3_384 (void);
82+
extern int ada_sha3_512 (void);
83+
5184
extern int get_wolfssl_error_want_read(void) {
5285
return WOLFSSL_ERROR_WANT_READ;
5386
}
@@ -107,3 +140,111 @@ extern int get_wolfssl_filetype_pem(void) {
107140
extern int get_wolfssl_filetype_default(void) {
108141
return WOLFSSL_FILETYPE_DEFAULT;
109142
}
143+
144+
extern void* ada_new_rsa (void)
145+
{
146+
/* Allocate and initialize an RSA key using wolfCrypt's constructor. */
147+
return (void*)wc_NewRsaKey(NULL, INVALID_DEVID, NULL);
148+
}
149+
150+
extern void ada_free_rsa (void* key)
151+
{
152+
/* Delete RSA key and release its memory. */
153+
wc_DeleteRsaKey((RsaKey*)key, NULL);
154+
}
155+
156+
extern void* ada_new_sha256 (void)
157+
{
158+
return XMALLOC(sizeof(wc_Sha256), NULL, DYNAMIC_TYPE_SHA);
159+
}
160+
161+
extern void ada_free_sha256 (void* sha256)
162+
{
163+
XFREE(sha256, NULL, DYNAMIC_TYPE_SHA);
164+
}
165+
166+
167+
168+
extern void* ada_new_aes (int devId)
169+
{
170+
/* Allocate and initialize an AES object using wolfCrypt's constructor. */
171+
return (void*)wc_AesNew(NULL, devId, NULL);
172+
}
173+
174+
extern void ada_free_aes (void* aes)
175+
{
176+
/* Delete AES object and release its memory. */
177+
wc_AesDelete((Aes*)aes, NULL);
178+
}
179+
180+
extern int get_wolfssl_invalid_devid (void)
181+
{
182+
return INVALID_DEVID;
183+
}
184+
185+
extern void* ada_new_rng (void)
186+
{
187+
/* Allocate and initialize a WC_RNG using wolfCrypt's allocator.
188+
* Per request: pass NULL and 0 to wc_rng_new (nonce, nonceSz).
189+
*/
190+
return (void*)wc_rng_new(NULL, 0, NULL);
191+
}
192+
193+
extern void ada_free_rng (void* rng)
194+
{
195+
wc_rng_free((WC_RNG*)rng);
196+
}
197+
198+
extern int ada_RsaSetRNG(RsaKey* key, WC_RNG* rng)
199+
{
200+
int r = 0;
201+
#ifdef WC_RSA_BLINDING /* HIGHLY RECOMMENDED! */
202+
r = wc_RsaSetRNG(key, rng);
203+
#endif
204+
return r;
205+
}
206+
207+
extern int ada_md5 (void)
208+
{
209+
return WC_MD5;
210+
}
211+
212+
extern int ada_sha (void)
213+
{
214+
return WC_SHA;
215+
}
216+
217+
extern int ada_sha256 (void)
218+
{
219+
return WC_SHA256;
220+
}
221+
222+
extern int ada_sha384 (void)
223+
{
224+
return WC_SHA384;
225+
}
226+
227+
extern int ada_sha512 (void)
228+
{
229+
return WC_SHA512;
230+
}
231+
232+
extern int ada_sha3_224 (void)
233+
{
234+
return WC_SHA3_224;
235+
}
236+
237+
extern int ada_sha3_256 (void)
238+
{
239+
return WC_SHA3_256;
240+
}
241+
242+
extern int ada_sha3_384 (void)
243+
{
244+
return WC_SHA3_384;
245+
}
246+
247+
extern int ada_sha3_512 (void)
248+
{
249+
return WC_SHA3_512;
250+
}

wrapper/Ada/alire.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ tags = ["ssl", "tls", "embedded", "spark"]
1212

1313
[configuration.variables]
1414
STATIC_PSK = {type = "Boolean", default = false}
15+
16+
[[depends-on]]
17+
gnatprove = "^13.2.1"

wrapper/Ada/default.gpr

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,6 @@ project Default is
1111
"../../src",
1212
"../../wolfcrypt/src");
1313

14-
-- Don't build the tls application examples because they make use
15-
-- of the Secondary Stack due to usage of the Ada.Command_Line
16-
-- package. All other Ada source code does not use the secondary stack.
17-
for Excluded_Source_Files use
18-
("tls_client_main.adb",
19-
"tls_client.ads",
20-
"tls_client.adb",
21-
"tls_server_main.adb",
22-
"tls_server.ads",
23-
"tls_server.adb");
24-
2514
for Object_Dir use "obj";
2615

2716
package Naming is

0 commit comments

Comments
 (0)